From 794b00805e46266dbe8eef451d7fdb2fe72c8d39 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 27 Dec 2014 22:14:23 +0100 Subject: [PATCH 01/83] Add man pages for the majority of utilities --- doc/man/bam-info.1 | 21 ++ doc/man/bam2egg.1 | 31 +++ doc/man/dae2egg.1 | 75 +++++++ doc/man/dxf-points.1 | 16 ++ doc/man/dxf2egg.1 | 72 +++++++ doc/man/egg-crop.1 | 32 +++ doc/man/egg-list-textures.1 | 21 ++ doc/man/egg-make-tube.1 | 77 ++++++++ doc/man/egg-mkfont.1 | 76 +++++++ doc/man/egg-optchar.1 | 150 ++++++++++++++ doc/man/egg-palettize.1 | 91 +++++++++ doc/man/egg-qtess.1 | 76 +++++++ doc/man/egg-rename.1 | 42 ++++ doc/man/egg-retarget-anim.1 | 66 +++++++ doc/man/egg-texture-cards.1 | 81 ++++++++ doc/man/egg-topstrip.1 | 75 +++++++ doc/man/egg-trans.1 | 117 +++++++++++ doc/man/egg2bam.1 | 81 ++++++++ doc/man/egg2c.1 | 49 +++++ doc/man/egg2dxf.1 | 29 +++ doc/man/egg2flt.1 | 26 +++ doc/man/egg2obj.1 | 29 +++ doc/man/egg2x.1 | 35 ++++ doc/man/flt-info.1 | 15 ++ doc/man/flt-trans.1 | 39 ++++ doc/man/flt2egg.1 | 94 +++++++++ doc/man/fltcopy.1 | 44 +++++ doc/man/image-info.1 | 14 ++ doc/man/image-resize.1 | 29 +++ doc/man/image-trans.1 | 35 ++++ doc/man/interrogate.1 | 186 ++++++++++++++++++ doc/man/interrogate_module.1 | 69 +++++++ doc/man/lwo-scan.1 | 12 ++ doc/man/lwo2egg.1 | 91 +++++++++ doc/man/make-prc-key.1 | 56 ++++++ doc/man/multify.1 | 156 +++++++++++++++ doc/man/obj2egg.1 | 75 +++++++ doc/man/p3dcparse.1 | 38 ++++ doc/man/pdecrypt.1 | 1 + doc/man/pencrypt.1 | 92 +++++++++ doc/man/pfm-bba.1 | 17 ++ doc/man/pfm-trans.1 | 70 +++++++ doc/man/punzip.1 | 1 + doc/man/pview.1 | 50 +++++ doc/man/pzip.1 | 64 ++++++ doc/man/softcvs.1 | 22 +++ doc/man/test_interrogate.1 | 40 ++++ doc/man/text-stats.1 | 20 ++ doc/man/vrml-trans.1 | 19 ++ doc/man/vrml2egg.1 | 72 +++++++ doc/man/x-trans.1 | 17 ++ doc/man/x2egg.1 | 103 ++++++++++ makepanda/makepanda.py | 5 + pandatool/src/bam/bamInfo.cxx | 1 + pandatool/src/bam/bamToEgg.cxx | 1 + pandatool/src/bam/eggToBam.cxx | 1 + pandatool/src/bam/ptsToBam.cxx | 1 + pandatool/src/cvscopy/testCopy.cxx | 1 + pandatool/src/daeprogs/daeToEgg.cxx | 1 + pandatool/src/daeprogs/eggToDAE.cxx | 1 + pandatool/src/dxfprogs/dxfPoints.cxx | 1 + pandatool/src/dxfprogs/dxfToEgg.cxx | 1 + pandatool/src/dxfprogs/eggToDXF.cxx | 1 + pandatool/src/egg-mkfont/eggMakeFont.cxx | 1 + pandatool/src/egg-optchar/eggOptchar.cxx | 1 + pandatool/src/egg-palettize/eggPalettize.cxx | 1 + pandatool/src/egg-qtess/eggQtess.cxx | 11 +- pandatool/src/eggprogs/eggCrop.cxx | 1 + pandatool/src/eggprogs/eggListTextures.cxx | 1 + pandatool/src/eggprogs/eggMakeTube.cxx | 1 + pandatool/src/eggprogs/eggRename.cxx | 1 + pandatool/src/eggprogs/eggRetargetAnim.cxx | 1 + pandatool/src/eggprogs/eggTextureCards.cxx | 1 + pandatool/src/eggprogs/eggToC.cxx | 1 + pandatool/src/eggprogs/eggTopstrip.cxx | 1 + pandatool/src/eggprogs/eggTrans.cxx | 1 + pandatool/src/fltprogs/eggToFlt.cxx | 1 + pandatool/src/fltprogs/fltCopy.cxx | 1 + pandatool/src/fltprogs/fltInfo.cxx | 1 + pandatool/src/fltprogs/fltToEgg.cxx | 1 + pandatool/src/fltprogs/fltTrans.cxx | 1 + .../src/imageprogs/imageFixHiddenColor.cxx | 1 + pandatool/src/imageprogs/imageInfo.cxx | 1 + pandatool/src/imageprogs/imageResize.cxx | 1 + pandatool/src/imageprogs/imageTrans.cxx | 1 + .../src/imageprogs/imageTransformColors.cxx | 1 + pandatool/src/lwoprogs/lwoScan.cxx | 1 + pandatool/src/lwoprogs/lwoToEgg.cxx | 1 + pandatool/src/mayaprogs/eggToMaya.cxx | 1 + pandatool/src/mayaprogs/mayaCopy.cxx | 1 + pandatool/src/mayaprogs/mayaToEgg.cxx | 1 + pandatool/src/mayaprogs/mayaToEgg_server.cxx | 1 + pandatool/src/miscprogs/binToC.cxx | 1 + pandatool/src/objprogs/eggToObj.cxx | 1 + pandatool/src/objprogs/objToEgg.cxx | 1 + pandatool/src/pfmprogs/pfmBba.cxx | 1 + pandatool/src/pfmprogs/pfmTrans.cxx | 1 + pandatool/src/progbase/programBase.cxx | 136 ++++++++++++- pandatool/src/progbase/programBase.h | 7 +- pandatool/src/progbase/test_prog.cxx | 1 + pandatool/src/softprogs/softCVS.cxx | 1 + pandatool/src/text-stats/textStats.cxx | 1 + pandatool/src/vrmlprogs/vrmlToEgg.cxx | 1 + pandatool/src/vrmlprogs/vrmlTrans.cxx | 1 + pandatool/src/xfileprogs/eggToX.cxx | 1 + pandatool/src/xfileprogs/xFileToEgg.cxx | 1 + pandatool/src/xfileprogs/xFileTrans.cxx | 1 + 107 files changed, 3110 insertions(+), 9 deletions(-) create mode 100644 doc/man/bam-info.1 create mode 100644 doc/man/bam2egg.1 create mode 100644 doc/man/dae2egg.1 create mode 100644 doc/man/dxf-points.1 create mode 100644 doc/man/dxf2egg.1 create mode 100644 doc/man/egg-crop.1 create mode 100644 doc/man/egg-list-textures.1 create mode 100644 doc/man/egg-make-tube.1 create mode 100644 doc/man/egg-mkfont.1 create mode 100644 doc/man/egg-optchar.1 create mode 100644 doc/man/egg-palettize.1 create mode 100644 doc/man/egg-qtess.1 create mode 100644 doc/man/egg-rename.1 create mode 100644 doc/man/egg-retarget-anim.1 create mode 100644 doc/man/egg-texture-cards.1 create mode 100644 doc/man/egg-topstrip.1 create mode 100644 doc/man/egg-trans.1 create mode 100644 doc/man/egg2bam.1 create mode 100644 doc/man/egg2c.1 create mode 100644 doc/man/egg2dxf.1 create mode 100644 doc/man/egg2flt.1 create mode 100644 doc/man/egg2obj.1 create mode 100644 doc/man/egg2x.1 create mode 100644 doc/man/flt-info.1 create mode 100644 doc/man/flt-trans.1 create mode 100644 doc/man/flt2egg.1 create mode 100644 doc/man/fltcopy.1 create mode 100644 doc/man/image-info.1 create mode 100644 doc/man/image-resize.1 create mode 100644 doc/man/image-trans.1 create mode 100644 doc/man/interrogate.1 create mode 100644 doc/man/interrogate_module.1 create mode 100644 doc/man/lwo-scan.1 create mode 100644 doc/man/lwo2egg.1 create mode 100644 doc/man/make-prc-key.1 create mode 100644 doc/man/multify.1 create mode 100644 doc/man/obj2egg.1 create mode 100644 doc/man/p3dcparse.1 create mode 120000 doc/man/pdecrypt.1 create mode 100644 doc/man/pencrypt.1 create mode 100644 doc/man/pfm-bba.1 create mode 100644 doc/man/pfm-trans.1 create mode 120000 doc/man/punzip.1 create mode 100644 doc/man/pview.1 create mode 100644 doc/man/pzip.1 create mode 100644 doc/man/softcvs.1 create mode 100644 doc/man/test_interrogate.1 create mode 100644 doc/man/text-stats.1 create mode 100644 doc/man/vrml-trans.1 create mode 100644 doc/man/vrml2egg.1 create mode 100644 doc/man/x-trans.1 create mode 100644 doc/man/x2egg.1 diff --git a/doc/man/bam-info.1 b/doc/man/bam-info.1 new file mode 100644 index 0000000000..c9432acd7a --- /dev/null +++ b/doc/man/bam-info.1 @@ -0,0 +1,21 @@ +.\" Automatically generated by bam-info -write-bam +.TH BAM-INFO 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +bam-info \- describe the contents of .bam files +.SH SYNOPSIS +\fBbam-info\fR [opts] input.bam [input.bam ... ] +.SH DESCRIPTION +This program scans one or more Bam files\-\-Panda's Binary Animation and Models native binary format\-\-and describes their contents. +.SH OPTIONS +.TP +.B \-ls +List the scene graph hierarchy in the bam file. +.TP +.B \-t +List explicitly each transition in the hierarchy. +.TP +.B \-g +Output verbose information about the each Geom in the Bam file. +.TP +.B \-h +Display this help page. diff --git a/doc/man/bam2egg.1 b/doc/man/bam2egg.1 new file mode 100644 index 0000000000..b88e908d14 --- /dev/null +++ b/doc/man/bam2egg.1 @@ -0,0 +1,31 @@ +.\" Automatically generated by bam2egg -write-bam +.TH BAM2EGG 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +bam2egg \- convert a native Panda .bam file to an .egg file +.SH SYNOPSIS +\fBbam2egg\fR [opts] input.bam output.egg +.br +\fBbam2egg\fR [opts] -o output.egg input.bam +.br +\fBbam2egg\fR [opts] input.bam >output.egg +.SH DESCRIPTION +This program converts native Panda bam files to egg. The conversion is somewhat incomplete; running egg2bam followed by bam2egg should not be expected to yield the same egg file you started with. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input bam file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.B \-ignore +Ignore non-fatal errors and generate an egg file anyway. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the input bam file. By default, this is taken from the Config.prc file, which is currently zup_right. +.TP +.B \-h +Display this help page. diff --git a/doc/man/dae2egg.1 b/doc/man/dae2egg.1 new file mode 100644 index 0000000000..dbcd6bf4d0 --- /dev/null +++ b/doc/man/dae2egg.1 @@ -0,0 +1,75 @@ +.\" Automatically generated by dae2egg -write-bam +.TH DAE2EGG 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +dae2egg \- convert COLLADA assets into .egg files +.SH SYNOPSIS +\fBdae2egg\fR [opts] input.dae output.egg +.br +\fBdae2egg\fR [opts] -o output.egg input.dae +.br +\fBdae2egg\fR [opts] input.dae >output.egg +.SH DESCRIPTION +This program converts .dae files (COLLADA Digital Asset Exchange) to .egg. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input COLLADA file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.B \-ignore +Ignore non-fatal errors and generate an egg file anyway. +.TP +.B \-invtrans +Import the .dae file using inverted transparency. This is useful when importing COLLADA files from some authoring tools that export models with inverted transparency, such as Google SketchUp. +.TP +.BI "\-ui " "units" +Specify the units of the input COLLADA file. Normally, this can be inferred from the file itself. +.TP +.BI "\-uo " "units" +Specify the units of the resulting egg file. If this is specified, the vertices in the egg file will be scaled as necessary to make the appropriate units conversion; otherwise, the vertices will be left as they are. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the input COLLADA file. Normally, this can inferred from the file itself. +.TP +.B \-h +Display this help page. diff --git a/doc/man/dxf-points.1 b/doc/man/dxf-points.1 new file mode 100644 index 0000000000..7c7489800c --- /dev/null +++ b/doc/man/dxf-points.1 @@ -0,0 +1,16 @@ +.\" Automatically generated by dxf-points -write-bam +.TH DXF-POINTS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +dxf-points \- extract points from AutoCAD .dxf files +.SH SYNOPSIS +\fBdxf-points\fR [opts] input.dxf > output.txt +.br +\fBdxf-points\fR [opts] -o output.txt input.dxf +.br +\fBdxf-points\fR [opts] input.dxf output.txt +.SH DESCRIPTION +This program reads an AutoCAD .dxf file and generates a simple list of all the points contained within it, one per line, to a text file, or to standard output. +.SH OPTIONS +.TP +.B \-h +Display this help page. diff --git a/doc/man/dxf2egg.1 b/doc/man/dxf2egg.1 new file mode 100644 index 0000000000..6e00fa86d7 --- /dev/null +++ b/doc/man/dxf2egg.1 @@ -0,0 +1,72 @@ +.\" Automatically generated by dxf2egg -write-bam +.TH DXF2EGG 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +dxf2egg \- convert AutoCAD .dxf files to .egg files +.SH SYNOPSIS +\fBdxf2egg\fR [opts] input.dxf output.egg +.br +\fBdxf2egg\fR [opts] -o output.egg input.dxf +.br +\fBdxf2egg\fR [opts] input.dxf >output.egg +.SH DESCRIPTION +This program converts DXF (AutoCAD interchange format) to egg. It only converts polygon data, with no fancy tricks. DXF does not support hierarchical databases, so dxf2egg creates a single group at the root level for each layer in the DXF file. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input DXF file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.B \-ignore +Ignore non-fatal errors and generate an egg file anyway. +.TP +.BI "\-ui " "units" +Specify the units of the input DXF file. Normally, this can be inferred from the file itself. +.TP +.BI "\-uo " "units" +Specify the units of the resulting egg file. If this is specified, the vertices in the egg file will be scaled as necessary to make the appropriate units conversion; otherwise, the vertices will be left as they are. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the input DXF file. Normally, this is z-up. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-crop.1 b/doc/man/egg-crop.1 new file mode 100644 index 0000000000..d7cd3f4d50 --- /dev/null +++ b/doc/man/egg-crop.1 @@ -0,0 +1,32 @@ +.\" Automatically generated by egg-crop -write-bam +.TH EGG-CROP 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-crop \- crop geometry in an .egg file +.SH SYNOPSIS +\fBegg-crop\fR [opts] -o output.egg input.egg +.br +\fBegg-crop\fR [opts] input.egg >output.egg +.SH DESCRIPTION +egg\-crop strips out all parts of an egg file that fall outside of an arbitrary bounding volume, specified with a minimum and maximum point in world coordinates. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-min " "x,y,z" +Specify the minimum point. +.TP +.BI "\-max " "x,y,z" +Specify the maximum point. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the egg file is written to standard output. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting egg file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is the same coordinate system as the input egg file. If this is different from the input egg file, a conversion will be performed. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-list-textures.1 b/doc/man/egg-list-textures.1 new file mode 100644 index 0000000000..0c8859b12b --- /dev/null +++ b/doc/man/egg-list-textures.1 @@ -0,0 +1,21 @@ +.\" Automatically generated by egg-list-textures -write-bam +.TH EGG-LIST-TEXTURES 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-list-textures \- list textures referenced by an .egg file +.SH SYNOPSIS +\fBegg-list-textures\fR [opts] input.egg +.SH DESCRIPTION +egg\-list\-textures reads an egg file and writes a list of the textures it references. It is particularly useful for building up the textures.txa file used for egg\-palettize, since the output format is crafted to be compatible with that file's input format. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system to operate in. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is the coordinate system of the input egg file. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-make-tube.1 b/doc/man/egg-make-tube.1 new file mode 100644 index 0000000000..2f7bc4cdd2 --- /dev/null +++ b/doc/man/egg-make-tube.1 @@ -0,0 +1,77 @@ +.\" Automatically generated by egg-make-tube -write-bam +.TH EGG-MAKE-TUBE 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-make-tube \- generate a tube or sphere from geometry in an .egg file +.SH SYNOPSIS +\fBegg-make-tube\fR [opts] output.egg +.br +\fBegg-make-tube\fR [opts] -o output.egg +.br +\fBegg-make-tube\fR [opts] >output.egg +.SH DESCRIPTION +egg\-make\-tube generates an egg file representing a "tube" model, a cylinder capped on both ends by hemispheres. This is similar in shape to the CollisionTube object within Panda. +.PP +This program can also generate spheres if you omit \-b; in this case, you are generating a degenerate tube of length 0. +.SH OPTIONS +.TP +.BI "\-a " "x,y,z" +Specify the first endpoint of the tube. +.TP +.BI "\-b " "x,y,z" +Specify the second endpoint of the tube. +.TP +.BI "\-r " "radius" +Specify the radius of the tube. The tube will extend beyond the endpoints in each direction by the amount of radius. +.TP +.BI "\-slices " "count" +Specify the number of slices appearing radially around the tube. +.TP +.BI "\-crings " "count" +Specify the number of rings appearing in each endcap of the tube. +.TP +.BI "\-trings " "count" +Specify the number of rings appearing in the cylindrical body of the tube. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting egg file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is y-up. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-mkfont.1 b/doc/man/egg-mkfont.1 new file mode 100644 index 0000000000..5e3a755e23 --- /dev/null +++ b/doc/man/egg-mkfont.1 @@ -0,0 +1,76 @@ +.\" Automatically generated by egg-mkfont -write-bam +.TH EGG-MKFONT 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-mkfont \- generates .egg files with rasterized font glyphs +.SH SYNOPSIS +\fBegg-mkfont\fR [opts] -o output.egg font +.br +\fBegg-mkfont\fR [opts] font output.egg +.SH DESCRIPTION +egg\-mkfont uses the FreeType library to generate an egg file and a series of texture images from a font file input, such as a TTF file. The resulting egg file can be loaded in Panda as a font for rendering text, even if FreeType is not compiled into the executing Panda. +.PP +egg\-mkfont will normally run the generated egg file through egg\-palettize automatically as part of the generation process. This collects the individual glyph textures into a small number of texture maps. If you intend to run the font through egg\-palettize yourself later, you may choose to omit this step. +.SH OPTIONS +.TP +.BI "\-fg " "r,g,b[,a]" +Specifies the foreground color of the generated texture map. The default is white: 1,1,1,1, which leads to the most flexibility as the color can be modulated at runtime to any suitable color. +.TP +.BI "\-bg " "r,g,b[,a]" +Specifies the background color of the generated texture map. The default is transparent: 1,1,1,0, which allows the text to be visible against any color background by placing a polygon of a suitable color behind it. If the alpha component of either -fg or -bg is not 1, the generated texture images will include an alpha component; if both colors specify an alpha component of 1 (or do not specify an alpha compenent), then the generated images will not include an alpha component. +.TP +.BI "\-interior " "r,g,b[,a]" +Specifies the color to render the interior part of a hollow font. This is a special effect that involves analysis of the bitmap after the font has been rendered, and so is more effective when the pixel size is large. It also implies -noaa (but you can use a scale factor with -sf to achieve antialiasing). +.TP +.BI "\-chars " "range" +Specifies the characters of the font that are used. The range specification may include combinations of decimal or hex unicode values (where hex values are identified with a leading 0x), separated by commas and hyphens to indicate ranges, e.g. '32-126,0xfa0-0xfff'. It also may specify ranges of ASCII characters by enclosing them within square brackets, e.g. '[A-Za-z0-9]'. If this is not specified, the default is the set of ASCII characters. +.TP +.BI "\-extra " "file.egg" +Specifies additional externally-painted glyphs to mix into the generated egg file. The named egg file is expected to contain one or more groups, each of which is named with the decimal unicode number of a character and should contain one polygon. These groups are simply copied into the output egg file as if they were generated locally. This option may be repeated. +.TP +.BI "\-ppu " "pixels" +Specify the pixels per unit. This is the number of pixels in the generated texture map that are used for each onscreen unit (or each 10 points of font; see -ps). Setting this number larger results in an easier-to-read font, but at the cost of more texture memory. The default is 30. +.TP +.BI "\-ps " "size" +Specify the point size of the resulting font. This controls the apparent size of the font when it is rendered onscreen. By convention, a 10 point font is 1 screen unit high, so the default is 10. +.TP +.BI "\-pm " "n" +The number of extra pixels around a single character in the generated polygon. This may be a floating-point number. The default is 1. +.TP +.BI "\-tm " "n" +The number of extra pixels around each character in the texture map. This may only be an integer. The default is 2. This is meaningful when -nopal is also used; in the normal case, use -pm to control both the polygon size and the texture map spacing. +.TP +.BI "\-rm " "n" +The amount of padding in screen units to place around the glyph when rendered. This differs from -pm in that it has no effect on the generated texture map, only on the generated egg. Use this in order to space the characters out in case they appear to be too close together when rendered. The default is 0. +.TP +.BI "\-sf " "factor" +The scale factor of the generated image. This is the factor by which the font image is generated oversized, then reduced to its final size, to improve antialiasing. If the specified font contains one or more fixed-size fonts instead of a scalable font, the scale factor may be automatically adjusted as necessary to scale the closest-matching font to the desired pixel size. The default is 2. +.TP +.B \-noaa +Disable low-level antialiasing by the Freetype library. This is unrelated to the antialiasing that is applied due to the scale factor specified by -sf; you may have either one, neither, or both kinds of antialiasing enabled. +.TP +.B \-nopal +Don't run egg-palettize automatically on the output file, but just output the raw egg file and all of its individual texture images, one for each glyph. +.TP +.B \-nr +Don't actually reduce the images after applying the scale factor, but leave them at their inflated sizes. Presumably you will reduce them later, for instance with egg-palettize. +.TP +.BI "\-gp " "pattern" +The pattern to be used to generate the glyph texture images. This string will be passed to sprintf to generate the actual file name; it should contain the string %d or %x (or some variant such as %03d) which will be filled in with the Unicode number of each symbol. If it is omitted, the default is based on the name of the egg file. This is used only if -nopal is specified; in the normal case, without -nopal, use -pp instead. +.TP +.BI "\-pp " "pattern" +The pattern to be used to generate the palette texture images. This string is effectively passed to egg-palettize as the -tn option, and thus should contain %i for the palette index number. This is used if -nopal is not specified. +.TP +.BI "\-palsize " "xsize,ysize" +Specify the size of the palette texture images. This is used if -nopal is not specified. +.TP +.BI "\-face " "index" +Specify the face index of the particular face within the font file to use. Some font files contain multiple faces, indexed beginning at 0. The default is face 0. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting egg file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is y-up. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-optchar.1 b/doc/man/egg-optchar.1 new file mode 100644 index 0000000000..7b6e949fa7 --- /dev/null +++ b/doc/man/egg-optchar.1 @@ -0,0 +1,150 @@ +.\" Automatically generated by egg-optchar -write-bam +.TH EGG-OPTCHAR 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-optchar \- optimizes character models and animations in .egg files +.SH SYNOPSIS +\fBegg-optchar\fR -o output.egg [opts] input.egg +.br +\fBegg-optchar\fR -d dirname [opts] file.egg [file.egg ...] +.br +\fBegg-optchar\fR -inplace [opts] file.egg [file.egg ...] +.br +\fBegg-optchar\fR -inf input_list_filename [opts] +.SH DESCRIPTION +egg\-optchar performs basic optimizations of a character model and its associated animations, primarily by analyzing the animation tables and removing unneeded joints and/or morphs. It can also perform basic restructuring operations on the character hierarchy. +.SH OPTIONS +.TP +.B \-noabs +Don't allow any of the named egg files to have absolute pathnames. If any do, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-ls +List the joint hierarchy instead of performing any operations. +.TP +.B \-lsv +List the joint hierarchy along with an indication of the properties each joint. +.TP +.B \-lsp +List the existing joint hierarchy as a series of -p joint,parent commands, suitable for pasting into an egg-optchar command line. +.TP +.BI "\-keep " "joint[,joint...]" +Keep the named joints (or sliders) in the character, even if they do not appear to be needed by the animation. +.TP +.BI "\-drop " "joint[,joint...]" +Removes the named joints or sliders, even if they appear to be needed. +.TP +.BI "\-expose " "joint[,joint...]" +Expose the named joints by flagging them with a DCS attribute, so each one can be found in the scene graph when the character is loaded, and objects can be parented to it. This implies -keep. +.TP +.BI "\-suppress " "joint[,joint...]" +The opposite of suppress, this prevents the named joints from being created with an implicit DCS attribute, even if they contain rigid geometry. The default is to create an implicit node for any joint that contains rigid geometry, to take advantage of display list and/or vertex buffer caching. This does not imply -keep. +.TP +.BI "\-flag " "node[,node...][=name]" +Assign the indicated name to the geometry within the given nodes. This will make the geometry visible as a node in the resulting character model when it is loaded in the scene graph (normally, the node hierarchy is suppressed when loading characters). This is different from -expose in that it reveals geometry rather than joints; the revealed node can be hidden or its attributes changed at runtime, but it will be animated by its vertices, not the node, so objects parented to this node will not inherit its animation. +.TP +.BI "\-defpose " "anim.egg,frame" +Specify the model's default pose. The pose is taken from the indicated frame of the named animation file (which must also be named separately on the command line). The pose will be held by the model in the absence of any animation, and need not be the same pose in which the model was originally skinned. +.TP +.B \-preload +Add an entry for each animation to the model file(s). This can be used at runtime to support asynchronous loading and binding of animation channels. +.TP +.BI "\-zero " "joint[,hprxyzijkabc]" +Zeroes out the animation channels for the named joint. If a subset of the component letters hprxyzijkabc is included, the operation is restricted to just those components; otherwise the entire transform is cleared. +.TP +.B \-keepall +Keep all joints and sliders in the character, except those named explicitly by -drop. +.TP +.BI "\-p " "joint,parent" +Moves the named joint under the named parent joint. Use "-p joint," to reparent a joint to the root. The joint transform is recomputed appropriately under its new parent so that the animation is not affected (the effect is similar to NodePath::wrt_reparent_to). +.TP +.BI "\-new " "joint,source" +Creates a new joint under the named parent joint. The new joint will inherit the same net transform as its parent. +.TP +.BI "\-rename " "joint,newjoint" +Renames the indicated joint, if present, to the given name. +.TP +.BI "\-q " "quantum" +Quantize joint membership values to the given unit. This is the smallest significant change in joint membership. There can be a significant performance (and memory utilization) runtime benefit for eliminating small differences in joint memberships between neighboring vertices. The default is 0.01; specifying 0 means to preserve the original values. +.TP +.BI "\-qa " "quantum[,hprxyzijkabc]" +Quantizes animation channels to the given unit. This rounds each of the named components of all joints to the nearest multiple of unit. There is no performance benefit, and little compression benefit, for doing this; and this may introduce visible artifacts to the animation. However, sometimes it is a useful tool for animation analysis and comparison. This option may be repeated several times to quantize different channels by a different amount. +.TP +.BI "\-dart " "[default, sync, nosync, or structured]" +change the dart value in the given eggs +.TP +.B \-fixrest +Specify this to force all the initial rest frames of the various model files to the same value as the first model specified. This is a fairly drastic way to repair models whose initial rest frame values are completely bogus, but should not be performed when the input models are correct. +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. This is only valid when there is only one input egg file on the command line. If you want to process multiple files simultaneously, you must use either -d or -inplace. +.TP +.BI "\-d " "dirname" +Specify the name of the directory in which to write the resulting egg files. If you are processing only one egg file, this may be omitted in lieu of the -o option. If you are processing multiple egg files, this may be omitted only if you specify -inplace instead. +.TP +.B \-inplace +If this option is given, the input egg files will be rewritten in place with the results. This obviates the need to specify -d for an output directory; however, it's risky because the original input egg files are lost. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system to operate in. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.BI "\-inf " "filename" +Reads input args from a text file instead of the command line. Useful for really, really large lists of args that break the OS-imposed limits on the length of command lines. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-palettize.1 b/doc/man/egg-palettize.1 new file mode 100644 index 0000000000..1309a4556e --- /dev/null +++ b/doc/man/egg-palettize.1 @@ -0,0 +1,91 @@ +.\" Automatically generated by egg-palettize -write-bam +.TH EGG-PALETTIZE 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-palettize \- pack textures from various .egg models into palette images +.SH SYNOPSIS +\fBegg-palettize\fR [opts] file.egg [file.egg ...] +.SH DESCRIPTION +egg\-palettize attempts to pack several texture maps from various models together into one or more palette images, for improved rendering performance and ease of texture management. It can also resize textures and convert them to another image file format, whether or not they are actually placed on a palette, and can manage some simple texture properties, like mipmapping and rendering format. +.PP +egg\-palettize reads a texture attributes file, usually named textures.txa, which contains instructions from the user about resizing particular textures. Type egg\-palettize \-H for an introduction to the syntax of this file. +.PP +The palettization information from previous runs is recorded in a file named textures.boo (assuming the attributes file is named textures.txa); a complete record of every egg file and every texture that has been referenced is kept here. This allows the program to intelligently manage the multiple egg files that may reference the textures in question. +.SH OPTIONS +.TP +.B \-noabs +Don't allow any of the named egg files to have absolute pathnames. If any do, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-af " "filename" +Read the indicated file as the .txa file. The default is textures.txa. +.TP +.BI "\-a " "filename" +Deprecated option. This is the same as -af. +.TP +.BI "\-as " "script" +Accept the script specified on the command line as the contents of the .txa file, instead of reading a file on disk. This implies -nodb and -opt. +.TP +.B \-nodb +Don't read or record the state information to a .boo file. By default, the palettization information is recorded so it can be preserved between multiple invocations of egg-palettize. If you specify this parameter, all the egg files to be palettized together must be named at the same time. This also implies -opt, since there's no point in not making an optimal packing if you won't be preserving the state for future adjustments. +.TP +.BI "\-tn " "pattern" +Specify the name to generate for each palette image. The string should contain %g for the group name, %p for the page name, and %i for the index within the page. The extension is inferred from the image type. The default is '%g_palette_%p_%i'. +.TP +.B \-pi +Do not process anything, but instead report the detailed palettization information written in the state file. +.TP +.B \-s +Do not process anything, but report statistics on palette and texture utilization from the state file. +.TP +.B \-R +Remove the named egg files from the previously-generated state data file. +.TP +.BI "\-d " "dirname" +The directory in which to write the palettized egg files. This is only necessary if more than one egg file is processed at the same time; if it is included, each egg file will be processed and written into the indicated directory. +.TP +.BI "\-dm " "dirname" +The directory in which to place all maps: generated palettes, as well as images which were not placed on palettes (but may have been resized). If this contains the string %g, this will be replaced with the 'dir' string associated with a palette group; see egg-palettize -H. +.TP +.BI "\-ds " "dirname" +The directory to write palette shadow images to. These are working copies of the palette images, useful when the palette image type is a lossy-compression type like JPEG; you can avoid generational loss of quality on the palette images with each pass through the palettes by storing these extra shadow images in a lossless image type. This directory is only used if the :shadowtype keyword appears in the .txa file. +.TP +.BI "\-dr " "dirname" +The directory to make map filenames relative to when writing egg files. If specified, this should be an initial substring of -dm. +.TP +.BI "\-g " "group" +The default palette group that egg files will be assigned to if they are not explicitly assigned to any other group. +.TP +.BI "\-gdir " "name" +The "dir" string to associate with the default palette group specified with -g, if no other dir name is given in the .txa file. +.TP +.B \-all +Consider all the textures referenced in all egg files that have ever been palettized, not just the egg files that appear on the command line. +.TP +.B \-egg +Regenerate all egg files that need modification, even those that aren't named on the command line. +.TP +.B \-redo +Force a regeneration of each image from its original source(s). When used in conjunction with -egg, this also forces each egg file to be regenerated. +.TP +.B \-opt +Force an optimal packing. By default, textures are added to existing palettes without disturbing them, which can lead to suboptimal packing. Including this switch forces the palettes to be rebuilt if necessary to optimize the packing, but this may invalidate other egg files which share this palette. +.TP +.B \-omitall +Re-enables the flag to omit all textures. This flag is normally on by default, causing nothing actually to be palettized, until the first time egg-palettize is run with the -opt flag, which turns off the omitall flag and thenceforth allows textures to be combined into palettes. Specifying this flag restores the original behavior of keeping every texture as a separate image (which is convenient for development). +.TP +.B \-H +Describe the syntax of the attributes file. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. This is only valid when there is only one input egg file on the command line. If you want to process multiple files simultaneously, you must use either -d or -inplace. +.TP +.B \-inplace +If this option is given, the input egg files will be rewritten in place with the results. This obviates the need to specify -d for an output directory; however, it's risky because the original input egg files are lost. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system to operate in. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. +.TP +.BI "\-inf " "filename" +Reads input args from a text file instead of the command line. Useful for really, really large lists of args that break the OS-imposed limits on the length of command lines. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-qtess.1 b/doc/man/egg-qtess.1 new file mode 100644 index 0000000000..cb2416954d --- /dev/null +++ b/doc/man/egg-qtess.1 @@ -0,0 +1,76 @@ +.\" Automatically generated by egg-qtess -write-bam +.TH EGG-QTESS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-qtess \- tesselate NURBS surfaces in .egg files +.SH SYNOPSIS +\fBegg-qtess\fR [opts] -o output.egg input.egg +.br +\fBegg-qtess\fR [opts] input.egg >output.egg +.SH DESCRIPTION +egg\-qtess reads an egg file, tessellates all of its NURBS surfaces using a simple uniform tessellation, and outputs a polygonal egg file. +.PP +Characters are supported, soft\-skinned and otherwise; joint ownership is computed correctly for each new polygon vertex. Primitives other than NURBS surfaces appearing in the egg file are unaffected. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-f " "filename" +Read the indicated parameter file. Type egg-qtess -H to print a description of the parameter file format. +.TP +.BI "\-up " "subdiv" +Specify a uniform subdivision per patch (isoparam). Each NURBS surface is made up of N x M patches, each of which is divided into subdiv x subdiv quads. A fractional number is allowed. +.TP +.BI "\-us " "subdiv" +Specify a uniform subdivision per surface. Each NURBS surface is subdivided into subdiv x subdiv quads, regardless of the number of isoparams it has. A fractional number is meaningless. +.TP +.BI "\-t " "tris" +Specify an approximate number of triangles to produce. This is the total number of triangles for the entire egg file, including those surfaces that have already been given an explicit tessellation by a parameter file. +.TP +.B \-ap +Attempt to automatically place tessellation lines where they'll do the most good on each surface (once the number of polygons for the surface has already been determined). +.TP +.B \-ad +Attempt to automatically distribute polygons among the surfaces where they are most needed according to curvature and size, instead of according to the number of isoparams. This only has meaning when used in conjunction with -t. +.TP +.BI "\-ar " "ratio" +Specify the ratio of dominance of size to curvature for -ap and -ad. A value of 0 forces placement by curvature only; a very large value (like 1000) forces placement by size only. The default is 5.0. +.TP +.B \-e +Respect subdivision parameters given in the egg file. If this is specified, the egg file may define the effective number of patches of each NURBS entry. This can be used alone or in conjunction with -u or -t to fine-tune the uniform tessellation on a per-surface basis. (This is ignored if -ad is in effect.) +.TP +.B \-q +Instead of writing an egg file, generate a parameter file for output. +.TP +.B \-H +Describe the format of the parameter file specified with -f. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the egg file is written to standard output. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting egg file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is the same coordinate system as the input egg file. If this is different from the input egg file, a conversion will be performed. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-rename.1 b/doc/man/egg-rename.1 new file mode 100644 index 0000000000..4cf84e5345 --- /dev/null +++ b/doc/man/egg-rename.1 @@ -0,0 +1,42 @@ +.\" Automatically generated by egg-rename -write-bam +.TH EGG-RENAME 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-rename \- rename nodes in .egg files +.SH SYNOPSIS +\fBegg-rename\fR -o output.egg [opts] input.egg +.br +\fBegg-rename\fR -d dirname [opts] file.egg [file.egg ...] +.br +\fBegg-rename\fR -inplace [opts] file.egg [file.egg ...] +.br +\fBegg-rename\fR -inf input_list_filename [opts] +.SH DESCRIPTION +egg\-rename reads one or more egg files and writes back with modifiednode names. ie. suppressing prefix from all the nodes' names. +.SH OPTIONS +.TP +.B \-noabs +Don't allow any of the named egg files to have absolute pathnames. If any do, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-strip_prefix " "name" +strips out the prefix that is put on all nodes, by maya ext. ref +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. This is only valid when there is only one input egg file on the command line. If you want to process multiple files simultaneously, you must use either -d or -inplace. +.TP +.BI "\-d " "dirname" +Specify the name of the directory in which to write the resulting egg files. If you are processing only one egg file, this may be omitted in lieu of the -o option. If you are processing multiple egg files, this may be omitted only if you specify -inplace instead. +.TP +.B \-inplace +If this option is given, the input egg files will be rewritten in place with the results. This obviates the need to specify -d for an output directory; however, it's risky because the original input egg files are lost. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system to operate in. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.BI "\-inf " "filename" +Reads input args from a text file instead of the command line. Useful for really, really large lists of args that break the OS-imposed limits on the length of command lines. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-retarget-anim.1 b/doc/man/egg-retarget-anim.1 new file mode 100644 index 0000000000..8b4c044a2f --- /dev/null +++ b/doc/man/egg-retarget-anim.1 @@ -0,0 +1,66 @@ +.\" Automatically generated by egg-retarget-anim -write-bam +.TH EGG-RETARGET-ANIM 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-retarget-anim \- remove transformations from animation data in .egg files +.SH SYNOPSIS +\fBegg-retarget-anim\fR -o output.egg [opts] input.egg +.br +\fBegg-retarget-anim\fR -d dirname [opts] file.egg [file.egg ...] +.br +\fBegg-retarget-anim\fR -inplace [opts] file.egg [file.egg ...] +.br +\fBegg-retarget-anim\fR -inf input_list_filename [opts] +.SH DESCRIPTION +egg\-retarget\-anim reads a character model and its associated animation files, and removes the translations and scales from the animation files, replacing them with the translations and scales from the rest position of the character model. +.PP +This allows an animation that was generated for a model with one skeleton to be played successfully on a model with a different skeleton, provided that both skeletons have the same hierarchy and differ only in scales and/or translations of the various joints, and that scales and translations are not part of the per\-frame animations. +.SH OPTIONS +.TP +.B \-noabs +Don't allow any of the named egg files to have absolute pathnames. If any do, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-r " "file.egg" +Read the reference model from the indicated egg file. All of the animations will be retargeted to match the indicated file. +.TP +.BI "\-keep " "joint[,joint...]" +Preserve the full animation on the named joint(s). This is especially appropriate for the root joint. +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. This is only valid when there is only one input egg file on the command line. If you want to process multiple files simultaneously, you must use either -d or -inplace. +.TP +.BI "\-d " "dirname" +Specify the name of the directory in which to write the resulting egg files. If you are processing only one egg file, this may be omitted in lieu of the -o option. If you are processing multiple egg files, this may be omitted only if you specify -inplace instead. +.TP +.B \-inplace +If this option is given, the input egg files will be rewritten in place with the results. This obviates the need to specify -d for an output directory; however, it's risky because the original input egg files are lost. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system to operate in. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.BI "\-inf " "filename" +Reads input args from a text file instead of the command line. Useful for really, really large lists of args that break the OS-imposed limits on the length of command lines. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-texture-cards.1 b/doc/man/egg-texture-cards.1 new file mode 100644 index 0000000000..35bbf1b5df --- /dev/null +++ b/doc/man/egg-texture-cards.1 @@ -0,0 +1,81 @@ +.\" Automatically generated by egg-texture-cards -write-bam +.TH EGG-TEXTURE-CARDS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-texture-cards \- generate an .egg file containing texture cards +.SH SYNOPSIS +\fBegg-texture-cards\fR [opts] texture [texture ...] output.egg +.br +\fBegg-texture-cards\fR [opts] -o output.egg texture [texture ...] +.br +\fBegg-texture-cards\fR [opts] texture [texture ...] >output.egg +.SH DESCRIPTION +egg\-texture\-cards generates an egg file consisting of several square polygons, one for each texture name that appears on the command line. +.PP +This is a handy thing to have for importing texture images through egg\-palettize, even when those textures do not appear on any real geometry; it can also be used for creating a lot of simple polygons for rendering click buttons and similar interfaces. +.SH OPTIONS +.TP +.BI "\-g " "left,right,bottom,top" +Specifies the geometry of each polygon. The default is a unit polygon centered on the origin: -0.5,0.5,-0.5,0.5. Polygons are always created on the X-Y plane. If -p is not also specified, all polygons will be the same size and shape. +.TP +.BI "\-p " "xpixels,ypixels" +Indicates that polygons should be sized in proportion to the pixel size of the texture image. This will potentially create a different size and shape polygon for each texture. The coordinate pair represents the image size in pixels that will exactly fill up the polygon described with -g (or the default polygon if -g is not specified); smaller images will be given proportionately smaller polygons, and larger images will be given proportionately larger polygons. +.TP +.BI "\-suffix " "string" +Normally, each polygon is given a name based on the basename of its corresponding texture's filename (without the filename extension). This option specifies an ignorable suffix in the texture filename(s); if this suffix is present, it is not included in the polygon's name. This option may be repeated multiple times. +.TP +.BI "\-c " "r,g,b[,a]" +Specifies the color of each polygon. The default is white: 1,1,1,1. +.TP +.BI "\-wm " "wrap" +Indicates the wrap mode of the texture: "repeat", "clamp", or any of the other modes supported by egg syntax. The default is to leave this unspecified. +.TP +.BI "\-wmu " "wrap_u" +Indicates the wrap mode of the texture in the U direction. This overrides -wm, if specified. +.TP +.BI "\-wmv " "wrap_v" +Indicates the wrap mode of the texture in the V direction. This overrides -wm, if specified. +.TP +.BI "\-minf " "filter" +Indicates the minfilter mode of the texture: "linear", "mipmap", or any of the other modes supported by egg syntax. The default is to leave this unspecified. +.TP +.BI "\-magf " "filter" +Indicates the magfilter mode of the texture: "linear" or "nearest". The default is to leave this unspecified. +.TP +.BI "\-aniso " "degree" +Indicates the anisotropic degree of the texture. The default is to leave this unspecified. +.TP +.BI "\-ql " "[default | fastest | normal | best]" +Specifies the quality level of the texture. This mainly affects the tinydisplay software renderer. +.TP +.BI "\-f " "format" +Indicates the format for all textures: typical choices are "rgba12" or "rgb5" or "alpha". The default is to leave this unspecified. +.TP +.BI "\-f1 " "format" +Indicates the format for one-channel textures only. If specified, this overrides the format specified by -f. +.TP +.BI "\-f2 " "format" +Indicates the format for two-channel textures only. If specified, this overrides the format specified by -f. +.TP +.BI "\-f3 " "format" +Indicates the format for three-channel textures only. If specified, this overrides the format specified by -f. +.TP +.BI "\-f4 " "format" +Indicates the format for four-channel textures only. If specified, this overrides the format specified by -f. +.TP +.B \-b +Make the textured polygons backfaced (two-sided). +.TP +.BI "\-fps " "frame-rate" +Normally, all of the texture cards are created as a series of nodes beneath a SequenceNode. This allows all of the cards to be viewed, one at a time, if the output file is loaded in pview. It also has the nice side-effect of creating an automatic texture flip that can be used directly by applications; use this parameter to specify the frame rate of that texture flip. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting egg file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is y-up. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-topstrip.1 b/doc/man/egg-topstrip.1 new file mode 100644 index 0000000000..7b59e09eee --- /dev/null +++ b/doc/man/egg-topstrip.1 @@ -0,0 +1,75 @@ +.\" Automatically generated by egg-topstrip -write-bam +.TH EGG-TOPSTRIP 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-topstrip \- unapplies animation from a joint in an .egg file +.SH SYNOPSIS +\fBegg-topstrip\fR -o output.egg [opts] input.egg +.br +\fBegg-topstrip\fR -d dirname [opts] file.egg [file.egg ...] +.br +\fBegg-topstrip\fR -inplace [opts] file.egg [file.egg ...] +.br +\fBegg-topstrip\fR -inf input_list_filename [opts] +.SH DESCRIPTION +egg\-topstrip reads a character model and its associated animation files, and unapplies the animation from one of the top joints. This effectively freezes that particular joint, and makes the rest of the character relative to that joint. +.PP +This is a particularly useful thing to do to generate character models that can stack one on top of the other in a sensible way. +.SH OPTIONS +.TP +.B \-noabs +Don't allow any of the named egg files to have absolute pathnames. If any do, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-t " "name" +Specify the name of the 'top' joint, from which to draw the animation channels which will be applied to the entire animation. +.TP +.B \-i +Invert the matrix before applying. This causes a subtractive effect. This is the default unless -r is specified. +.TP +.B \-n +Do not invert the matrix before applying. This causes an additive effect. +.TP +.BI "\-s " "[ijkphrxyz]" +Specify the components of the transform that are to be applied. Use any combination of the nine token letters: i, j, k represent the three scale axes; h, p, r represent rotation; and x, y, z represent translation. The default is everything: -s ijkphrxyz. +.TP +.BI "\-r " "file.egg" +Read the animation channel from the indicated egg file. If this is not specified, each egg file will supply its own animation channel. +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. This is only valid when there is only one input egg file on the command line. If you want to process multiple files simultaneously, you must use either -d or -inplace. +.TP +.BI "\-d " "dirname" +Specify the name of the directory in which to write the resulting egg files. If you are processing only one egg file, this may be omitted in lieu of the -o option. If you are processing multiple egg files, this may be omitted only if you specify -inplace instead. +.TP +.B \-inplace +If this option is given, the input egg files will be rewritten in place with the results. This obviates the need to specify -d for an output directory; however, it's risky because the original input egg files are lost. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system to operate in. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.BI "\-inf " "filename" +Reads input args from a text file instead of the command line. Useful for really, really large lists of args that break the OS-imposed limits on the length of command lines. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg-trans.1 b/doc/man/egg-trans.1 new file mode 100644 index 0000000000..f615a540bd --- /dev/null +++ b/doc/man/egg-trans.1 @@ -0,0 +1,117 @@ +.\" Automatically generated by egg-trans -write-bam +.TH EGG-TRANS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg-trans \- apply transformations and optimizations to an .egg file +.SH SYNOPSIS +\fBegg-trans\fR [opts] -o output.egg input.egg +.br +\fBegg-trans\fR [opts] input.egg >output.egg +.SH DESCRIPTION +egg\-trans reads an egg file and writes an essentially equivalent egg file to the standard output, or to the file specified with \-o. Some simple operations on the egg file are supported. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-F +Flatten out transforms. +.TP +.B \-t +Apply texture matrices to UV's. +.TP +.B \-T +Collapse equivalent texture references. +.TP +.B \-c +Clean out degenerate polygons and unused vertices. +.TP +.B \-C +Clean out higher-order polygons by subdividing into triangles. +.TP +.B \-mesh +Mesh triangles into triangle strips. This is mainly useful as a tool to visualize the work that the mesher will do, since triangles are automatically meshed whenever an egg file is loaded. Note that, unlike the automatic meshing at load time, you are must ensure that you do not start out with multiple triangles with different attributes (e.g. texture) together in the same group. +.TP +.B \-N +Standardize and uniquify group names. +.TP +.BI "\-ct " "threshold" +Implies -c, but sets the threshold for determining whether two vertex positions are equivalent. A higher value here may be used to merge adjacent vertices together, and an even higher value can be used to reduce the density of a model. +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.BI "\-td " "dirname" +Copy textures to the indicated directory. The copy is performed only if the destination file does not exist or is older than the source file. +.TP +.BI "\-te " "ext" +Rename textures to have the indicated extension. This also automatically copies them to the new filename (possibly in a different directory if -td is also specified), and may implicitly convert to a different image format according to the extension. +.TP +.BI "\-tt " "type" +Explicitly specifies the image format to convert textures to when copying them via -td or -te. Normally, this is unnecessary as the image format can be determined by the extension, but sometimes the extension is insufficient to unambiguously specify an image type. +.TP +.BI "\-delod " "dist" +Eliminate LOD's by choosing the level that would be appropriate for a camera at the indicated fixed distance from each LOD. Use -delod -1 to keep all the LOD's as they are, which is the default. + +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the egg file is written to standard output. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting egg file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is the same coordinate system as the input egg file. If this is different from the input egg file, a conversion will be performed. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg2bam.1 b/doc/man/egg2bam.1 new file mode 100644 index 0000000000..28caf2b502 --- /dev/null +++ b/doc/man/egg2bam.1 @@ -0,0 +1,81 @@ +.\" Automatically generated by egg2bam -write-bam +.TH EGG2BAM 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg2bam \- convert .egg files to .bam files +.SH SYNOPSIS +\fBegg2bam\fR [opts] input.egg output.bam +.br +\fBegg2bam\fR [opts] -o output.bam input.egg +.SH DESCRIPTION +This program reads Egg files and outputs Bam files, the binary format suitable for direct loading of animation and models into Panda. Bam files are tied to a particular version of Panda, so should not be considered replacements for egg files, but they tend to be smaller and load much faster than the equivalent egg files. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-flatten " "flag" +Specifies whether to flatten the egg hierarchy after it is loaded. If flag is zero, the egg hierarchy will not be flattened, but will instead be written to the bam file exactly as it is. If flag is non-zero, the hierarchy will be flattened so that unnecessary nodes (usually group nodes with only one child) are eliminated. The default if this is not specified is taken from the egg-flatten Config.prc variable. +.TP +.BI "\-combine-geoms " "flag" +Specifies whether to combine sibling GeomNodes into a common GeomNode when possible. This flag is only respected if flatten, above, is also enabled (or implicitly true from the Config.prc file). The default if this is not specified is taken from the egg-combine-geoms Config.prc variable. +.TP +.BI "\-suppress-hidden " "flag" +Specifies whether to suppress hidden geometry. If this is nonzero, egg geometry tagged as "hidden" will be removed from the final scene graph; otherwise, it will be preserved (but stashed). The default is nonzero, to remove it. +.TP +.B \-ls +Writes a scene graph listing to standard output after the egg file has been loaded, showing the nodes that will be written out. +.TP +.BI "\-C " "quality" +Specify the quality level for lossy channel compression. If this is specified, the animation channels will be compressed at this quality level, which is normally an integer value between 0 and 100, inclusive, where higher numbers produce larger files with greater quality. Generally, 95 is the highest useful quality level. Use -NC (described below) to disable channel compression. If neither option is specified, the default comes from the Config.prc file. +.TP +.B \-NC +Turn off lossy compression of animation channels. Channels will be written exactly as they are, losslessly. +.TP +.B \-rawtex +Record texture data directly in the bam file, instead of storing a reference to the texture elsewhere on disk. The textures are stored uncompressed, unless -ctex is also specified. A particular texture that is encoded into multiple different bam files in this way cannot be unified into the same part of texture memory if the different bam files are loaded together. That being said, this can sometimes be a convenient way to ensure the bam file is completely self-contained. +.TP +.B \-txo +Rather than writing texture data directly into the bam file, as in -rawtex, create a texture object for each referenced texture. A texture object is a kind of mini-bam file, with a .txo extension, that contains all of the data needed to recreate a texture, including its image contents, filter and wrap settings, and so on. 3-D textures and cube maps can also be represented in a single .txo file. Texture object files, like bam files, are tied to a particular version of Panda. +.TP +.B \-txopz +In addition to writing texture object files as above, compress each one using pzip to a .txo.pz file. In many cases, this will yield a disk file size comparable to that achieved by png compression. This is an on-disk compression only, and does not affect the amount of RAM or texture memory consumed by the texture when it is loaded. +.TP +.B \-ctex +Pre-compress the texture images using the libsquish library, when using -rawtex or -txo. This is unrelated to the on-disk compression achieved via -txopz (and it may be used in conjunction with that parameter). This will result in a smaller RAM and texture memory footprint for the texture images. The same effect can be achieved at load time by setting compressed-textures in your Config.prc file; but -ctex pre-compresses the textures so that they do not need to be compressed at load time. +.TP +.B \-mipmap +Records the pre-generated mipmap levels in the texture object file when using -rawtex or -txo, regardless of the texture filter mode. This will increase the size of the texture object file by about 33%, but it prevents the need to compute the mipmaps at runtime. The default is to record mipmap levels only when the texture uses a mipmap filter mode. +.TP +.BI "\-ctexq " "quality" +Specifies the compression quality to use when performing the texture compression requested by -ctex. This may be one of 'default', 'fastest', 'normal', or 'best'. The default is 'best'. Set it to 'default' to use whatever is specified by the Config.prc file. This is a global setting only; individual texture quality settings appearing within the egg file will override this. +.TP +.BI "\-load-display " "display name" +Specifies the particular display module to load to perform the texture compression requested by -ctex. If this is omitted, the default is taken from the Config.prc file. Since your Panda has libsquish compiled in, this is not necessary; Panda can compress textures without loading a display module. +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting Bam file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting Bam file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is z-up. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg2c.1 b/doc/man/egg2c.1 new file mode 100644 index 0000000000..2aa826bc2c --- /dev/null +++ b/doc/man/egg2c.1 @@ -0,0 +1,49 @@ +.\" Automatically generated by egg2c -write-bam +.TH EGG2C 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg2c \- convert .egg geometry into compilable C tables +.SH SYNOPSIS +\fBegg2c\fR [opts] input.egg output.c +.br +\fBegg2c\fR [opts] -o output.c input.egg +.br +\fBegg2c\fR [opts] input.egg >output.c +.SH DESCRIPTION +This program reads Egg files and outputs code that will almost compile as a C or C++ program. You get to define the data structures for the program after the fact; the program only generates tables of vertices and polygons. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-v +Generate a table of vertex positions. +.TP +.B \-u +Generate a table of UV's per each vertex. +.TP +.B \-vn +Generate a table of normals per each vertex. +.TP +.B \-vc +Generate a table of colors per each vertex. +.TP +.B \-p +Generate a table of polygons that index into the above tables. +.TP +.B \-pn +Generate a table of normals per each polygon. +.TP +.B \-pc +Generate a table of colors per each polygon. +.TP +.B \-t +Output only triangles by subdividing higher-order polygons. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting C file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting C file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is the same coordinate system as the input egg file. If this is different from the input egg file, a conversion will be performed. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg2dxf.1 b/doc/man/egg2dxf.1 new file mode 100644 index 0000000000..3eb38a6c1d --- /dev/null +++ b/doc/man/egg2dxf.1 @@ -0,0 +1,29 @@ +.\" Automatically generated by egg2dxf -write-bam +.TH EGG2DXF 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg2dxf \- convert .egg files to AutoCAD .dxf files +.SH SYNOPSIS +\fBegg2dxf\fR [opts] input.egg output.dxf +.br +\fBegg2dxf\fR [opts] -o output.dxf input.egg +.SH DESCRIPTION +This program converts files from egg format to AutoCAD DXF format. Since DXF does not support nested hierarchies, vertex normals, or any fancy stuff you are probably used to, there is some information lost in the conversion +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-p +Use POLYLINE to represent polygons instead of the default, 3DFACE. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting DXF file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting DXF file. This may be one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is the same coordinate system as the input egg file. If this is different from the input egg file, a conversion will be performed. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg2flt.1 b/doc/man/egg2flt.1 new file mode 100644 index 0000000000..7c19ac7697 --- /dev/null +++ b/doc/man/egg2flt.1 @@ -0,0 +1,26 @@ +.\" Automatically generated by egg2flt -write-bam +.TH EGG2FLT 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg2flt \- convert files from .egg format to MultiGen .flt +.SH SYNOPSIS +\fBegg2flt\fR [opts] input.egg output.flt +.br +\fBegg2flt\fR [opts] -o output.flt input.egg +.SH DESCRIPTION +egg2lt converts files from egg format to MultiGen .flt format. It attempts to be as robust as possible, and matches the capabilities of flt2egg. Generally, converting a model from egg2lt and then back via flt2egg will result in essentially the same egg file, within the limitations of what can be represented in flt. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.BI "\-attr " "none/new/all" +Specifies whether to write (or rewrite) .attr files for each texture image. MultiGen stores texture properties like mipmapping in a separate .attr file for each different texture image. If this parameter is "none", these files will not be generated; if this is "new", these files will only be generated if they do not already exist (even if the properties have changed). Specifying "all" causes these to be rewritten every time. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting MultiGen file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg2obj.1 b/doc/man/egg2obj.1 new file mode 100644 index 0000000000..74d773a57f --- /dev/null +++ b/doc/man/egg2obj.1 @@ -0,0 +1,29 @@ +.\" Automatically generated by egg2obj -write-bam +.TH EGG2OBJ 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg2obj \- convert .egg files to .obj +.SH SYNOPSIS +\fBegg2obj\fR [opts] input.egg output.obj +.br +\fBegg2obj\fR [opts] -o output.obj input.egg +.SH DESCRIPTION +This program converts egg files to obj. It only converts polygon data, with no fancy tricks. Very bare\-bones at the moment; not even texture maps are supported. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-C +Clean out higher-order polygons by subdividing into triangles. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting Obj file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the resulting Obj file. Normally, this is z-up. +.TP +.B \-f +Force complete loading: load up the egg file along with all of its external references. +.TP +.B \-h +Display this help page. diff --git a/doc/man/egg2x.1 b/doc/man/egg2x.1 new file mode 100644 index 0000000000..03a5c19880 --- /dev/null +++ b/doc/man/egg2x.1 @@ -0,0 +1,35 @@ +.\" Automatically generated by egg2x -write-bam +.TH EGG2X 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +egg2x \- convert an .egg file into a DirectX .x file +.SH SYNOPSIS +\fBegg2x\fR [opts] input.egg output.x +.br +\fBegg2x\fR [opts] -o output.x input.egg +.SH DESCRIPTION +This program reads an Egg file and outputs an equivalent, or nearly equivalent, DirectX\-style .x file. Only simple hierarchy and polygon meshes are supported; advanced features like LOD's, decals, and animation or skinning are not supported. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input egg file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-m +Convert all the objects in the egg file as one big mesh, instead of preserving the normal egg hierarchy. +.TP +.BI "\-td " "dirname" +Copy textures to the indicated directory. The copy is performed only if the destination file does not exist or is older than the source file. +.TP +.BI "\-te " "ext" +Rename textures to have the indicated extension. This also automatically copies them to the new filename (possibly in a different directory if -td is also specified), and may implicitly convert to a different image format according to the extension. +.TP +.BI "\-tt " "type" +Explicitly specifies the image format to convert textures to when copying them via -td or -te. Normally, this is unnecessary as the image format can be determined by the extension, but sometimes the extension is insufficient to unambiguously specify an image type. +.TP +.BI "\-delod " "dist" +Eliminate LOD's by choosing the level that would be appropriate for a camera at the indicated fixed distance from each LOD. Use -delod -1 to keep all the LOD's as they are. The default value is 0. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting DirectX file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.B \-h +Display this help page. diff --git a/doc/man/flt-info.1 b/doc/man/flt-info.1 new file mode 100644 index 0000000000..b05a07d5c7 --- /dev/null +++ b/doc/man/flt-info.1 @@ -0,0 +1,15 @@ +.\" Automatically generated by flt-info -write-bam +.TH FLT-INFO 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +flt-info \- describe the contents of a MultiGen .flt file +.SH SYNOPSIS +\fBflt-info\fR [opts] input.flt +.SH DESCRIPTION +This program reads a MultiGen OpenFlight (.flt) file and reports some interesting things about its contents. +.SH OPTIONS +.TP +.B \-ls +List the hierarchy in the flt file. +.TP +.B \-h +Display this help page. diff --git a/doc/man/flt-trans.1 b/doc/man/flt-trans.1 new file mode 100644 index 0000000000..c41c142c97 --- /dev/null +++ b/doc/man/flt-trans.1 @@ -0,0 +1,39 @@ +.\" Automatically generated by flt-trans -write-bam +.TH FLT-TRANS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +flt-trans \- apply various operations to a MultiGen .flt file +.SH SYNOPSIS +\fBflt-trans\fR [opts] input.flt output.flt +.br +\fBflt-trans\fR [opts] -o output.flt input.flt +.SH DESCRIPTION +This program reads a MultiGen OpenFlight (.flt) file and writes an essentially equivalent .flt file, to the file specified with \-o (or as the second parameter). Some simple operations may be performed. +.SH OPTIONS +.TP +.BI "\-v " "version" +Upgrade (or downgrade) the flt file to the indicated version. This may not be completely correct for all version-to-version combinations. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting .flt file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.B \-h +Display this help page. diff --git a/doc/man/flt2egg.1 b/doc/man/flt2egg.1 new file mode 100644 index 0000000000..1796b7b543 --- /dev/null +++ b/doc/man/flt2egg.1 @@ -0,0 +1,94 @@ +.\" Automatically generated by flt2egg -write-bam +.TH FLT2EGG 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +flt2egg \- convert a MultiGen .flt file to .egg +.SH SYNOPSIS +\fBflt2egg\fR [opts] input.flt output.egg +.br +\fBflt2egg\fR [opts] -o output.egg input.flt +.br +\fBflt2egg\fR [opts] input.flt >output.egg +.SH DESCRIPTION +This program converts MultiGen OpenFlight (.flt) files to egg. Most features of MultiGen that are also recognized by egg are supported. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input MultiGen file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.B \-ignore +Ignore non-fatal errors and generate an egg file anyway. +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.BI "\-ui " "units" +Specify the units of the input MultiGen file. Normally, this can be inferred from the file itself. +.TP +.BI "\-uo " "units" +Specify the units of the resulting egg file. If this is specified, the vertices in the egg file will be scaled as necessary to make the appropriate units conversion; otherwise, the vertices will be left as they are. +.TP +.B \-f +Follow and convert all external references in the source file. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the input MultiGen file. Normally, this is z-up. +.TP +.B \-h +Display this help page. diff --git a/doc/man/fltcopy.1 b/doc/man/fltcopy.1 new file mode 100644 index 0000000000..59632efe50 --- /dev/null +++ b/doc/man/fltcopy.1 @@ -0,0 +1,44 @@ +.\" Automatically generated by fltcopy -write-bam +.TH FLTCOPY 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +fltcopy \- copy MultiGen .flt files into a CVS source hierarchy +.SH SYNOPSIS +\fBfltcopy\fR [opts] file.flt [file.flt ... ] +.SH DESCRIPTION +fltcopy copies one or more MultiGen .flt files into a CVS source hierarchy. Rather than copying the named files immediately into the current directory, it first scans the entire source hierarchy, identifying all the already\-existing files. If the named file to copy matches the name of an already\-existing file in the current directory or elsewhere in the hierarchy, that file is overwritten. Other .flt files, as well as texture files, that are externally referenced by the named .flt file(s) are similarly copied. +.SH OPTIONS +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.B \-f +Force the copy to happen without any input from the user. If a file with the same name exists anywhere in the source hierarchy, it will be overwritten without prompting; if a file does not yet exist, it will be created in the directory named by -d or by -m, as appropriate. +.TP +.B \-i +The opposite of -f, this will prompt the user before each action. The default is only to prompt the user when an action is ambiguous or unusual. +.TP +.BI "\-d " "dirname" +Copy model files that are not already present somewhere in the tree to the indicated directory. The default is the current directory. +.TP +.BI "\-m " "dirname" +Copy texture map files to the indicated directory. The default is src/maps from the root directory. +.TP +.BI "\-root " "dirname" +Specify the root of the CVS source hierarchy. The default is to use the ppremake convention of locating the directory above the -d directory that contains a file called Package.pp. +.TP +.BI "\-key " "filename" +Specify the name of the file that must exist in each directory for it to be considered part of the CVS source hierarchy. The default is the ppremake convention, "Sources.pp". Other likely candidates are "CVS" to search a CVS hierarchy, or "." to include all subdirectories indiscriminately. +.TP +.B \-nc +Do not attempt to add newly-created files to CVS. The default is to add them. +.TP +.BI "\-cvs " "cvs_binary" +Specify how to run the cvs program for adding newly-created files. The default is simply "cvs". +.TP +.B \-h +Display this help page. diff --git a/doc/man/image-info.1 b/doc/man/image-info.1 new file mode 100644 index 0000000000..60f693f54e --- /dev/null +++ b/doc/man/image-info.1 @@ -0,0 +1,14 @@ +.\" Automatically generated by image-info -write-bam +.TH IMAGE-INFO 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +image-info \- report the size of image files +.SH SYNOPSIS +.SH DESCRIPTION +This program reads the headers of a series of one or more image files and reports the image sizes to standard output. +.SH OPTIONS +.TP +.B \-2 +Report only images that have a non-power-of-two size in either dimension. Images whose dimensions are both a power of two will not be mentioned. +.TP +.B \-h +Display this help page. diff --git a/doc/man/image-resize.1 b/doc/man/image-resize.1 new file mode 100644 index 0000000000..27a5dbb66e --- /dev/null +++ b/doc/man/image-resize.1 @@ -0,0 +1,29 @@ +.\" Automatically generated by image-resize -write-bam +.TH IMAGE-RESIZE 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +image-resize \- resize an image file +.SH SYNOPSIS +\fBimage-resize\fR [opts] inputimage outputimage +.br +\fBimage-resize\fR [opts] -o outputimage inputimage +.SH DESCRIPTION +This program reads an image file and resizes it to a larger or smaller image file. +.SH OPTIONS +.TP +.BI "\-x " "xsize" +Specify the width of the output image in pixels, or as a percentage of the original width (if a trailing percent sign is included). If this is omitted, the ratio is taken from the ysize parameter. +.TP +.BI "\-y " "ysize" +Specify the height of the output image in pixels, or as a percentage of the original height (if a trailing percent sign is included). If this is omitted, the ratio is taken from the xsize parameter. +.TP +.BI "\-g " "radius" +Use Gaussian filtering to resize the image, with the indicated radius. +.TP +.B \-1 +This option is ignored. It is provided only for backward compatibility with a previous version of image-resize. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting image file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.B \-h +Display this help page. diff --git a/doc/man/image-trans.1 b/doc/man/image-trans.1 new file mode 100644 index 0000000000..943902d643 --- /dev/null +++ b/doc/man/image-trans.1 @@ -0,0 +1,35 @@ +.\" Automatically generated by image-trans -write-bam +.TH IMAGE-TRANS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +image-trans \- apply transformations to an image file +.SH SYNOPSIS +\fBimage-trans\fR [opts] inputimage outputimage +.br +\fBimage-trans\fR [opts] -o outputimage inputimage +.SH DESCRIPTION +This program reads an image file and writes a similar image file to the output. It can implicitly convert from one image file format to another; it uses the extension of the output filename to specify the destination file format. +.SH OPTIONS +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting image file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.BI "\-chan " "channels" +Elevate (or truncate) the image to the indicated number of channels. This may be 1, 2, 3, or 4. You may also specify one of the keywords l, la, rgb, or rgba, respectively, or any of the keywords r, g, b, or a to extract out just the indicated channel as a single grayscale image. +.TP +.BI "\-cscale " "r,g,b[,a]" +Apply the indicated color scale to each pixel of the image. +.TP +.B \-flip +Flip the image vertically. +.TP +.B \-mirror +Reverse the image horizontally. +.TP +.B \-cw +Rotate the image 90 degrees clockwise. +.TP +.B \-ccw +Rotate the image 90 degrees counter-clockwise. +.TP +.B \-h +Display this help page. diff --git a/doc/man/interrogate.1 b/doc/man/interrogate.1 new file mode 100644 index 0000000000..1bea02091e --- /dev/null +++ b/doc/man/interrogate.1 @@ -0,0 +1,186 @@ +.TH INTERROGATE 1 "27 December 2014" "" Panda3D +.SH NAME +interrogate \- generate scripting language bindings for C/C++ APIs +.SH SYNOPSIS +.B interrogate +[ +.I opts +] +.I file.C +[ +.I file.C ... +] +.SH DESCRIPTION +Interrogate is a program to parse a body of C++ code and build up a table +of classes, methods, functions, and symbols found, for the purposes of +calling into the codebase via a non-C++ scripting language like Scheme, +Smalltalk, or Python. +.PP +In addition to identifying all the classes and their relationships, +interrogate will generate a wrapper function for each callable function. +The wrapper functions will be callable directly from the scripting language, +with no understanding of C++ necessary; these wrapper functions will in turn +call the actual C++ functions or methods. +.PP +Most exportable features of C++ are supported, including templates, default +parameters, and function overloading. +.SH OPTIONS +.TP +.BI "\-oc " output.C +Specify the name of the file to which generated code will be written. +This includes all of the function wrappers, as well as those tables +which must be compiled into the library. +.TP +.BI "\-od " output.in +Specify the name of the file to which the non-compiled data tables +will be written. This file describes the relationships between +all the types and the functions, and associates the function wrappers +above with this data. This file will be opened and read at runtime +when the scripting language first calls some interrogate query +function. +.TP +.BI "\-srcdir " directory +Specify the name of the directory to which the source filenames are +relative. +.TP +.BI "\-module " module_name +Defines the name of the module this data is associated with. This +is strictly a code-organizational tool. Conceptually, a module is +the highest level of grouping for interrogate data; a module may +contain several libraries. If this is omitted, no module name is +specified. +.PP +Sometimes, depending on the type of wrappers being generated, there +may be additional code that needs to be generated on the module +level, above that which was already generated at the library level. +Python, for instance, generates the table of python-callable function +wrappers at the module level. Use the program +.BR interrogate_module (1) +to generate the appropriate code at the module level. +.TP +.BI "\-library " library_name +Defines the name of the library this data is associated with. This +is another code-organizational tool. Typically, there will be one +invocation of interrogate for each library, and there will be +multiple libraries per module. If this is omitted, no library name +is specified. +.TP +.B \-do\-module +Generate whatever module-level code should be generated immediately, +rather than waiting for a special +.BR interrogate_module (1) +pass. This, of course, prohibits grouping several libraries together +into a single module. +.TP +.B \-fptrs +Make void* pointers to the function wrappers directly available. A +scripting language will be able to call the interrogate functions +directly by pointer. +.TP +.B \-fnames +Make the names of the function wrappers public symbols so that the +scripting language will be able to call the interrogate functions +by name. +.PP +Either or both of \fB\-fptrs\fP and/or \fB\-fnames\fP may be specified. +If both are omitted, the default is \fB\-fnames\fP. +.TP +.B \-string +Treat char* and basic_string as special cases, and map +parameters of these types to type atomic string. The scripting +language will see only functions that receive and return strings, +not pointers to character or structures of basic_string. +If C calling convention wrappers are being generated, the atomic +string type means type char*. In any other calling convention, the +atomic string type is whatever the native string type is. +.TP +.B \-refcount +Treat classes that inherit from a class called ReferenceCount as a +special case. Any wrapper function that returns a pointer to +one of these classes will automatically increment the reference +count by calling ref() on the object first, and any destructors +that are generated will call unref_delete() on the object instead of +simply delete. +.PP +Furthermore, parameters of type PointerTo or ConstPointerTo +will automatically be mapped to N * and const N *, respectively. +.TP +.B \-assert +Generate code in each wrapper that will check the state of the assert +flag and trigger an exception in the scripting language when a +C++ assertion fails. Presently, this only has meaning to the Python +wrappers. +.TP +.B \-true\-names +Use the actual name of the function being wrapped as the name of +the generated wrapper function, instead of an ugly hash name. +This means the wrapper functions may be called directly using a +meaningful name (especially if \fB\-fnames\fP is also given), but it +also means that C++ function overloading (including default values +for parameters) cannot be used, as it will lead to multiple wrapper +functions with the same name. +.TP +.B \-c +Generate function wrappers using the C calling convention. Any +scripting language that can call a C function should be able to +make advantage of the interrogate database. +.TP +.B \-python +Generate function wrappers using the Python calling convention. +The shared library will be directly loadable as a Python module +(especially if the module definitions are made available either by +running +.BR interrogate_module (1) +later, or by specifying \fB\-do\-module\fP on the command line now). +However, C++ objects and methods will be converted into an object +handle and a list of independent Python functions. +.TP +.B \-python\-obj +Generate Python function wrappers that convert C++ objects to true +python objects, with all methods converted to Python methods. This +is currently experimental. +.TP +.B \-python\-native +Generate Python function wrappers that convert C++ objects to true +python objects, with all methods converted to Python methods. This +is the recommended method for creating Python wrappers. +.PP +Any combination of \fB\-c\fP, \fB\-python\fP, or \fB\-python\-obj\fP +may be specified. If all are omitted, the default is \fB\-c\fP. +.TP +.B \-track\-interpreter +Generate code within each wrapper function to adjust the global +variable "in_interpreter" to indicated whether code is running +within the Panda C++ environment or within the high-level language. +.TP +.B \-unique\-names +Compile a table into the library (i.e. generate code into the +\fB\-oc\fP file) that defines a lookup of each function wrapper by +its unique name. This makes it possible to consistently identify +function wrappers between sessions, at the cost of having this +additional table in memory. +.TP +.B \-nodb +Do not build a full interrogate database, but just generate function +wrappers. It is assumed that the user will know how to call the +function wrappers already, from some external source. This is most +useful in conjunction with \fB\-true\-names\fP. +.TP +.BI "\-longlong " typename +Specify the name of the 64-bit integer type for the current compiler. +By default, this is "long long". +.TP +.B \-promiscuous +Export *all* public symbols, functions, and classes seen, even those +not explicitly marked to be published. +.TP +.B \-spam +Generate wrapper functions that report each invocation to Notify. +This can sometimes be useful for tracking down bugs. +.TP +.B \-noangles +Treat #include the same as #include "file". This means +\fB\-I\fP and \fB\-S\fP are equivalent. +.SH "SEE ALSO" +.BR interrogate_module (1), +.BR test_interrogate (1) diff --git a/doc/man/interrogate_module.1 b/doc/man/interrogate_module.1 new file mode 100644 index 0000000000..289c65d691 --- /dev/null +++ b/doc/man/interrogate_module.1 @@ -0,0 +1,69 @@ +.TH INTERROGATE_MODULE 1 "26 December 2014" "" Panda3D +.SH NAME +interrogate_module \- generate module-level code for interrogate +.SH SYNOPSIS +.B interrogate_module +[ +.I opts +] +.I libname.in +[ +.I libname.in ... +] +.SH DESCRIPTION +This program generates a module-level file for the +.BR interrogate (1) program. +This is a higher level than library, and groups several libraries +together. In particular, the code generated by interrogate_module +typically includes a table of the classes that are to be exported +to Python. +.SH OPTIONS +.TP +.BI "\-oc " output.C +Specify the name of the file to which generated code will be written. +.TP +.BI "\-module " module_name +Defines the name of the module this data is associated with. This +is strictly a code-organizational tool. Conceptually, a module is +the highest level of grouping for interrogate data; a module may +contain several libraries. If this is omitted, no module name is +specified. +.TP +.BI "\-library " library_name +Defines the name of the library this data is associated with. This +is another code-organizational tool. Typically, there will be one +invocation of interrogate for each library, and there will be +multiple libraries per module. If this is omitted, no library name +is specified. +.TP +.B \-c +Generate function wrappers using the C calling convention. Any +scripting language that can call a C function should be able to +make advantage of the interrogate database. +.TP +.B \-python +Generate function wrappers using the Python calling convention. +The shared library will be directly loadable as a Python module. +However, C++ objects and methods will be converted into an object +handle and a list of independent Python functions. +.TP +.B \-python\-obj +Generate Python function wrappers that convert C++ objects to true +python objects, with all methods converted to Python methods. This +is currently experimental. +.TP +.B \-python\-native +Generate Python function wrappers that convert C++ objects to true +python objects, with all methods converted to Python methods. This +is the recommended method for creating Python wrappers. +.PP +Any combination of \fB\-c\fP, \fB\-python\fP, or \fB\-python\-obj\fP +may be specified. If all are omitted, the default is \fB\-c\fP. +.TP +.B \-track\-interpreter +Generate code within each wrapper function to adjust the global +variable "in_interpreter" to indicated whether code is running +within the Panda C++ environment or within the high-level language. +.SH "SEE ALSO" +.BR interrogate (1), +.BR test_interrogate (1) diff --git a/doc/man/lwo-scan.1 b/doc/man/lwo-scan.1 new file mode 100644 index 0000000000..9da0cf39ae --- /dev/null +++ b/doc/man/lwo-scan.1 @@ -0,0 +1,12 @@ +.\" Automatically generated by lwo-scan -write-bam +.TH LWO-SCAN 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +lwo-scan \- describe the contents of a Lightwave object file +.SH SYNOPSIS +\fBlwo-scan\fR [opts] input.lwo +.SH DESCRIPTION +This program simply reads a Lightwave object file and dumps its contents to standard output. It's mainly useful for debugging problems with lwo2egg. +.SH OPTIONS +.TP +.B \-h +Display this help page. diff --git a/doc/man/lwo2egg.1 b/doc/man/lwo2egg.1 new file mode 100644 index 0000000000..7f80833a09 --- /dev/null +++ b/doc/man/lwo2egg.1 @@ -0,0 +1,91 @@ +.\" Automatically generated by lwo2egg -write-bam +.TH LWO2EGG 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +lwo2egg \- convert a Lightwave Object file to .egg +.SH SYNOPSIS +\fBlwo2egg\fR [opts] input.lwo output.egg +.br +\fBlwo2egg\fR [opts] -o output.egg input.lwo +.br +\fBlwo2egg\fR [opts] input.lwo >output.egg +.SH DESCRIPTION +This program converts Lightwave Object (.lwo) files to egg. Many rendering characteristics of Lightwave (like layered shaders, etc.) are not supported, but fundamental things like polygons and texture maps are. This program is primarily designed to support files written by Lightwave version 6.x (LWO2 files), but it also has some limited support for version 5.x files (LWOB files). +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input Lightwave file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.B \-ignore +Ignore non-fatal errors and generate an egg file anyway. +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.BI "\-ui " "units" +Specify the units of the input Lightwave file. By convention, this is assumed to be meters if it is unspecified. +.TP +.BI "\-uo " "units" +Specify the units of the resulting egg file. If this is specified, the vertices in the egg file will be scaled as necessary to make the appropriate units conversion; otherwise, the vertices will be left as they are. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the input Lightwave file. Normally, this is y-up-left. +.TP +.B \-h +Display this help page. diff --git a/doc/man/make-prc-key.1 b/doc/man/make-prc-key.1 new file mode 100644 index 0000000000..ca4f4beedf --- /dev/null +++ b/doc/man/make-prc-key.1 @@ -0,0 +1,56 @@ +.TH MAKE-PRC-KEY 1 "27 December 2014" "" Panda3D +.SH NAME +make-prc-key \- generate keys for signing .prc files +.SH SYNOPSIS +.B make-prc-key +[\fIopts\fP] +1[,"\fIpass_phrase\fP"] [2[,"\fIpass_phrase\fP"] 3 ...] +.SH DESCRIPTION +This program generates one or more new keys to be used for signing +a prc file. The key itself is a completely arbitrary random bit +sequence. It is divided into a public and a private key; the public +key is not secret and will be compiled into libdtool, while the private +key should be safeguarded and will be written into a .cxx file that +can be compiled as a standalone application. +.PP +The output is a public and private key pair for each trust level. The +form of the output for both public and private keys will be compilable +C++ code; see \-a and \-b, below, for a complete description. +.PP +After the options, the remaining arguments list the individual trust +level keys to generate. For each integer specified, a different key +will be created. There should be one key for each trust level +required; a typical application will only need one or two keys. +.SH OPTIONS +.TP +.BI "\-a " pub_outfile.cxx +Specifies the name and location of the public key output file +to generate. This file must then be named by the Config.pp +variable PRC_PUBLIC_KEYS_FILENAME so that it will be compiled +in with libdtool and available to verify signatures. If this +option is omitted, the previously-compiled value is used. +.TP +.BI "\-b " priv_outfile#.cxx +Specifies the name and location of the private key output file(s) +to generate. A different output file will be generated for each +different trust level; the hash mark '#' appearing in the file +name will be filled in with the corresponding numeric trust level. +The hash mark may be omitted if you only require one trust level. +When compiled against dtool, each of these files will generate +a program that can be used to sign a prc file with the corresponding +trust level. +.TP +.BI "\-p " passphrase +Uses the indicated pass phrase to encrypt the private key. +This specifies an overall pass phrase; you may also specify +a different pass phrase for each key by using the +\fIkey\fB,"\fIpassphrase\fB"\fR syntax. +.PP +If a pass phrase is not specified on the command line, you will be +prompted interactively. Every user of the signing programs +(outfile_sign1.cxx, etc.) will need to know the pass phrase +in order to sign prc files. +.PP +If this is specified as the empty string (""), then the key +will not be encrypted, and anyone can run the signing +programs without having to supply a pass phrase. diff --git a/doc/man/multify.1 b/doc/man/multify.1 new file mode 100644 index 0000000000..62de0b48fe --- /dev/null +++ b/doc/man/multify.1 @@ -0,0 +1,156 @@ +.TH MULTIFY 1 "27 December 2014" "" Panda3D +.SH NAME +multify \- manipulate .mf multifiles +.SH SYNOPSIS +.B multify \-[c|r|u|t|x] -f +.I multifile_name.mf +[ +.I options +] +.I subfile_name ... +.SH DESCRIPTION +\fBmultify\fP is used to store and extract files from a Panda Multifile. +This is similar to a tar or zip file in that it is an archive file that +contains a number of subfiles that may later be extracted. +.PP +Panda's VirtualFileSystem is capable of mounting Multifiles for direct +access to the subfiles contained within without having to extract them +out to independent files first. +.PP +The command-line options for multify are designed to be similar to those +for \fBtar\fR(1), the traditional Unix archiver utility. +.SH OPTIONS +You must specify exactly one of the following command switches: +.TP +.B \-c +Create a new Multifile archive. Subfiles named on the command line +will be added to the new Multifile. If the Multifile already exists, +it is first removed. +.TP +.B \-r +Rewrite an existing Multifile archive. Subfiles named on the command +line will be added to the Multifile or will replace subfiles within +the Multifile with the same name. The Multifile will be repacked +after completion, even if no Subfiles were added. +.TP +.B \-u +Update an existing Multifile archive. This is similar to \fB\-r\fP, +except that files are compared byte\-for\-byte with their corresponding +files in the archive first. If they have not changed, the multifile +is not modified (other than to repack it if necessary). +.TP +.B \-t +List the contents of an existing Multifile. With -v, this shows +the size of each Subfile and its compression ratio, if compressed. +.TP +.B \-x +Extract the contents of an existing Multifile. The Subfiles named on +the command line, or all Subfiles if nothing is named, are extracted +into the current directory or into whichever directory is specified +with \fB\-C\fP. +.TP +.B \-k +Delete (kill) the named Subfiles from the Multifile. The Multifile +will be repacked after completion. +.PP +You must always specify the following switch: +.TP +.BI "\-f " multifile_name.mf +Names the Multifile that will be operated on. +.PP +The remaining switches are optional: +.TP +.B \-v +Run verbosely. In \-c, \-r, or \-x mode, list each file as it is +written or extracted. In \-t mode, list more information about each +file. +.TP +.B \-z +Compress subfiles as they are written to the Multifile. Unlike tar +(but like zip), subfiles are compressed individually, instead of the +entire archive being compressed as one stream. It is not necessary +to specify \-z when extracting compressed subfiles; they will always be +decompressed automatically. Also see \-Z, which restricts which +subfiles will be compressed based on the filename extension. +.TP +.B \-e +Encrypt subfiles as they are written to the Multifile using the password +specified with \-p, below. Subfiles are encrypted individually, rather +than encrypting the entire multifile, and different subfiles may be +encrypted using different passwords (although this requires running +multify multiple times). It is not possible to encrypt the multifile's +table of contents using this interface, but see the +.BR pencrypt (1) +program to encrypt the entire multifile after it has been generated. +.TP +.BI "\-p " password +Specifies the password to encrypt or decrypt subfiles. If this is not +specified, and passwords are required, the user will be prompted from +standard input. +.TP +.BI "\-P " prefix +Specifies a header_prefix to write to the beginning of the multifile. +This is primarily useful for creating a multifile that can be invoked +directly as a program from the shell on Unix-like environments, +for instance, p3d files. The header_prefix must begin with a hash +mark and end with a newline; this will be enforced if it is not +already so. This only has effect in conjunction with with -c, -u, +or -k. +.TP +.BI "\-F " scale_factor +Specify a Multifile scale factor. This is only necessary to support +Multifiles that will exceed 4GB in size. The default scale factor is +1, which should be sufficient for almost any application, but the total +size of the Multifile will be limited to 4GB * \fIscale_factor\fP. +The size of individual subfiles may not exceed 4GB in any case. +.TP +.BI "\-C " extract_dir +Change to the named directory before working on files; +that is, extraction/creation/update and replace will be based on this path +.TP +.BI "\-O +With \-x, extract subfiles to standard output instead of to disk. +.TP +.BI "\-Z " extension_list +Specify a comma-separated list of filename extensions that represent +files that are not to be compressed. The default if this is omitted is +"\fIjpg,png,mp3,ogg\fP". Specify \-Z "" (be sure to include the space) +to allow all files to be compressed. +.TP +.BI "\-X " extension_list +Specify a comma-separated list of filename extensions that represent +text files. These files are opened and read in text mode, and added to +the multifile with the text flag set. The default if this is omitted is +"\fItxt\fP". Specify \-X "" (be sure to include the space) to record +all files in binary mode. +.TP +.BI "\-T " flag +Enable or disable the recording of file timestamps within the multifile. +If \fIflag\fP is 1, timestamps will be recorded within the multifile for +each subfile added; this is the default behavior. If is 0, +timestamps will not be recorded, which will make it easier to do a +bitwise comparison between multifiles to determine whether their +contents are equivalent. +.TP +.B \-1 .. \-9 +Specify the compression level when \-z is in effect. Larger numbers +generate slightly smaller files, but compression takes longer. The +default is \-6. +.TP +.BI "\-S " file.crt[,chain.crt[,file.key[,"password"]]] +Sign the multifile. The signing certificate should be in PEM form in +\fIfile.crt\fP, with its private key in PEM form in \fIfile.key\fP. +If the key is encrypted on-disk, specify the decryption password as +the third option. If a certificate chain is required, \fIchain.crt\fP +should also be specified; note that the separating commas should be +supplied even if this optional filename is omitted. +You may also provide a single composite file that contains the +certificate, chain, and key in the same file. +PEM form is the form accepted by the Apache web server. The +signature is written to the multifile to prove it is unchanged; any +subsequent change to the multifile will invalidate the signature. +This parameter may be repeated to sign the multifile with additional +certificates. +.SH "SEE ALSO" +.BR pencrypt (1), +.BR pzip (1) diff --git a/doc/man/obj2egg.1 b/doc/man/obj2egg.1 new file mode 100644 index 0000000000..842f0527a7 --- /dev/null +++ b/doc/man/obj2egg.1 @@ -0,0 +1,75 @@ +.\" Automatically generated by obj2egg -write-bam +.TH OBJ2EGG 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +obj2egg \- convert .obj files to .egg +.SH SYNOPSIS +\fBobj2egg\fR [opts] input.obj output.egg +.br +\fBobj2egg\fR [opts] -o output.egg input.obj +.br +\fBobj2egg\fR [opts] input.obj >output.egg +.SH DESCRIPTION +This program converts obj files to egg. It only converts polygon data, with no fancy tricks. Very bare\-bones at the moment; not even texture maps are supported. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input obj file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.B \-ignore +Ignore non-fatal errors and generate an egg file anyway. +.TP +.BI "\-ui " "units" +Specify the units of the input obj file. Normally, this can be inferred from the file itself. +.TP +.BI "\-uo " "units" +Specify the units of the resulting egg file. If this is specified, the vertices in the egg file will be scaled as necessary to make the appropriate units conversion; otherwise, the vertices will be left as they are. +.TP +.B \-points +Construct entries for any unreferenced vertices, to make them visible. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the input obj file. Normally, this is z-up. +.TP +.B \-h +Display this help page. diff --git a/doc/man/p3dcparse.1 b/doc/man/p3dcparse.1 new file mode 100644 index 0000000000..6a37f09d2c --- /dev/null +++ b/doc/man/p3dcparse.1 @@ -0,0 +1,38 @@ +.TH DCPARSE 1 "27 December 2014" "" Panda3D +.SH NAME +dcparse \- read distributed class files +.SH SYNOPSIS +.B p3dcparse +[ +.I options +] [ +.I file1 file2 ... +] +.br +.B p3dcparse -h +.SH DESCRIPTION +This program reads one or more DC files, which are used to describe the +communication channels in the distributed class system. By default, +the file(s) are read and concatenated, and a single hash code is printed +corresponding to the file's contents. +.SH OPTIONS +.TP +.B \-v +Writes a complete parseable version of the file to standard +output instead of printing a hash code. +.TP +.B \-b +Writes a brief parseable version of the file instead of a full +version. This is semantically the same as the output produced +the above \fB\-v\fP option--reading it would produce exactly the +same results--but it is designed to be slightly obfuscated. The +comments and parameter names are not included. +.TP +.B \-c +Write a list of class names, showing the inheritance hierarchy. +Some class names will be listed twice in the presence of multiple +inheritance. +.TP +.B \-f +Write a complete list of field names available for each class, +including all inherited fields. diff --git a/doc/man/pdecrypt.1 b/doc/man/pdecrypt.1 new file mode 120000 index 0000000000..cafeec2fb0 --- /dev/null +++ b/doc/man/pdecrypt.1 @@ -0,0 +1 @@ +pencrypt.1 \ No newline at end of file diff --git a/doc/man/pencrypt.1 b/doc/man/pencrypt.1 new file mode 100644 index 0000000000..f1493da6fe --- /dev/null +++ b/doc/man/pencrypt.1 @@ -0,0 +1,92 @@ +.TH PENCRYPT 1 "27 December 2014" "" Panda3D +.SH NAME +pencrypt, pdecrypt \- encrypt or decrypt a file +.SH SYNOPSIS +.B pencrypt +[ +.I opts +] +.I file +[ +.I file2 file3 ... +] +.br +.B pencrypt -o +.I dest_file file +.PP +.B pdecrypt +[ +.B -p +.I password +] +.I file.pe +[ +.I file2.pe file3.pe ... +] +.br +.B pdecrypt +[ +.B -p +.I password +] +.B -o +.I dest_file file.pe +.SH DESCRIPTION +\fBpencrypt\fP will apply an encryption algorithm to a file (or multiple files), +creating an encrypted version of each file which can only be recovered using +pdecrypt and the same password that was supplied to \fBpencrypt\fP. The +compressed versions are written to a file with the same name as the original, +but the extension .pe added to the filename, and the original file is removed +(unless the version with \fB\-o\fP is used, in which case you can encrypt only +one file, you specify the destination file name, and the original file is not +removed). +.PP +Note that if you are adding files to a Panda multifile (.mf file) with the +.BR multify (1) +command, it is not necessary to encrypt them separately; \fBmultify\fP has an +inline encryption option. +.PP +\fBpdecrypt\fP reverses the operation of a previous \fBpdecrypt\fP command. +It decrypts the contents of the named source file(s) and removes the .pe +extension. The encryption algorithm need not be specified; it can be +determined by examining the header of each encrypted file. The password +must match the encryption password exactly. If it does not, an error may +or may not be reported; but the file will not be decrypted correctly even +if no error is reported. +.SH OPTIONS +.TP +.BI "\-p " \"password\" +Specifies the password to use for encryption. There are no +restrictions on the password length or contents, but longer passwords +are more secure. If this is not specified, the user is prompted from +standard input. +.PP +The following options are only available to \fBpencrypt\fP. These settings +are automatically read from the header of the encrypted file by \fBpdecrypt\fP. +.TP +.B \-t +Read the file as a text file. This will automatically convert universal +end-of-line characters into a newline character, ascii 10. +.TP +.BI "\-a " \"algorithm\" +Specifies the particular encryption algorithm to use. The complete +set of available algorithms is defined by the current version of +OpenSSL. The default algorithm is taken from the encryption- +algorithm config variable. +.TP +.BI "\-k " key_length +Specifies the key length, in bits, for the selected encryption +algorithm. This only makes sense for those algorithms that support +a variable key length. The default value is taken from the +\fBencryption\-key\-length\fP config variable. +.TP +.BI "\-i " iteration_count +Specifies the number of times the password is hashed to generate +a key. The only purpose of this is to make it computationally +more expensive for an attacker to search the key space exhaustively. +This should be a multiple of 1,000 and should not exceed about 65 +million; the value 0 indicates just one application of the hashing +algorithm. The default value is taken from the +\fBencryption\-iteration\-count\fP config variable. +.SH "SEE ALSO" +.BR multify (1) diff --git a/doc/man/pfm-bba.1 b/doc/man/pfm-bba.1 new file mode 100644 index 0000000000..691b361911 --- /dev/null +++ b/doc/man/pfm-bba.1 @@ -0,0 +1,17 @@ +.\" Automatically generated by pfm-bba -write-bam +.TH PFM-BBA 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +pfm-bba \- generate .bba files from .pfm files +.SH SYNOPSIS +.SH DESCRIPTION +pfm\-bba generates a .bba file from a .pfm file that lists the planar bounding volume of the pfm's internal data. +.SH OPTIONS +.TP +.B \-z +Treats (0,0,0) in the pfm file as a special don't-touch value. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting bba file will be written. +.TP +.B \-h +Display this help page. diff --git a/doc/man/pfm-trans.1 b/doc/man/pfm-trans.1 new file mode 100644 index 0000000000..f2ae7ddf33 --- /dev/null +++ b/doc/man/pfm-trans.1 @@ -0,0 +1,70 @@ +.\" Automatically generated by pfm-trans -write-bam +.TH PFM-TRANS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +pfm-trans \- transform .pfm files +.SH SYNOPSIS +.SH DESCRIPTION +pfm\-trans reads an pfm file and transforms it, filters it, operates on it, writing the output to another pfm file. A pfm file contains a 2\-d table of floating\-point values. +.SH OPTIONS +.TP +.B \-z +Treats (0,0,0) in the pfm file as a special don't-touch value. +.TP +.BI "\-nan " "num_channels" +Treats a NaN in any of the first num_channels channels as a special don't-touch value. +.TP +.BI "\-resize " "width,height" +Resamples the pfm file to scale it to the indicated grid size. A simple box filter is applied during the scale. Don't confuse this with -TS, which scales the individual point values, but doesn't change the number of points. +.TP +.BI "\-crop " "xbegin,xend,ybegin,yend" +Crops the pfm file to the indicated subregion. +.TP +.B \-autocrop +Automatically crops to the smallest possible rectangle that includes all points. Requires -z or -nan. +.TP +.BI "\-rotate " "degrees" +Rotates the pfm file the specified number of degrees counterclockwise, which must be a multiple of 90. +.TP +.B \-mirror_x +Flips the pfm file about the x axis. +.TP +.B \-mirror_y +Flips the pfm file about the y axis. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting pfm file will be written. This is only valid when there is only one input pfm file on the command line. If you want to process multiple files simultaneously, you must use -d. +.TP +.BI "\-d " "dirname" +Specify the name of the directory in which to write the processed pfm files. If you are processing only one pfm file, this may be omitted in lieu of the -o option. +.TP +.BI "\-vis " "filename.bam" +Generates a bam file that represents a visualization of the pfm file as a 3-D geometric mesh. If -vistex is specified, the mesh is textured. +.TP +.B \-visinv +Inverts the visualization, generating a uniform 2-d mesh with the 3-d depth values encoded in the texture coordinates. +.TP +.B \-vis2d +Respect only the first two components of each depth value, ignoring z. +.TP +.BI "\-vistex " "texture.jpg" +Specifies the name of the texture to apply to the visualization. +.TP +.BI "\-ls " "filename.txt" +Lists the points in the file to the indicated text file. +.TP +.B \-h +Display this help page. diff --git a/doc/man/punzip.1 b/doc/man/punzip.1 new file mode 120000 index 0000000000..93e1901659 --- /dev/null +++ b/doc/man/punzip.1 @@ -0,0 +1 @@ +pzip.1 \ No newline at end of file diff --git a/doc/man/pview.1 b/doc/man/pview.1 new file mode 100644 index 0000000000..a45fb8110f --- /dev/null +++ b/doc/man/pview.1 @@ -0,0 +1,50 @@ +.TH PVIEW 1 "27 December 2014" "" Panda3D +.SH NAME +pview \- quickly view a Panda model and/or animation +.SH SYNOPSIS +.B pview +[ +.I opts +] +.I model +[ +.I model ... +] +.br +.B pview \-h +.SH DESCRIPTION +\fBpview\fP opens a quick Panda window for viewing one or more models +and/or animations. +.SH OPTIONS +.TP +.B \-a +Convert and play animations, if loading an external file type +(like .mb) directly and if the converter supports animations. +Also implicitly enables the animation controls. +.TP +.B \-c +Automatically center models within the viewing window on startup. +This can also be achieved with the 'c' hotkey at runtime. +.TP +.B \-l +Open the window before loading any models with the text "Loading" +displayed in the window. The default is not to open the window +until all models are loaded. +.TP +.B \-i +Ignore bundle/group names. Normally, the name must match +the name, or the animation will not be used. +.TP +.BI "\-s " filename +After displaying the models, immediately take a screenshot and +exit. +.TP +.B \-D +Delete the model files after loading them (presumably this option +will only be used when loading a temporary model file). +.TP +.B \-V +Report the current version of Panda, and exit. +.TP +.B \-h +Display this help text. diff --git a/doc/man/pzip.1 b/doc/man/pzip.1 new file mode 100644 index 0000000000..22ac0d931a --- /dev/null +++ b/doc/man/pzip.1 @@ -0,0 +1,64 @@ +.TH PZIP 1 "27 December 2014" "" Panda3D +.SH NAME +pzip, punzip \- compress or decompress files +.SH SYNOPSIS +.B pzip +.I file +[ +.I file2 file3 ... +] +.br +.B pzip -c < \fIfile\fB > \fIdest_file\fB +.br +.B pzip -o +.I dest_file file +.PP +.B punzip +.I file.pz +[ +.I file2.pz file3.pz ... +] +.br +.B punzip -c < \fIfile.pz\fB > \fIdest_file\fB +.br +.B punzip -o +.I dest_file file.pz +.SH DESCRIPTION +The \fBpzip\fP program compresses the named file(s) using the Panda +native compression algorithm (gzip in practice, but with a different +file header). The compressed versions are written to a file with the +same name as the original, but the extension .pz added to the +filename, and the original file is removed (unless the version with +\fB\-o\fP is used, in which case you can compress only one file, you +specify the destination file name, and the original file is not removed). +.PP +In many cases, Panda can read the resulting .pz file directly, +exactly as if it were still in its uncompressed original form. +In fact, unless \fBvfs\-implicit\-pz\fP is set to \fBfalse\fP in your +Config.prc file, you can also load the file by referencing it with its +original filename (without the .pz extension), even though it no longer +exists under that filename, and Panda will find the .pz file and +transparently decompress it on the fly, as if the original, uncompressed +file still existed. +.PP +Note that if you are adding files to a Panda multifile (.mf file) with the +.BR multify (1) +command, it is not necessary to encrypt them separately; \fBmultify\fP has an +inline encryption option. +.PP +\fBpunzip\fP reverses the operation of a previous \fBpzip\fP command. +It uncompresses the contents of the named source file(s) and removes +the .pz extension. +.SH OPTIONS +These options apply to \fBpzip\fP only. +.TP +.B \-1 +compress faster +.TP +.B \-6 +compress default +.TP +.B \-9 +compress better (intermediate compression levels supported also) +.SH "SEE ALSO" +.BR multify (1) diff --git a/doc/man/softcvs.1 b/doc/man/softcvs.1 new file mode 100644 index 0000000000..e0f49ab949 --- /dev/null +++ b/doc/man/softcvs.1 @@ -0,0 +1,22 @@ +.\" Automatically generated by softcvs -write-bam +.TH SOFTCVS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +softcvs \- prepare a SoftImage database directory for adding to CVS +.SH SYNOPSIS +\fBsoftcvs\fR [opts] +.SH DESCRIPTION +softcvs is designed to prepare a directory hierarchy representing a SoftImage database for adding to CVS. First, it eliminates SoftImage's silly filename\-based versioning system by renaming versioned filenames higher than 1\-0 back to version 1\-0. Then, it rolls up all the files for each scene except the texture images into a Panda multifile, which is added to CVS; the texture images are directly added to CVS where they are. +.PP +The reduction of hundreds of SoftImage files per scene down to one multifile and a handle of texture images should greatly improve the update and commit times of CVS. +.PP +You must run this from within the root of a SoftImage database directory; e.g. the directory that contains SCENES, PICTURES, MODELS, and so on. +.SH OPTIONS +.TP +.B \-nc +Do not attempt to add newly-created files to CVS. The default is to add them. +.TP +.BI "\-cvs " "cvs_binary" +Specify how to run the cvs program for adding newly-created files. The default is simply "cvs". +.TP +.B \-h +Display this help page. diff --git a/doc/man/test_interrogate.1 b/doc/man/test_interrogate.1 new file mode 100644 index 0000000000..325c544eed --- /dev/null +++ b/doc/man/test_interrogate.1 @@ -0,0 +1,40 @@ +.TH TEST_INTERROGATE 1 "27 December 2014" "" Panda3D +.SH NAME +test_interrogate \- report symbols defined in an interrogate module +.SH SYNOPSIS +.B test_interrogate +[ +.I opts +] +.I libfile.so +[ +.I libfile.so ... +] +.SH DESCRIPTION +Loads the given shared library or libraries, if possible, and reports the +symbols, types, and functions available within those libraries as reported +by interrogate. +.PP +In lieu of loading a shared library, you may also read the interrogate +database file directly by specifying a filename like \fIlibfile.in\fP. +This will report the symbols defined in that file only (without pulling +in dependent files), and will not have any function pointers available. +.SH OPTIONS +.TP +.BI "\-p " path +Specify the search path for *.in files. This option may be repeated. +.TP +.B \-f +Give a detailed report of each function in the database, including +synthesized functions like upcasts and downcasts. +.TP +.B \-t +Give a detailed report of every type in the database, including types +like pointers and const pointers. +.TP +.B \-q +Quickly load up each shared library, if possible, and then immediately +exit. Useful for quickly determining whether a library can even load. +.SH "SEE ALSO" +.BR interrogate (1), +.BR interrogate_module (1) diff --git a/doc/man/text-stats.1 b/doc/man/text-stats.1 new file mode 100644 index 0000000000..187f14a3a6 --- /dev/null +++ b/doc/man/text-stats.1 @@ -0,0 +1,20 @@ +.\" Automatically generated by text-stats -write-bam +.TH TEXT-STATS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +text-stats \- text-based PStats client +.SH SYNOPSIS +.SH DESCRIPTION +This is a simple PStats server that listens on a TCP port for a connection from a PStatClient in a Panda player. It will then report frame rate and timing information sent by the player. +.SH OPTIONS +.TP +.BI "\-p " "port" +Specify the TCP port to listen for connections on. By default, this is taken from the pstats-host Config variable. +.TP +.B \-r +Show the raw frame data, in addition to boiling it down to a total time per collector. +.TP +.BI "\-o " "filename" +Filename where to print. If not given then stderr is being used. +.TP +.B \-h +Display this help page. diff --git a/doc/man/vrml-trans.1 b/doc/man/vrml-trans.1 new file mode 100644 index 0000000000..e78342935c --- /dev/null +++ b/doc/man/vrml-trans.1 @@ -0,0 +1,19 @@ +.\" Automatically generated by vrml-trans -write-bam +.TH VRML-TRANS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +vrml-trans \- reads and writes VRML 2.0 files +.SH SYNOPSIS +\fBvrml-trans\fR [opts] input.wrl > output.wrl +.br +\fBvrml-trans\fR [opts] input.wrl output.wrl +.br +\fBvrml-trans\fR [opts] -o output.wrl input.wrl +.SH DESCRIPTION +This program reads a VRML 2.0 file (.wrl) and writes an essentially equivalent .wrl file. It is primarily useful for debugging the VRML parser that is part of the Pandatool library. +.SH OPTIONS +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting .wrl file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.B \-h +Display this help page. diff --git a/doc/man/vrml2egg.1 b/doc/man/vrml2egg.1 new file mode 100644 index 0000000000..45a5ea5f05 --- /dev/null +++ b/doc/man/vrml2egg.1 @@ -0,0 +1,72 @@ +.\" Automatically generated by vrml2egg -write-bam +.TH VRML2EGG 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +vrml2egg \- convert VRML 2.0 model files to .egg +.SH SYNOPSIS +\fBvrml2egg\fR [opts] input.wrl output.egg +.br +\fBvrml2egg\fR [opts] -o output.egg input.wrl +.br +\fBvrml2egg\fR [opts] input.wrl >output.egg +.SH DESCRIPTION +This program converts VRML 2.0 model files to egg. Animated files, and VRML 1.0 files, are not supported. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input VRML file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.B \-ignore +Ignore non-fatal errors and generate an egg file anyway. +.TP +.BI "\-ui " "units" +Specify the units of the input VRML file. Normally, this can be inferred from the file itself. +.TP +.BI "\-uo " "units" +Specify the units of the resulting egg file. If this is specified, the vertices in the egg file will be scaled as necessary to make the appropriate units conversion; otherwise, the vertices will be left as they are. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the input VRML file. Normally, this is y-up. +.TP +.B \-h +Display this help page. diff --git a/doc/man/x-trans.1 b/doc/man/x-trans.1 new file mode 100644 index 0000000000..ce80ae6632 --- /dev/null +++ b/doc/man/x-trans.1 @@ -0,0 +1,17 @@ +.\" Automatically generated by x-trans -write-bam +.TH X-TRANS 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +x-trans \- reads and writes DirectX .x files +.SH SYNOPSIS +\fBx-trans\fR [opts] input.x output.x +.br +\fBx-trans\fR [opts] -o output.x input.x +.SH DESCRIPTION +This program reads a DirectX retained\-mode file (.x) and writes an essentially equivalent .x file. It is primarily useful for debugging the X file parser that is part of the Pandatool library. +.SH OPTIONS +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting .x file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file. +.TP +.B \-h +Display this help page. diff --git a/doc/man/x2egg.1 b/doc/man/x2egg.1 new file mode 100644 index 0000000000..48e514b023 --- /dev/null +++ b/doc/man/x2egg.1 @@ -0,0 +1,103 @@ +.\" Automatically generated by x2egg -write-bam +.TH X2EGG 1 "27 December 2014" "1.9.0" Panda3D +.SH NAME +x2egg \- convert a DirectX .x file to an .egg file +.SH SYNOPSIS +\fBx2egg\fR [opts] input.x output.egg +.br +\fBx2egg\fR [opts] -o output.egg input.x +.br +\fBx2egg\fR [opts] input.x >output.egg +.SH DESCRIPTION +This program converts DirectX retained\-mode (.x) files to egg. Polygon meshes, materials, and textures, as well as skeleton animation and skinning data, are supported. All animations found in the source .x file are written together into the same egg file. +.SH OPTIONS +.TP +.B \-noabs +Don't allow the input DirectX file to have absolute pathnames. If it does, abort with an error. This option is designed to help detect errors when populating or building a standalone model tree, which should be self-contained and include only relative pathnames. +.TP +.B \-noexist +Don't treat it as an error if the input file references pathnames (e.g. textures) that don't exist. Normally, this will be flagged as an error and the command aborted; with this option, an egg file will be generated anyway, referencing pathnames that do not exist. +.TP +.B \-ignore +Ignore non-fatal errors and generate an egg file anyway. +.TP +.BI "\-a " "name" +Specify the name of the animated character to generate. This option forces the model to be converted as an animatable character, even if animation channels are not found in the file. Without this option, the model is converted as a static model (which is usually more efficient to load within Panda), unless animation channels are present in the .x file. +.TP +.BI "\-fr " "fps" +Specify the frame rate of the resulting animation. If this is omitted or 0, the frame rate is inferred from the file itself; but note that the file must contain evenly-spaced keyframes. +.TP +.B \-anim +Generate animation data only (all geometry will be discarded). +.TP +.B \-model +Generate model data only (all animation data will be discarded). +.TP +.BI "\-pr " "path_replace" +Sometimes references to other files (textures, external references) are stored with a full path that is appropriate for some other system, but does not exist here. This option may be used to specify how those invalid paths map to correct paths. Generally, this is of the form 'orig_prefix=replacement_prefix', which indicates a particular initial sequence of characters that should be replaced with a new sequence; e.g. '/c/home/models=/beta/fish'. If the replacement prefix does not begin with a slash, the file will then be searched for along the search path specified by -pp. You may use standard filename matching characters ('*', '?', etc.) in the original prefix, and '**' as a component by itself stands for any number of components. + +This option may be repeated as necessary; each file will be tried against each specified method, in the order in which they appear in the command line, until the file is found. If the file is not found, the last matching prefix is used anyway. +.TP +.BI "\-pp " "dirname" +Adds the indicated directory name to the list of directories to search for filenames referenced by the source file. This is used only for relative paths, or for paths that are made relative by a -pr replacement string that doesn't begin with a leading slash. The model-path is always implicitly searched anyway. +.TP +.BI "\-ps " "path_store" +Specifies the way an externally referenced file is to be represented in the resulting output file. This assumes the named filename actually exists; see -pr to indicate how to deal with external references that have bad pathnames. This option will not help you to find a missing file, but simply controls how filenames are represented in the output. + +The option may be one of: rel, abs, rel_abs, strip, or keep. If either rel or rel_abs is specified, the files are made relative to the directory specified by -pd. The default is rel. +.TP +.BI "\-pd " "path_directory" +Specifies the name of a directory to make paths relative to, if '-ps rel' or '-ps rel_abs' is specified. If this is omitted, the directory name is taken from the name of the output file. +.TP +.BI "\-pc " "target_directory" +Copies textures and other dependent files into the indicated directory. If a relative pathname is specified, it is relative to the directory specified with -pd, above. +.TP +.BI "\-ui " "units" +Specify the units of the input DirectX file. +.TP +.BI "\-uo " "units" +Specify the units of the resulting egg file. If both this and -ui are specified, the vertices in the egg file will be scaled as necessary to make the appropriate units conversion; otherwise, the vertices will be left as they are. +.TP +.B \-no +Strip all normals. +.TP +.B \-np +Strip existing normals and redefine polygon normals. +.TP +.BI "\-nv " "threshold" +Strip existing normals and redefine vertex normals. Consider an edge between adjacent polygons to be smooth if the angle between them is less than threshold degrees. +.TP +.B \-nn +Preserve normals exactly as they are. This is the default. +.TP +.BI "\-tbn " "name" +Compute tangent and binormal for the named texture coordinate set(s). The name may include wildcard characters such as * and ?. The normal must already exist or have been computed via one of the above options. The tangent and binormal are used to implement bump mapping and related texture-based lighting effects. This option may be repeated as necessary to name multiple texture coordinate sets. +.TP +.B \-tbnall +Compute tangent and binormal for all texture coordinate sets. This is equivalent to -tbn "*". +.TP +.B \-tbnauto +Compute tangent and binormal for all normal maps. +.TP +.BI "\-TS " "sx[,sy,sz]" +Scale the model uniformly by the given factor (if only one number is given) or in each axis by sx, sy, sz (if three numbers are given). +.TP +.BI "\-TR " "x,y,z" +Rotate the model x degrees about the x axis, then y degrees about the y axis, and then z degrees about the z axis. +.TP +.BI "\-TA " "angle,x,y,z" +Rotate the model angle degrees counterclockwise about the given axis. +.TP +.BI "\-TT " "x,y,z" +Translate the model by the indicated amount. + +All transformation options (-TS, -TR, -TA, -TT) are cumulative and are applied in the order they are encountered on the command line. +.TP +.BI "\-o " "filename" +Specify the filename to which the resulting egg file will be written. If this option is omitted, the last parameter name is taken to be the name of the output file, or standard output is used if there are no other parameters. +.TP +.BI "\-cs " "coordinate-system" +Specify the coordinate system of the input DirectX file. Normally, this is y-up-left. +.TP +.B \-h +Display this help page. diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index d58e235a6d..e0ad2a8150 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -6290,6 +6290,8 @@ def MakeInstallerLinux(): else: InstallPanda(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=GetDebLibDir()) oscmd("chmod -R 755 targetroot/usr/share/panda3d") + oscmd("mkdir -p targetroot/usr/share/man/man1") + oscmd("cp doc/man/*.1 targetroot/usr/share/man/man1/") oscmd("dpkg --print-architecture > "+GetOutputDir()+"/tmp/architecture.txt") pkg_arch = ReadFile(GetOutputDir()+"/tmp/architecture.txt").strip() @@ -6463,6 +6465,9 @@ def MakeInstallerOSX(): # Trailing newline is important, works around a bug in OSX WriteFile("dstroot/tools/etc/paths.d/Panda3D", "/Developer/Tools/Panda3D\n") + oscmd("mkdir -p dstroot/tools/usr/share/man/man1") + oscmd("cp doc/man/*.1 dstroot/tools/usr/share/man/man1/") + for base in os.listdir(GetOutputDir()+"/bin"): binname = "dstroot/tools/Developer/Tools/Panda3D/" + base # OSX needs the -R argument to copy symbolic links correctly, it doesn't have -d. How weird. diff --git a/pandatool/src/bam/bamInfo.cxx b/pandatool/src/bam/bamInfo.cxx index b220025e3b..1839c09347 100644 --- a/pandatool/src/bam/bamInfo.cxx +++ b/pandatool/src/bam/bamInfo.cxx @@ -34,6 +34,7 @@ //////////////////////////////////////////////////////////////////// BamInfo:: BamInfo() { + set_program_brief("describe the contents of .bam files"); set_program_description ("This program scans one or more Bam files--Panda's Binary Animation " "and Models native binary format--and describes their contents."); diff --git a/pandatool/src/bam/bamToEgg.cxx b/pandatool/src/bam/bamToEgg.cxx index 4239a05f42..eb2f652a3b 100644 --- a/pandatool/src/bam/bamToEgg.cxx +++ b/pandatool/src/bam/bamToEgg.cxx @@ -28,6 +28,7 @@ BamToEgg:: BamToEgg() : SomethingToEgg("bam", ".bam") { + set_program_brief("convert a native Panda .bam file to an .egg file"); set_program_description ("This program converts native Panda bam files to egg. The conversion " "is somewhat incomplete; running egg2bam followed by bam2egg should not " diff --git a/pandatool/src/bam/eggToBam.cxx b/pandatool/src/bam/eggToBam.cxx index d10257c6ed..4c1587fc99 100644 --- a/pandatool/src/bam/eggToBam.cxx +++ b/pandatool/src/bam/eggToBam.cxx @@ -43,6 +43,7 @@ EggToBam:: EggToBam() : EggToSomething("Bam", ".bam", true, false) { + set_program_brief("convert .egg files to .bam files"); set_program_description ("This program reads Egg files and outputs Bam files, the binary format " "suitable for direct loading of animation and models into Panda. Bam " diff --git a/pandatool/src/bam/ptsToBam.cxx b/pandatool/src/bam/ptsToBam.cxx index e914faa178..c45dd6e1a3 100755 --- a/pandatool/src/bam/ptsToBam.cxx +++ b/pandatool/src/bam/ptsToBam.cxx @@ -32,6 +32,7 @@ PtsToBam:: PtsToBam() : WithOutputFile(true, false, true) { + set_program_brief("convert point cloud data into a .bam file"); set_program_description ("This program reads a point clound in a pts file and outputs a bam files, " "suitable for viewing in Panda."); diff --git a/pandatool/src/cvscopy/testCopy.cxx b/pandatool/src/cvscopy/testCopy.cxx index ec0e5844be..23b0ba4cfa 100644 --- a/pandatool/src/cvscopy/testCopy.cxx +++ b/pandatool/src/cvscopy/testCopy.cxx @@ -23,6 +23,7 @@ //////////////////////////////////////////////////////////////////// TestCopy:: TestCopy() { + set_program_brief("copy files into a CVS source hierarchy"); set_program_description ("This program copies one or more files into a CVS source hierarchy. " "Rather than copying the named files immediately into the current " diff --git a/pandatool/src/daeprogs/daeToEgg.cxx b/pandatool/src/daeprogs/daeToEgg.cxx index 49606788d5..503d1af33a 100755 --- a/pandatool/src/daeprogs/daeToEgg.cxx +++ b/pandatool/src/daeprogs/daeToEgg.cxx @@ -37,6 +37,7 @@ DAEToEgg(): "that export models with inverted transparency, such as Google SketchUp.", &SomethingToEgg::dispatch_none, &_invert_transparency); + set_program_brief("convert COLLADA assets into .egg files"); set_program_description ("This program converts .dae files (COLLADA Digital Asset Exchange) to .egg."); diff --git a/pandatool/src/daeprogs/eggToDAE.cxx b/pandatool/src/daeprogs/eggToDAE.cxx index cb119a5d28..d5f042ec9e 100755 --- a/pandatool/src/daeprogs/eggToDAE.cxx +++ b/pandatool/src/daeprogs/eggToDAE.cxx @@ -40,6 +40,7 @@ EggToDAE() : EggToSomething("COLLADA", ".dae", true, false) { set_binary_output(false); + set_program_brief("convert .egg files into COLLADA asset files"); set_program_description ("This program converts files from the egg format to the COLLADA " ".dae (Digital Asset Exchange) format."); diff --git a/pandatool/src/dxfprogs/dxfPoints.cxx b/pandatool/src/dxfprogs/dxfPoints.cxx index ceef87f9d9..14f50bb696 100644 --- a/pandatool/src/dxfprogs/dxfPoints.cxx +++ b/pandatool/src/dxfprogs/dxfPoints.cxx @@ -28,6 +28,7 @@ DXFPoints() : // output files. _preferred_extension = ".txt"; + set_program_brief("extract points from AutoCAD .dxf files"); set_program_description ("This program reads an AutoCAD .dxf file and generates a simple " "list of all the points contained within it, one per line, to a " diff --git a/pandatool/src/dxfprogs/dxfToEgg.cxx b/pandatool/src/dxfprogs/dxfToEgg.cxx index 7ce2b5e167..9f2cc149f2 100644 --- a/pandatool/src/dxfprogs/dxfToEgg.cxx +++ b/pandatool/src/dxfprogs/dxfToEgg.cxx @@ -30,6 +30,7 @@ DXFToEgg() : add_normals_options(); add_transform_options(); + set_program_brief("convert AutoCAD .dxf files to .egg files"); set_program_description ("This program converts DXF (AutoCAD interchange format) to egg. It " "only converts polygon data, with no fancy tricks. DXF does not support " diff --git a/pandatool/src/dxfprogs/eggToDXF.cxx b/pandatool/src/dxfprogs/eggToDXF.cxx index 13e9f4d64b..e2404b2007 100644 --- a/pandatool/src/dxfprogs/eggToDXF.cxx +++ b/pandatool/src/dxfprogs/eggToDXF.cxx @@ -27,6 +27,7 @@ EggToDXF() : EggToSomething("DXF", ".dxf", true, false) { set_binary_output(true); + set_program_brief("convert .egg files to AutoCAD .dxf files"); set_program_description ("This program converts files from egg format to AutoCAD DXF format. " "Since DXF does not support nested hierarchies, vertex normals, or any " diff --git a/pandatool/src/egg-mkfont/eggMakeFont.cxx b/pandatool/src/egg-mkfont/eggMakeFont.cxx index 36a5e04acc..68403c5e62 100644 --- a/pandatool/src/egg-mkfont/eggMakeFont.cxx +++ b/pandatool/src/egg-mkfont/eggMakeFont.cxx @@ -41,6 +41,7 @@ //////////////////////////////////////////////////////////////////// EggMakeFont:: EggMakeFont() : EggWriter(true, false) { + set_program_brief("generates .egg files with rasterized font glyphs"); set_program_description ("egg-mkfont uses the FreeType library to generate an egg file " "and a series of texture images from a font file " diff --git a/pandatool/src/egg-optchar/eggOptchar.cxx b/pandatool/src/egg-optchar/eggOptchar.cxx index 840d8bcdf2..cf22dbe394 100644 --- a/pandatool/src/egg-optchar/eggOptchar.cxx +++ b/pandatool/src/egg-optchar/eggOptchar.cxx @@ -49,6 +49,7 @@ EggOptchar() { add_transform_options(); add_fixrest_option(); + set_program_brief("optimizes character models and animations in .egg files"); set_program_description ("egg-optchar performs basic optimizations of a character model " "and its associated animations, primarily by analyzing the " diff --git a/pandatool/src/egg-palettize/eggPalettize.cxx b/pandatool/src/egg-palettize/eggPalettize.cxx index d34179c676..07f0ab49ed 100644 --- a/pandatool/src/egg-palettize/eggPalettize.cxx +++ b/pandatool/src/egg-palettize/eggPalettize.cxx @@ -35,6 +35,7 @@ //////////////////////////////////////////////////////////////////// EggPalettize:: EggPalettize() : EggMultiFilter(true) { + set_program_brief("pack textures from various .egg models into palette images"); set_program_description ("egg-palettize attempts to pack several texture maps from various models " "together into one or more palette images, for improved rendering performance " diff --git a/pandatool/src/egg-qtess/eggQtess.cxx b/pandatool/src/egg-qtess/eggQtess.cxx index 5cb300c6b0..50ae8544dd 100644 --- a/pandatool/src/egg-qtess/eggQtess.cxx +++ b/pandatool/src/egg-qtess/eggQtess.cxx @@ -26,9 +26,10 @@ EggQtess:: EggQtess() { add_normals_options(); + set_program_brief("tesselate NURBS surfaces in .egg files"); set_program_description - ("egg-qtess reads an egg file, tesselates all of its NURBS surfaces " - "using a simple uniform tesselation, and outputs a polygonal " + ("egg-qtess reads an egg file, tessellates all of its NURBS surfaces " + "using a simple uniform tessellation, and outputs a polygonal " "egg file.\n\n" "Characters are supported, soft-skinned and otherwise; joint " @@ -62,12 +63,12 @@ EggQtess() { "Specify an approximate number of triangles to produce. This " "is the total number of triangles for the entire egg file, " "including those surfaces that have already been given an " - "explicit tesselation by a parameter file.", + "explicit tessellation by a parameter file.", &EggQtess::dispatch_int, NULL, &_total_tris); add_option ("ap", "", 0, - "Attempt to automatically place tesselation lines where they'll " + "Attempt to automatically place tessellation lines where they'll " "do the most good on each surface (once the number of polygons " "for the surface has already been determined).", &EggQtess::dispatch_none, &QtessGlobals::_auto_place); @@ -93,7 +94,7 @@ EggQtess() { "Respect subdivision parameters given in the egg file. If this " "is specified, the egg file may define the effective number of " "patches of each NURBS entry. This can be used alone or in " - "conjunction with -u or -t to fine-tune the uniform tesselation " + "conjunction with -u or -t to fine-tune the uniform tessellation " "on a per-surface basis. (This is ignored if -ad is in effect.)", &EggQtess::dispatch_none, &QtessGlobals::_respect_egg); diff --git a/pandatool/src/eggprogs/eggCrop.cxx b/pandatool/src/eggprogs/eggCrop.cxx index 83786130c1..73a623298c 100644 --- a/pandatool/src/eggprogs/eggCrop.cxx +++ b/pandatool/src/eggprogs/eggCrop.cxx @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////////////// EggCrop:: EggCrop() { + set_program_brief("crop geometry in an .egg file"); set_program_description ("egg-crop strips out all parts of an egg file that fall outside of an " "arbitrary bounding volume, specified with a minimum and maximum point " diff --git a/pandatool/src/eggprogs/eggListTextures.cxx b/pandatool/src/eggprogs/eggListTextures.cxx index b26758678c..bc1af8161f 100644 --- a/pandatool/src/eggprogs/eggListTextures.cxx +++ b/pandatool/src/eggprogs/eggListTextures.cxx @@ -24,6 +24,7 @@ //////////////////////////////////////////////////////////////////// EggListTextures:: EggListTextures() { + set_program_brief("list textures referenced by an .egg file"); set_program_description ("egg-list-textures reads an egg file and writes a list of the " "textures it references. It is particularly useful for building " diff --git a/pandatool/src/eggprogs/eggMakeTube.cxx b/pandatool/src/eggprogs/eggMakeTube.cxx index 20a0b770b8..3b8eddb5c8 100644 --- a/pandatool/src/eggprogs/eggMakeTube.cxx +++ b/pandatool/src/eggprogs/eggMakeTube.cxx @@ -29,6 +29,7 @@ EggMakeTube:: EggMakeTube() { + set_program_brief("generate a tube or sphere from geometry in an .egg file"); set_program_description ("egg-make-tube generates an egg file representing a \"tube\" model, " "a cylinder capped on both ends by hemispheres. This is similar " diff --git a/pandatool/src/eggprogs/eggRename.cxx b/pandatool/src/eggprogs/eggRename.cxx index 4dec65368f..a497671c79 100755 --- a/pandatool/src/eggprogs/eggRename.cxx +++ b/pandatool/src/eggprogs/eggRename.cxx @@ -22,6 +22,7 @@ //////////////////////////////////////////////////////////////////// EggRename:: EggRename() { + set_program_brief("rename nodes in .egg files"); set_program_description ("egg-rename reads one or more egg files and writes back with modified" "node names. ie. suppressing prefix from all the nodes' names. "); diff --git a/pandatool/src/eggprogs/eggRetargetAnim.cxx b/pandatool/src/eggprogs/eggRetargetAnim.cxx index bc189d48fd..ff26b8f686 100644 --- a/pandatool/src/eggprogs/eggRetargetAnim.cxx +++ b/pandatool/src/eggprogs/eggRetargetAnim.cxx @@ -34,6 +34,7 @@ EggRetargetAnim() { add_path_replace_options(); add_path_store_options(); + set_program_brief("remove transformations from animation data in .egg files"); set_program_description ("egg-retarget-anim reads a character model and its associated animation " "files, and removes the translations and scales from the animation " diff --git a/pandatool/src/eggprogs/eggTextureCards.cxx b/pandatool/src/eggprogs/eggTextureCards.cxx index 90fe0adb3a..b30c480059 100644 --- a/pandatool/src/eggprogs/eggTextureCards.cxx +++ b/pandatool/src/eggprogs/eggTextureCards.cxx @@ -31,6 +31,7 @@ //////////////////////////////////////////////////////////////////// EggTextureCards:: EggTextureCards() : EggWriter(true, true) { + set_program_brief("generate an .egg file containing texture cards"); set_program_description ("egg-texture-cards generates an egg file consisting of several " "square polygons, one for each texture name that appears on the " diff --git a/pandatool/src/eggprogs/eggToC.cxx b/pandatool/src/eggprogs/eggToC.cxx index 66131adee8..4b7fc2bae1 100644 --- a/pandatool/src/eggprogs/eggToC.cxx +++ b/pandatool/src/eggprogs/eggToC.cxx @@ -33,6 +33,7 @@ EggToC:: EggToC() : EggToSomething("C", ".c", true, true) { + set_program_brief("convert .egg geometry into compilable C tables"); set_program_description ("This program reads Egg files and outputs code that will almost " "compile as a C or C++ program. You get to define the data structures " diff --git a/pandatool/src/eggprogs/eggTopstrip.cxx b/pandatool/src/eggprogs/eggTopstrip.cxx index 9ddabdedba..2b833ce40d 100644 --- a/pandatool/src/eggprogs/eggTopstrip.cxx +++ b/pandatool/src/eggprogs/eggTopstrip.cxx @@ -34,6 +34,7 @@ EggTopstrip() { add_path_replace_options(); add_path_store_options(); + set_program_brief("unapplies animation from a joint in an .egg file"); set_program_description ("egg-topstrip reads a character model and its associated animation " "files, and unapplies the animation from one of the top joints. " diff --git a/pandatool/src/eggprogs/eggTrans.cxx b/pandatool/src/eggprogs/eggTrans.cxx index 7202b6b2af..99481020db 100644 --- a/pandatool/src/eggprogs/eggTrans.cxx +++ b/pandatool/src/eggprogs/eggTrans.cxx @@ -30,6 +30,7 @@ EggTrans() { add_texture_options(); add_delod_options(); + set_program_brief("apply transformations and optimizations to an .egg file"); set_program_description ("egg-trans reads an egg file and writes an essentially equivalent " "egg file to the standard output, or to the file specified with -o. " diff --git a/pandatool/src/fltprogs/eggToFlt.cxx b/pandatool/src/fltprogs/eggToFlt.cxx index f47d8b221f..d771f8d826 100644 --- a/pandatool/src/fltprogs/eggToFlt.cxx +++ b/pandatool/src/fltprogs/eggToFlt.cxx @@ -47,6 +47,7 @@ EggToFlt() : EggToSomething("MultiGen", ".flt", true, false) { set_binary_output(true); + set_program_brief("convert files from .egg format to MultiGen .flt"); set_program_description ("egg2lt converts files from egg format to MultiGen .flt " "format. It attempts to be as robust as possible, and matches " diff --git a/pandatool/src/fltprogs/fltCopy.cxx b/pandatool/src/fltprogs/fltCopy.cxx index a5457b6c75..d2c117d176 100644 --- a/pandatool/src/fltprogs/fltCopy.cxx +++ b/pandatool/src/fltprogs/fltCopy.cxx @@ -29,6 +29,7 @@ //////////////////////////////////////////////////////////////////// FltCopy:: FltCopy() { + set_program_brief("copy MultiGen .flt files into a CVS source hierarchy"); set_program_description ("fltcopy copies one or more MultiGen .flt files into a " "CVS source hierarchy. " diff --git a/pandatool/src/fltprogs/fltInfo.cxx b/pandatool/src/fltprogs/fltInfo.cxx index 730967c0ad..ab83af6705 100644 --- a/pandatool/src/fltprogs/fltInfo.cxx +++ b/pandatool/src/fltprogs/fltInfo.cxx @@ -25,6 +25,7 @@ //////////////////////////////////////////////////////////////////// FltInfo:: FltInfo() { + set_program_brief("describe the contents of a MultiGen .flt file"); set_program_description ("This program reads a MultiGen OpenFlight (.flt) file and reports " "some interesting things about its contents."); diff --git a/pandatool/src/fltprogs/fltToEgg.cxx b/pandatool/src/fltprogs/fltToEgg.cxx index e41e84fcbd..ab22aedc5c 100644 --- a/pandatool/src/fltprogs/fltToEgg.cxx +++ b/pandatool/src/fltprogs/fltToEgg.cxx @@ -34,6 +34,7 @@ FltToEgg() : add_transform_options(); add_merge_externals_options(); + set_program_brief("convert a MultiGen .flt file to .egg"); set_program_description ("This program converts MultiGen OpenFlight (.flt) files to egg. Most " "features of MultiGen that are also recognized by egg are supported."); diff --git a/pandatool/src/fltprogs/fltTrans.cxx b/pandatool/src/fltprogs/fltTrans.cxx index 8a54272d1b..8c9d095edc 100644 --- a/pandatool/src/fltprogs/fltTrans.cxx +++ b/pandatool/src/fltprogs/fltTrans.cxx @@ -30,6 +30,7 @@ FltTrans() : // output files. _preferred_extension = ".flt"; + set_program_brief("apply various operations to a MultiGen .flt file"); set_program_description ("This program reads a MultiGen OpenFlight (.flt) file and writes an " "essentially equivalent .flt file, to the file specified with -o (or " diff --git a/pandatool/src/imageprogs/imageFixHiddenColor.cxx b/pandatool/src/imageprogs/imageFixHiddenColor.cxx index f8622843ae..682cc8dd1b 100644 --- a/pandatool/src/imageprogs/imageFixHiddenColor.cxx +++ b/pandatool/src/imageprogs/imageFixHiddenColor.cxx @@ -23,6 +23,7 @@ //////////////////////////////////////////////////////////////////// ImageFixHiddenColor:: ImageFixHiddenColor() : ImageFilter(true) { + set_program_brief("change the color of transparent pixels in an image"); set_program_description ("This program is designed to fix the color channels of an " "alpha-cutout image, making the \"color\" of the invisible part of the " diff --git a/pandatool/src/imageprogs/imageInfo.cxx b/pandatool/src/imageprogs/imageInfo.cxx index 4d9d2a348b..ea2954315b 100755 --- a/pandatool/src/imageprogs/imageInfo.cxx +++ b/pandatool/src/imageprogs/imageInfo.cxx @@ -23,6 +23,7 @@ //////////////////////////////////////////////////////////////////// ImageInfo:: ImageInfo() { + set_program_brief("report the size of image files"); set_program_description ("This program reads the headers of a series of one or more " "image files and reports the image sizes to standard output."); diff --git a/pandatool/src/imageprogs/imageResize.cxx b/pandatool/src/imageprogs/imageResize.cxx index f37edeba40..d10356f0fc 100755 --- a/pandatool/src/imageprogs/imageResize.cxx +++ b/pandatool/src/imageprogs/imageResize.cxx @@ -23,6 +23,7 @@ //////////////////////////////////////////////////////////////////// ImageResize:: ImageResize() : ImageFilter(true) { + set_program_brief("resize an image file"); set_program_description ("This program reads an image file and resizes it to a larger or smaller " "image file."); diff --git a/pandatool/src/imageprogs/imageTrans.cxx b/pandatool/src/imageprogs/imageTrans.cxx index 58e1329d1c..94b8bcf4d3 100644 --- a/pandatool/src/imageprogs/imageTrans.cxx +++ b/pandatool/src/imageprogs/imageTrans.cxx @@ -23,6 +23,7 @@ //////////////////////////////////////////////////////////////////// ImageTrans:: ImageTrans() : ImageFilter(true) { + set_program_brief("apply transformations to an image file"); set_program_description ("This program reads an image file and writes a similar " "image file to the output. It can implicitly convert from one image " diff --git a/pandatool/src/imageprogs/imageTransformColors.cxx b/pandatool/src/imageprogs/imageTransformColors.cxx index 5e1b73b060..118ef0f5c1 100644 --- a/pandatool/src/imageprogs/imageTransformColors.cxx +++ b/pandatool/src/imageprogs/imageTransformColors.cxx @@ -25,6 +25,7 @@ //////////////////////////////////////////////////////////////////// ImageTransformColors:: ImageTransformColors() { + set_program_brief("transform colors in an image file"); set_program_description ("This program can apply a global color transform to all of the " "pixels in an image, or in a series of images. This can be used, " diff --git a/pandatool/src/lwoprogs/lwoScan.cxx b/pandatool/src/lwoprogs/lwoScan.cxx index 13bcf141db..f8866ee75c 100644 --- a/pandatool/src/lwoprogs/lwoScan.cxx +++ b/pandatool/src/lwoprogs/lwoScan.cxx @@ -29,6 +29,7 @@ LwoScan() { clear_runlines(); add_runline("[opts] input.lwo"); + set_program_brief("describe the contents of a Lightwave object file"); set_program_description ("This program simply reads a Lightwave object file and dumps its " "contents to standard output. It's mainly useful for debugging " diff --git a/pandatool/src/lwoprogs/lwoToEgg.cxx b/pandatool/src/lwoprogs/lwoToEgg.cxx index de16c822de..dfaf1cb7fd 100644 --- a/pandatool/src/lwoprogs/lwoToEgg.cxx +++ b/pandatool/src/lwoprogs/lwoToEgg.cxx @@ -35,6 +35,7 @@ LwoToEgg() : add_normals_options(); add_transform_options(); + set_program_brief("convert a Lightwave Object file to .egg"); set_program_description ("This program converts Lightwave Object (.lwo) files to egg. Many " "rendering characteristics of Lightwave (like layered shaders, etc.) " diff --git a/pandatool/src/mayaprogs/eggToMaya.cxx b/pandatool/src/mayaprogs/eggToMaya.cxx index a91be286e3..4410145745 100755 --- a/pandatool/src/mayaprogs/eggToMaya.cxx +++ b/pandatool/src/mayaprogs/eggToMaya.cxx @@ -40,6 +40,7 @@ EggToMaya() : add_units_options(); set_binary_output(true); + set_program_brief("convert .egg files to Maya .mb or .ma files"); set_program_description ("egg2maya converts files from egg format to Maya .mb or .ma " "format. It contains support for basic geometry (polygons with textures)." diff --git a/pandatool/src/mayaprogs/mayaCopy.cxx b/pandatool/src/mayaprogs/mayaCopy.cxx index 5421cac22a..5d6520da63 100644 --- a/pandatool/src/mayaprogs/mayaCopy.cxx +++ b/pandatool/src/mayaprogs/mayaCopy.cxx @@ -43,6 +43,7 @@ //////////////////////////////////////////////////////////////////// MayaCopy:: MayaCopy() { + set_program_brief("copy Maya .mb files into a CVS source hierarchy"); set_program_description ("mayacopy copies one or more Maya .mb files into a " "CVS source hierarchy. " diff --git a/pandatool/src/mayaprogs/mayaToEgg.cxx b/pandatool/src/mayaprogs/mayaToEgg.cxx index 35a1b201b7..a6497c46cd 100644 --- a/pandatool/src/mayaprogs/mayaToEgg.cxx +++ b/pandatool/src/mayaprogs/mayaToEgg.cxx @@ -64,6 +64,7 @@ MayaToEgg() : add_normals_options(); add_transform_options(); + set_program_brief("convert Maya model files to .egg"); set_program_description ("This program converts Maya model files to egg. Static and animatable " "models can be converted, with polygon or NURBS output. Animation tables " diff --git a/pandatool/src/mayaprogs/mayaToEgg_server.cxx b/pandatool/src/mayaprogs/mayaToEgg_server.cxx index ac4aad600c..15a063fa6e 100755 --- a/pandatool/src/mayaprogs/mayaToEgg_server.cxx +++ b/pandatool/src/mayaprogs/mayaToEgg_server.cxx @@ -40,6 +40,7 @@ MayaToEggServer() : add_normals_options(); add_transform_options(); + set_program_brief("convert Maya model files to .egg"); set_program_description ("This program converts Maya model files to egg. Static and animatable " "models can be converted, with polygon or NURBS output. Animation tables " diff --git a/pandatool/src/miscprogs/binToC.cxx b/pandatool/src/miscprogs/binToC.cxx index 40eb02145e..947c6e3022 100644 --- a/pandatool/src/miscprogs/binToC.cxx +++ b/pandatool/src/miscprogs/binToC.cxx @@ -33,6 +33,7 @@ BinToC() : add_runline("input -o output.c"); add_runline("input >output.c"); + set_program_brief("convert binary data to a compilable C table"); set_program_description ("bin2c is a simple utility program to read a disk file, presumably " "one with binary contents, and output a table that can be " diff --git a/pandatool/src/objprogs/eggToObj.cxx b/pandatool/src/objprogs/eggToObj.cxx index fd18a1c375..8bfbe67790 100644 --- a/pandatool/src/objprogs/eggToObj.cxx +++ b/pandatool/src/objprogs/eggToObj.cxx @@ -28,6 +28,7 @@ EggToObj:: EggToObj() : EggToSomething("Obj", ".obj", true, false) { + set_program_brief("convert .egg files to .obj"); set_program_description ("This program converts egg files to obj. It " "only converts polygon data, with no fancy tricks. " diff --git a/pandatool/src/objprogs/objToEgg.cxx b/pandatool/src/objprogs/objToEgg.cxx index cc1261afbb..e670bf7ea5 100755 --- a/pandatool/src/objprogs/objToEgg.cxx +++ b/pandatool/src/objprogs/objToEgg.cxx @@ -31,6 +31,7 @@ ObjToEgg() : add_normals_options(); add_transform_options(); + set_program_brief("convert .obj files to .egg"); set_program_description ("This program converts obj files to egg. It " "only converts polygon data, with no fancy tricks. " diff --git a/pandatool/src/pfmprogs/pfmBba.cxx b/pandatool/src/pfmprogs/pfmBba.cxx index 3f15b08b96..382768c964 100755 --- a/pandatool/src/pfmprogs/pfmBba.cxx +++ b/pandatool/src/pfmprogs/pfmBba.cxx @@ -24,6 +24,7 @@ //////////////////////////////////////////////////////////////////// PfmBba:: PfmBba() { + set_program_brief("generate .bba files from .pfm files"); set_program_description ("pfm-bba generates a .bba file from a .pfm file that lists the " "planar bounding volume of the pfm's internal data."); diff --git a/pandatool/src/pfmprogs/pfmTrans.cxx b/pandatool/src/pfmprogs/pfmTrans.cxx index 5e7e3cf8e7..db5ea973b3 100755 --- a/pandatool/src/pfmprogs/pfmTrans.cxx +++ b/pandatool/src/pfmprogs/pfmTrans.cxx @@ -37,6 +37,7 @@ PfmTrans() { add_transform_options(); + set_program_brief("transform .pfm files"); set_program_description ("pfm-trans reads an pfm file and transforms it, filters it, " "operates on it, writing the output to another pfm file. A pfm " diff --git a/pandatool/src/progbase/programBase.cxx b/pandatool/src/progbase/programBase.cxx index 46736055ba..e1417b023e 100644 --- a/pandatool/src/progbase/programBase.cxx +++ b/pandatool/src/progbase/programBase.cxx @@ -27,6 +27,7 @@ #include "configVariableBool.h" #include "panda_getopt_long.h" #include "preprocess_argv.h" +#include "pandaVersion.h" #include #include @@ -80,7 +81,7 @@ static ConfigVariableBool use_terminal_width // Description: //////////////////////////////////////////////////////////////////// ProgramBase:: -ProgramBase() { +ProgramBase(const string &name) : _name(name) { // Set up Notify to write output to our own formatted stream. Notify::ptr()->set_ostream_ptr(new WordWrapStream(this), true); @@ -141,7 +142,7 @@ void ProgramBase:: show_usage() { nout << "\rUsage:\n"; Runlines::const_iterator ri; - string prog = " " +_program_name.get_basename_wo_extension(); + string prog = " " + _program_name.get_basename_wo_extension(); for (ri = _runlines.begin(); ri != _runlines.end(); ++ri) { show_text(prog, prog.length() + 1, *ri); @@ -189,6 +190,92 @@ show_text(const string &prefix, int indent_width, string text) { prefix, indent_width, text, _terminal_width); } +//////////////////////////////////////////////////////////////////// +// Function: ProgramBase::write_man_page +// Access: Public +// Description: Generates a man page in nroff syntax based on the +// description and options. This is useful when +// creating a man page for this utility. +//////////////////////////////////////////////////////////////////// +void ProgramBase:: +write_man_page(ostream &out) { + string prog = _program_name.get_basename_wo_extension(); + out << ".\\\" Automatically generated by " << prog << " -write-bam\n"; + + // Format the man page title as the uppercase version of the program name, + // as per the UNIX manual conventions. + out << ".TH "; + string::const_iterator si; + for (si = _name.begin(); si != _name.end(); ++si) { + out << (char)toupper(*si); + } + + // Generate a date string for inclusion into the footer. + char date_str[256]; + date_str[0] = 0; + time_t current_time = time(NULL); + + if (current_time != (time_t) -1) { + tm *today = localtime(¤t_time); + if (today == NULL || 0 == strftime(date_str, 256, "%d %B %Y", today)) { + date_str[0] = 0; + } + } + + out << " 1 \"" << date_str << "\" \"" PANDA_VERSION_STR "\" Panda3D\n"; + + out << ".SH NAME\n"; + if (_brief.empty()) { + out << _name << "\n"; + } else { + out << _name << " \\- " << _brief << "\n"; + } + + out << ".SH SYNOPSIS\n"; + Runlines::const_iterator ri = _runlines.begin(); + if (ri != _runlines.end()) { + out << "\\fB" << prog << "\\fR " << *ri << "\n"; + ++ri; + } + + for (; ri != _runlines.end(); ++ri) { + out << ".br\n"; + out << "\\fB" << prog << "\\fR " << *ri << "\n"; + } + + out << ".SH DESCRIPTION\n"; + string::const_iterator di; + char prev = 0; + for (di = _description.begin(); di != _description.end(); ++di) { + if ((*di) == '-') { + // We have to escape hyphens. + out << "\\-"; + } else if (prev == '\n' && (*di) == '\n') { + // Indicate the start of a new paragraph. + out << ".PP\n"; + } else { + out << (char)(*di); + } + prev = (*di); + } + out << "\n"; + + out << ".SH OPTIONS\n"; + sort_options(); + OptionsByIndex::const_iterator oi; + for (oi = _options_by_index.begin(); oi != _options_by_index.end(); ++oi) { + const Option &opt = *(*oi); + out << ".TP\n"; + + if (opt._parm_name.empty()) { + out << ".B \\-" << opt._option << "\n"; + } else { + out << ".BI \"\\-" << opt._option << " \" \"" << opt._parm_name << "\"\n"; + } + out << opt._description << "\n"; + } +} + //////////////////////////////////////////////////////////////////// // Function: ProgramBase::parse_command_line // Access: Public, Virtual @@ -208,13 +295,41 @@ parse_command_line(int argc, char **argv) { extern int optind; optind = 0; - _program_name = Filename::from_os_specific(argv[0]); int i; for (i = 1; i < argc; i++) { _program_args.push_back(argv[i]); } + if (_name.empty()) { + _name = _program_name.get_basename_wo_extension(); + } + + // Catch a special hidden option: -write-man, which causes the tool + // to generate a manual page. + if (argc > 1 && strcmp(argv[1], "-write-man") == 0) { + if (argc == 2) { + write_man_page(cout); + + } else if (argc == 3) { + if (strlen(argv[2]) == 1 && argv[2][0] == '-') { + write_man_page(cout); + + } else { + pofstream man_out(argv[2], ios::out | ios::trunc); + if (!man_out) { + cerr << "Failed to open output file " << argv[2] << "!\n"; + } + write_man_page(man_out); + man_out.close(); + } + } else { + cerr << "Invalid number of options for -write-man!\n"; + exit(1); + } + exit(0); + } + // Build up the long options list and the short options string for // getopt_long_only(). pvector long_options; @@ -438,6 +553,21 @@ post_command_line() { return true; } +//////////////////////////////////////////////////////////////////// +// Function: ProgramBase::set_program_brief +// Access: Protected +// Description: Sets a brief synopsis of the program's function. +// This is currently only used for generating the +// synopsis of the program's man page. +// +// This should be of the format: +// "perform operation foo on bar files" +//////////////////////////////////////////////////////////////////// +void ProgramBase:: +set_program_brief(const string &brief) { + _brief = brief; +} + //////////////////////////////////////////////////////////////////// // Function: ProgramBase::set_program_description // Access: Protected diff --git a/pandatool/src/progbase/programBase.h b/pandatool/src/progbase/programBase.h index 1f2ddcb664..dc58d98e01 100644 --- a/pandatool/src/progbase/programBase.h +++ b/pandatool/src/progbase/programBase.h @@ -36,7 +36,7 @@ //////////////////////////////////////////////////////////////////// class ProgramBase { public: - ProgramBase(); + ProgramBase(const string &name = string()); virtual ~ProgramBase(); void show_description(); @@ -46,6 +46,8 @@ public: INLINE void show_text(const string &text); void show_text(const string &prefix, int indent_width, string text); + void write_man_page(ostream &out); + virtual void parse_command_line(int argc, char **argv); string get_exec_command() const; @@ -61,6 +63,7 @@ protected: virtual bool handle_args(Args &args); virtual bool post_command_line(); + void set_program_brief(const string &brief); void set_program_description(const string &description); void clear_runlines(); void add_runline(const string &runline); @@ -137,6 +140,8 @@ private: bool operator () (const Option *a, const Option *b) const; }; + string _name; + string _brief; string _description; typedef vector_string Runlines; Runlines _runlines; diff --git a/pandatool/src/progbase/test_prog.cxx b/pandatool/src/progbase/test_prog.cxx index a2841141e0..b64c4ffac7 100644 --- a/pandatool/src/progbase/test_prog.cxx +++ b/pandatool/src/progbase/test_prog.cxx @@ -28,6 +28,7 @@ public: TestProgram:: TestProgram() { + set_program_brief("test program for ProgramBase class"); set_program_description ("This is a simple test program to verify the effectiveness of the " "ProgramBase base class as a base class for simple programs. It " diff --git a/pandatool/src/softprogs/softCVS.cxx b/pandatool/src/softprogs/softCVS.cxx index d25d061af1..cff45eac57 100644 --- a/pandatool/src/softprogs/softCVS.cxx +++ b/pandatool/src/softprogs/softCVS.cxx @@ -29,6 +29,7 @@ SoftCVS:: SoftCVS() { _cvs_binary = "cvs"; + set_program_brief("prepare a SoftImage database directory for adding to CVS"); set_program_description ("softcvs is designed to prepare a directory hierarchy " "representing a SoftImage database for adding to CVS. " diff --git a/pandatool/src/text-stats/textStats.cxx b/pandatool/src/text-stats/textStats.cxx index 0a34978552..0e53212246 100644 --- a/pandatool/src/text-stats/textStats.cxx +++ b/pandatool/src/text-stats/textStats.cxx @@ -36,6 +36,7 @@ static void signal_handler(int) { //////////////////////////////////////////////////////////////////// TextStats:: TextStats() { + set_program_brief("text-based PStats client"); set_program_description ("This is a simple PStats server that listens on a TCP port for a " "connection from a PStatClient in a Panda player. It will then report " diff --git a/pandatool/src/vrmlprogs/vrmlToEgg.cxx b/pandatool/src/vrmlprogs/vrmlToEgg.cxx index a52111f1cc..8ade53d2e0 100644 --- a/pandatool/src/vrmlprogs/vrmlToEgg.cxx +++ b/pandatool/src/vrmlprogs/vrmlToEgg.cxx @@ -30,6 +30,7 @@ VRMLToEgg() : add_normals_options(); add_transform_options(); + set_program_brief("convert VRML 2.0 model files to .egg"); set_program_description ("This program converts VRML 2.0 model files to egg. Animated files, " "and VRML 1.0 files, are not supported."); diff --git a/pandatool/src/vrmlprogs/vrmlTrans.cxx b/pandatool/src/vrmlprogs/vrmlTrans.cxx index 21a27abe62..acf226978e 100644 --- a/pandatool/src/vrmlprogs/vrmlTrans.cxx +++ b/pandatool/src/vrmlprogs/vrmlTrans.cxx @@ -29,6 +29,7 @@ VRMLTrans() : // output files. _preferred_extension = ".wrl"; + set_program_brief("reads and writes VRML 2.0 files"); set_program_description ("This program reads a VRML 2.0 file (.wrl) and writes an " "essentially equivalent .wrl file. It is primarily useful for " diff --git a/pandatool/src/xfileprogs/eggToX.cxx b/pandatool/src/xfileprogs/eggToX.cxx index f0507906f7..244da4405e 100644 --- a/pandatool/src/xfileprogs/eggToX.cxx +++ b/pandatool/src/xfileprogs/eggToX.cxx @@ -26,6 +26,7 @@ EggToX() : EggToSomething("DirectX", ".x", true, false) { add_texture_options(); add_delod_options(0.0); + set_program_brief("convert an .egg file into a DirectX .x file"); set_program_description ("This program reads an Egg file and outputs an equivalent, " "or nearly equivalent, DirectX-style .x file. Only simple " diff --git a/pandatool/src/xfileprogs/xFileToEgg.cxx b/pandatool/src/xfileprogs/xFileToEgg.cxx index 18bc458b25..046761e409 100644 --- a/pandatool/src/xfileprogs/xFileToEgg.cxx +++ b/pandatool/src/xfileprogs/xFileToEgg.cxx @@ -32,6 +32,7 @@ XFileToEgg() : add_normals_options(); add_transform_options(); + set_program_brief("convert a DirectX .x file to an .egg file"); set_program_description ("This program converts DirectX retained-mode (.x) files to egg. " "Polygon meshes, materials, and textures, as well as skeleton " diff --git a/pandatool/src/xfileprogs/xFileTrans.cxx b/pandatool/src/xfileprogs/xFileTrans.cxx index 92333e5c54..8e1b406df4 100644 --- a/pandatool/src/xfileprogs/xFileTrans.cxx +++ b/pandatool/src/xfileprogs/xFileTrans.cxx @@ -29,6 +29,7 @@ XFileTrans() : // output files. _preferred_extension = ".x"; + set_program_brief("reads and writes DirectX .x files"); set_program_description ("This program reads a DirectX retained-mode file (.x) and writes an " "essentially equivalent .x file. It is primarily useful for " From be1eb1d81239b93de09ad70f4f96fc3d60e6308c Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Dec 2014 15:15:29 +0100 Subject: [PATCH 02/83] More minor linux packaging fixes --- .../directscripts/profilepaths-osx.command | 0 .../interfaceMakerPythonNative.cxx | 0 .../interrogate/interfaceMakerPythonNative.h | 0 makepanda/installpanda.py | 19 +++--- makepanda/makepanda.py | 12 ++-- makepanda/makepandacore.py | 61 ++++--------------- makepanda/panda3d.desktop | 2 +- makepanda/pview.desktop | 2 +- 8 files changed, 28 insertions(+), 68 deletions(-) mode change 100644 => 100755 direct/src/directscripts/profilepaths-osx.command mode change 100755 => 100644 dtool/src/interrogate/interfaceMakerPythonNative.cxx mode change 100755 => 100644 dtool/src/interrogate/interfaceMakerPythonNative.h diff --git a/direct/src/directscripts/profilepaths-osx.command b/direct/src/directscripts/profilepaths-osx.command old mode 100644 new mode 100755 diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx old mode 100755 new mode 100644 diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h old mode 100755 new mode 100644 diff --git a/makepanda/installpanda.py b/makepanda/installpanda.py index 20f4fd2773..c35ad8abd3 100644 --- a/makepanda/installpanda.py +++ b/makepanda/installpanda.py @@ -12,7 +12,7 @@ # ######################################################################## -import os, sys, platform, compileall +import os, sys, platform from distutils.sysconfig import get_python_lib from optparse import OptionParser from makepandacore import * @@ -201,9 +201,9 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir( WriteKeysFile(destdir+prefix+"/share/mime-info/panda3d.keys", MIME_INFO) WriteMimeXMLFile(destdir+prefix+"/share/mime/packages/panda3d.xml", MIME_INFO) WriteApplicationsFile(destdir+prefix+"/share/application-registry/panda3d.applications", APP_INFO, MIME_INFO) - oscmd("cp makepanda/pview.desktop "+destdir+prefix+"/share/applications/pview.desktop") - oscmd("cp doc/LICENSE "+destdir+prefix+"/share/panda3d/LICENSE") - oscmd("cp doc/LICENSE "+destdir+prefix+"/include/panda3d/LICENSE") + if os.path.isfile(outputdir+"/bin/pview"): + oscmd("cp makepanda/pview.desktop "+destdir+prefix+"/share/applications/pview.desktop") + oscmd("cp doc/ReleaseNotes "+destdir+prefix+"/share/panda3d/ReleaseNotes") oscmd("echo '"+prefix+"/share/panda3d' > "+destdir+PPATH+"/panda3d.pth") oscmd("echo '"+libdir+"/panda3d'>> "+destdir+PPATH+"/panda3d.pth") @@ -211,22 +211,17 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir( oscmd("echo '"+libdir+"/panda3d'> "+destdir+"/usr/local/libdata/ldconfig/panda3d") else: oscmd("echo '"+libdir+"/panda3d'> "+destdir+"/etc/ld.so.conf.d/panda3d.conf") - oscmd("chmod +x "+destdir+"/etc/ld.so.conf.d/panda3d.conf") + oscmd("cp "+outputdir+"/bin/* "+destdir+prefix+"/bin/") for base in os.listdir(outputdir+"/lib"): if (not base.endswith(".a")) or base == "libp3pystub.a": # We really need to specify -R in order not to follow symlinks on non-GNU oscmd("cp -R -P "+outputdir+"/lib/"+base+" "+destdir+libdir+"/panda3d/"+base) - # rpmlint doesn't like it if we compile pyc. - #for base in os.listdir(destdir+prefix+"/share/panda3d/direct"): - # if ((base != "extensions") and (base != "extensions_native")): - # compileall.compile_dir(destdir+prefix+"/share/panda3d/direct/"+base) - #compileall.compile_dir(destdir+prefix+"/share/panda3d/Pmw") - DeleteCVS(destdir+prefix+"/share/panda3d") + DeleteVCS(destdir+prefix+"/share/panda3d") DeleteBuildFiles(destdir+prefix+"/share/panda3d") DeleteEmptyDirs(destdir+prefix+"/share/panda3d") - DeleteCVS(destdir+prefix+"/include/panda3d") + DeleteVCS(destdir+prefix+"/include/panda3d") DeleteBuildFiles(destdir+prefix+"/include/panda3d") DeleteEmptyDirs(destdir+prefix+"/include/panda3d") diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index e0ad2a8150..1921a71fe8 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2583,7 +2583,7 @@ CopyFile(GetOutputDir()+'/include/parser-inc/glew/','dtool/src/parser-inc/glew.h CopyFile(GetOutputDir()+'/include/parser-inc/Eigen/','dtool/src/parser-inc/Dense') CopyFile(GetOutputDir()+'/include/parser-inc/Eigen/','dtool/src/parser-inc/StdVector') CopyFile(GetOutputDir()+'/include/parser-inc/Rocket/Core/','dtool/src/parser-inc/RenderInterface.h') -DeleteCVS(GetOutputDir()+'/include/parser-inc') +DeleteVCS(GetOutputDir()+'/include/parser-inc') ######################################################################## # @@ -6158,7 +6158,7 @@ Conflicts: panda3d Replaces: panda3d Maintainer: rdb Installed-Size: INSTSIZE -Description: The Panda3D free 3D engine SDK +Description: Panda3D free 3D engine SDK Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost. Panda3D's intended game-development language is Python. The engine itself is written in C++, and utilizes an automatic wrapper-generator to expose the complete functionality of the engine in a Python interface. . @@ -6285,10 +6285,11 @@ def MakeInstallerLinux(): if os.path.exists("/usr/bin/dpkg-deb"): # Invoke installpanda.py to install it into a temporary dir + lib_dir = GetDebLibDir() if RUNTIME: - InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=GetDebLibDir()) + InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=lib_dir) else: - InstallPanda(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=GetDebLibDir()) + InstallPanda(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=lib_dir) oscmd("chmod -R 755 targetroot/usr/share/panda3d") oscmd("mkdir -p targetroot/usr/share/man/man1") oscmd("cp doc/man/*.1 targetroot/usr/share/man/man1/") @@ -6311,7 +6312,6 @@ def MakeInstallerLinux(): # Determine the package name and the locations that # dpkg-shlibdeps should look in for executables. - lib_dir = GetLibDir() pkg_version = DEBVERSION if RUNTIME: pkg_name = "panda3d-runtime" @@ -6507,7 +6507,7 @@ def MakeInstallerOSX(): oscmd("cp -R samples/* dstroot/samples/Developer/Examples/Panda3D/") oscmd("chmod -R 0775 dstroot/*") - DeleteCVS("dstroot") + DeleteVCS("dstroot") DeleteBuildFiles("dstroot") # We need to be root to perform a chown. Bleh. # Fortunately PackageMaker does it for us, on 10.5 and above. diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 2c99416823..0f25cdac75 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -22,6 +22,8 @@ else: SUFFIX_INC = [".cxx",".c",".h",".I",".yxx",".lxx",".mm",".rc",".r"] SUFFIX_DLL = [".dll",".dlo",".dle",".dli",".dlm",".mll",".exe",".pyd",".ocx"] SUFFIX_LIB = [".lib",".ilb"] +VCS_DIRS = set(["CVS", "CVSROOT", ".git", ".hg"]) +VCS_FILES = set([".cvsignore", ".gitignore", ".gitmodules", ".hgignore"]) STARTTIME = time.time() MAINTHREAD = threading.currentThread() OUTPUTDIR = "built" @@ -534,16 +536,6 @@ def oscmd(cmd, ignoreError = False): ## ## GetDirectoryContents ## -## At times, makepanda will use a function like "os.listdir" to process -## all the files in a directory. Unfortunately, that means that any -## accidental addition of a file to a directory could cause makepanda -## to misbehave without warning. -## -## To alleviate this weakness, we created GetDirectoryContents. This -## uses "os.listdir" to fetch the directory contents, but then it -## compares the results to the appropriate CVS/Entries to see if -## they match. If not, it prints a big warning message. -## ######################################################################## def GetDirectoryContents(dir, filters="*", skip=[]): @@ -555,33 +547,6 @@ def GetDirectoryContents(dir, filters="*", skip=[]): for file in fnmatch.filter(files, filter): if (skip.count(file)==0) and (os.path.isfile(dir + "/" + file)): actual[file] = 1 - if (os.path.isfile(dir + "/CVS/Entries")): - cvs = {} - srchandle = open(dir + "/CVS/Entries", "r") - files = [] - for line in srchandle: - if (line[0]=="/"): - s = line.split("/",2) - if (len(s)==3): - files.append(s[1]) - srchandle.close() - for filter in filters: - for file in fnmatch.filter(files, filter): - if (skip.count(file)==0): - cvs[file] = 1 - - #XXX this happens all the time, do we really need to warn about this? - #for file in actual.keys(): - # if (file not in cvs and VERBOSE): - # msg = "%sWARNING: %s is in %s, but not in CVS%s" % (GetColor("red"), ColorText("green", file), ColorText("green", dir), GetColor()) - # print msg - # WARNINGS.append(msg) - - for file in cvs.keys(): - if (file not in actual and VERBOSE): - msg = "%sWARNING: %s is not in %s, but is in CVS%s" % (GetColor("red"), ColorText("green", file), ColorText("green", dir), GetColor()) - print(msg) - WARNINGS.append(msg) results = list(actual.keys()) results.sort() @@ -1023,16 +988,16 @@ def ConditionalWriteFile(dest, desiredcontents): sys.stdout.flush() WriteFile(dest, desiredcontents) -def DeleteCVS(dir): +def DeleteVCS(dir): if dir == "": dir = "." for entry in os.listdir(dir): subdir = os.path.join(dir, entry) if (os.path.isdir(subdir)): - if (entry == "CVS" or entry == "CVSROOT"): + if entry in VCS_DIRS: shutil.rmtree(subdir) else: - DeleteCVS(subdir) - elif (os.path.isfile(subdir) and (entry == ".cvsignore" or entry.startswith(".#"))): + DeleteVCS(subdir) + elif (os.path.isfile(subdir) and (entry in VCS_FILES or entry.startswith(".#"))): os.remove(subdir) def DeleteBuildFiles(dir): @@ -2432,16 +2397,16 @@ def CopyAllJavaSources(dir, skip=[]): WriteBinaryFile(dstfile, ReadBinaryFile(srcfile)) JustBuilt([dstfile], [srcfile]) -def CopyTree(dstdir, srcdir, omitCVS=True): +def CopyTree(dstdir, srcdir, omitVCS=True): if (os.path.isdir(dstdir)): for entry in os.listdir(srcdir): srcpth = os.path.join(srcdir, entry) dstpth = os.path.join(dstdir, entry) if (os.path.isfile(srcpth)): - if (not omitCVS or entry != ".cvsignore"): + if not omitVCS or entry not in VCS_FILES: CopyFile(dstpth, srcpth) else: - if (not omitCVS or entry != "CVS"): + if not omitVCS or entry not in VCS_DIRS: CopyTree(dstpth, srcpth) else: if sys.platform == 'win32': @@ -2449,8 +2414,8 @@ def CopyTree(dstdir, srcdir, omitCVS=True): else: cmd = 'cp -R -f ' + srcdir + ' ' + dstdir oscmd(cmd) - if omitCVS: - DeleteCVS(dstdir) + if omitVCS: + DeleteVCS(dstdir) def CopyPythonTree(dstdir, srcdir, lib2to3_fixers=[]): if (not os.path.isdir(dstdir)): @@ -2470,7 +2435,7 @@ def CopyPythonTree(dstdir, srcdir, lib2to3_fixers=[]): dstpth = os.path.join(dstdir, entry) if (os.path.isfile(srcpth)): base, ext = os.path.splitext(entry) - if (entry != ".cvsignore" and ext not in SUFFIX_INC + ['.pyc', '.pyo']): + if entry not in VCS_FILES and ext not in SUFFIX_INC + ['.pyc', '.pyo']: if (NeedsBuild([dstpth], [srcpth])): WriteBinaryFile(dstpth, ReadBinaryFile(srcpth)) @@ -2479,7 +2444,7 @@ def CopyPythonTree(dstdir, srcdir, lib2to3_fixers=[]): else: JustBuilt([dstpth], [srcpth]) - elif (entry != "CVS"): + elif entry not in VCS_DIRS: CopyPythonTree(dstpth, srcpth, lib2to3_fixers) for dstpth, srcpth in refactor: diff --git a/makepanda/panda3d.desktop b/makepanda/panda3d.desktop index 873bfef491..ec988ad64b 100644 --- a/makepanda/panda3d.desktop +++ b/makepanda/panda3d.desktop @@ -7,5 +7,5 @@ StartupNotify=true NoDisplay=true Terminal=false Type=Application -Categories=Game;Viewer; +Categories=Game;3DGraphics;Viewer; MimeType=application/x-panda3d; diff --git a/makepanda/pview.desktop b/makepanda/pview.desktop index 14609243be..c64d8e2fb5 100644 --- a/makepanda/pview.desktop +++ b/makepanda/pview.desktop @@ -8,5 +8,5 @@ StartupNotify=true NoDisplay=true Terminal=true Type=Application -Categories=Viewer; +Categories=Graphics;Utility;3DGraphics;Viewer; MimeType=model/x-egg;model/x-compressed-egg;model/x-bam;model/x-compressed-bam; From 24b8bd8b964965c4f210a164b701685992a486e2 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Dec 2014 15:58:06 +0100 Subject: [PATCH 03/83] Fix regression in Volumetric Lighting filter --- direct/src/filter/CommonFilters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/direct/src/filter/CommonFilters.py b/direct/src/filter/CommonFilters.py index ee3de9ac8d..d5481aa749 100644 --- a/direct/src/filter/CommonFilters.py +++ b/direct/src/filter/CommonFilters.py @@ -167,7 +167,7 @@ class CommonFilters: auxbits |= AuxBitplaneAttrib.ABOGlow if ("VolumetricLighting" in configuration): - needtex[configuration["VolumetricLighting"].source] = True + needtex.add(configuration["VolumetricLighting"].source) for tex in needtex: self.textures[tex] = Texture("scene-" + tex) From 8c0b0990a8327429de741b89ea5c4df4344163df Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 30 Dec 2014 00:06:15 +0100 Subject: [PATCH 04/83] Dramatically improve performance when sorting vectors of PointerTo objects --- panda/src/express/pointerTo.h | 14 ++++++++++++++ panda/src/express/pointerToVoid.I | 10 ++++++++++ panda/src/express/pointerToVoid.h | 4 ++++ 3 files changed, 28 insertions(+) diff --git a/panda/src/express/pointerTo.h b/panda/src/express/pointerTo.h index b989b0f944..144bc0eb87 100644 --- a/panda/src/express/pointerTo.h +++ b/panda/src/express/pointerTo.h @@ -163,6 +163,20 @@ PUBLISHED: }; +// The existence of these functions makes it possible to sort vectors +// of PointerTo objects without incurring the cost of unnecessary +// reference count changes. The performance difference is dramatic! +template +void swap(PointerTo &one, PointerTo &two) { + one.swap(two); +} + +template +void swap(ConstPointerTo &one, ConstPointerTo &two) { + one.swap(two); +} + + // Finally, we'll define a couple of handy abbreviations to save on // all that wasted typing time. diff --git a/panda/src/express/pointerToVoid.I b/panda/src/express/pointerToVoid.I index 0834b25f60..108e959323 100644 --- a/panda/src/express/pointerToVoid.I +++ b/panda/src/express/pointerToVoid.I @@ -105,3 +105,13 @@ operator != (const PointerToVoid &other) const { return _void_ptr != other._void_ptr; } +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::swap +// Access: Public +// Description: Swaps the contents of this PointerTo with the other, +// without touching the reference counts. +//////////////////////////////////////////////////////////////////// +INLINE void PointerToVoid:: +swap(PointerToVoid &other) { + std::swap(_void_ptr, other._void_ptr); +} diff --git a/panda/src/express/pointerToVoid.h b/panda/src/express/pointerToVoid.h index 7b1a9ff335..2556b1eb8c 100644 --- a/panda/src/express/pointerToVoid.h +++ b/panda/src/express/pointerToVoid.h @@ -20,6 +20,8 @@ #include "memoryBase.h" #include "atomicAdjust.h" +#include + //////////////////////////////////////////////////////////////////// // Class : PointerToVoid // Description : This is the non-template part of the base class for @@ -52,6 +54,8 @@ public: INLINE bool operator == (const PointerToVoid &other) const; INLINE bool operator != (const PointerToVoid &other) const; + INLINE void swap(PointerToVoid &other); + protected: // Within the PointerToVoid class, we only store a void pointer. // This is actually the (To *) pointer that is typecast to (void *) From 624b3dad143492fdcf5d758f7d98fc1b002fb7d9 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 30 Dec 2014 02:00:43 +0100 Subject: [PATCH 05/83] Delete DirectX 8 support --- direct/src/p3d/panda3d.pdef | 3 +- doc/Config.pp.sample | 7 +- doc/INSTALL-MK | 1 - doc/INSTALL-PP | 11 +- dtool/Config.Android.pp | 1 - dtool/Config.pp | 12 - dtool/LocalSetup.pp | 16 - dtool/Package.pp | 10 - dtool/pptempl/Global.pp | 14 - makepanda/config.in | 1 - makepanda/makepanda.py | 22 - makepanda/makepanda.vcproj | 1 - makepanda/makepandacore.py | 21 +- panda/metalibs/pandadx8/Sources.pp | 24 - panda/metalibs/pandadx8/pandadx8.cxx | 38 - panda/metalibs/pandadx8/pandadx8.h | 14 - panda/src/configfiles/panda.prc.pp | 3 - panda/src/dxgsg8/Sources.pp | 42 - panda/src/dxgsg8/config_dxgsg8.cxx | 155 - panda/src/dxgsg8/config_dxgsg8.h | 60 - panda/src/dxgsg8/dxGeomMunger8.I | 40 - panda/src/dxgsg8/dxGeomMunger8.cxx | 322 -- panda/src/dxgsg8/dxGeomMunger8.h | 82 - panda/src/dxgsg8/dxGraphicsDevice8.cxx | 42 - panda/src/dxgsg8/dxGraphicsDevice8.h | 51 - panda/src/dxgsg8/dxGraphicsStateGuardian8.I | 159 - panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 4674 ----------------- panda/src/dxgsg8/dxGraphicsStateGuardian8.h | 309 -- panda/src/dxgsg8/dxIndexBufferContext8.I | 14 - panda/src/dxgsg8/dxIndexBufferContext8.cxx | 173 - panda/src/dxgsg8/dxIndexBufferContext8.h | 62 - panda/src/dxgsg8/dxInput8.cxx | 272 - panda/src/dxgsg8/dxInput8.h | 41 - panda/src/dxgsg8/dxTextureContext8.I | 69 - panda/src/dxgsg8/dxTextureContext8.cxx | 1853 ------- panda/src/dxgsg8/dxTextureContext8.h | 89 - panda/src/dxgsg8/dxVertexBufferContext8.I | 14 - panda/src/dxgsg8/dxVertexBufferContext8.cxx | 299 -- panda/src/dxgsg8/dxVertexBufferContext8.h | 63 - panda/src/dxgsg8/dxgsg8base.h | 208 - panda/src/dxgsg8/p3dxgsg8_composite1.cxx | 10 - panda/src/dxgsg8/wdxGraphicsBuffer8.I | 27 - panda/src/dxgsg8/wdxGraphicsBuffer8.cxx | 575 -- panda/src/dxgsg8/wdxGraphicsBuffer8.h | 99 - panda/src/dxgsg8/wdxGraphicsPipe8.I | 13 - panda/src/dxgsg8/wdxGraphicsPipe8.cxx | 931 ---- panda/src/dxgsg8/wdxGraphicsPipe8.h | 122 - panda/src/dxgsg8/wdxGraphicsWindow8.I | 13 - panda/src/dxgsg8/wdxGraphicsWindow8.cxx | 1241 ----- panda/src/dxgsg8/wdxGraphicsWindow8.h | 108 - panda/src/framework/Sources.pp | 2 - panda/src/framework/pandaFramework.cxx | 45 +- panda/src/windisplay/Sources.pp | 6 +- panda/src/windisplay/winDetectDx.h | 105 +- panda/src/windisplay/winDetectDx8.cxx | 48 - panda/src/windisplay/winDetectDx9.cxx | 1 - panda/src/windisplay/winGraphicsPipe.cxx | 39 +- pandatool/src/scripts/builder.cshrc | 1 - 58 files changed, 77 insertions(+), 12601 deletions(-) delete mode 100644 panda/metalibs/pandadx8/Sources.pp delete mode 100644 panda/metalibs/pandadx8/pandadx8.cxx delete mode 100644 panda/metalibs/pandadx8/pandadx8.h delete mode 100644 panda/src/dxgsg8/Sources.pp delete mode 100644 panda/src/dxgsg8/config_dxgsg8.cxx delete mode 100644 panda/src/dxgsg8/config_dxgsg8.h delete mode 100644 panda/src/dxgsg8/dxGeomMunger8.I delete mode 100644 panda/src/dxgsg8/dxGeomMunger8.cxx delete mode 100644 panda/src/dxgsg8/dxGeomMunger8.h delete mode 100644 panda/src/dxgsg8/dxGraphicsDevice8.cxx delete mode 100755 panda/src/dxgsg8/dxGraphicsDevice8.h delete mode 100644 panda/src/dxgsg8/dxGraphicsStateGuardian8.I delete mode 100644 panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx delete mode 100644 panda/src/dxgsg8/dxGraphicsStateGuardian8.h delete mode 100644 panda/src/dxgsg8/dxIndexBufferContext8.I delete mode 100644 panda/src/dxgsg8/dxIndexBufferContext8.cxx delete mode 100644 panda/src/dxgsg8/dxIndexBufferContext8.h delete mode 100644 panda/src/dxgsg8/dxInput8.cxx delete mode 100644 panda/src/dxgsg8/dxInput8.h delete mode 100644 panda/src/dxgsg8/dxTextureContext8.I delete mode 100644 panda/src/dxgsg8/dxTextureContext8.cxx delete mode 100644 panda/src/dxgsg8/dxTextureContext8.h delete mode 100644 panda/src/dxgsg8/dxVertexBufferContext8.I delete mode 100644 panda/src/dxgsg8/dxVertexBufferContext8.cxx delete mode 100644 panda/src/dxgsg8/dxVertexBufferContext8.h delete mode 100644 panda/src/dxgsg8/dxgsg8base.h delete mode 100644 panda/src/dxgsg8/p3dxgsg8_composite1.cxx delete mode 100644 panda/src/dxgsg8/wdxGraphicsBuffer8.I delete mode 100644 panda/src/dxgsg8/wdxGraphicsBuffer8.cxx delete mode 100644 panda/src/dxgsg8/wdxGraphicsBuffer8.h delete mode 100644 panda/src/dxgsg8/wdxGraphicsPipe8.I delete mode 100644 panda/src/dxgsg8/wdxGraphicsPipe8.cxx delete mode 100644 panda/src/dxgsg8/wdxGraphicsPipe8.h delete mode 100644 panda/src/dxgsg8/wdxGraphicsWindow8.I delete mode 100644 panda/src/dxgsg8/wdxGraphicsWindow8.cxx delete mode 100644 panda/src/dxgsg8/wdxGraphicsWindow8.h delete mode 100644 panda/src/windisplay/winDetectDx8.cxx diff --git a/direct/src/p3d/panda3d.pdef b/direct/src/p3d/panda3d.pdef index 6c93c4485d..bc86846f63 100755 --- a/direct/src/p3d/panda3d.pdef +++ b/direct/src/p3d/panda3d.pdef @@ -96,7 +96,7 @@ class panda3d(package): # platform-specific extension for an executable. file('libpandagl.dll', 'libp3tinydisplay.dll') if platform.startswith('win'): - file('libpandadx8.dll', 'libpandadx9.dll') + file('libpandadx9.dll') # A basic config file is needed to lay some some fundamental runtime # variables. @@ -104,7 +104,6 @@ class panda3d(package): auxDisplays = """ aux-display pandagl aux-display pandadx9 -aux-display pandadx8 aux-display p3tinydisplay """ else: diff --git a/doc/Config.pp.sample b/doc/Config.pp.sample index cc9fa0cea9..567961384b 100644 --- a/doc/Config.pp.sample +++ b/doc/Config.pp.sample @@ -32,13 +32,10 @@ // Note the use of the Panda filename convention, with forward slashes // instead of backslashes, and /c/ instead of c:/ . -#define DX8_IPATH /c/DXSDK-OCT2004/include -#define DX8_LPATH /c/DXSDK-OCT2004/lib #define DX9_IPATH /c/DXSDK-DEC2006/include #define DX9_LPATH /c/DXSDK-DEC2006/lib -// If for any reason you need to turn off either the DX8 or DX9 builds, -// you can uncomment one of the following lines. (Defining a +// If for any reason you need to turn off the DX9 builds, +// you can uncomment the following line. (Defining a // variable to an empty string means setting it false.) -//#define HAVE_DX8 //#define HAVE_DX9 diff --git a/doc/INSTALL-MK b/doc/INSTALL-MK index 2a5624a6a1..dd1536e60b 100644 --- a/doc/INSTALL-MK +++ b/doc/INSTALL-MK @@ -141,7 +141,6 @@ it will show you the available command-line options: --use-max9 --no-max9 (enable/disable use of MAX9) --use-max2009 --no-max2009 (enable/disable use of MAX2009) --use-max2010 --no-max2010 (enable/disable use of MAX2010) - --use-dx8 --no-dx8 (enable/disable use of DX8) --use-dx9 --no-dx9 (enable/disable use of DX9) --use-python --no-python (enable/disable use of PYTHON) --use-zlib --no-zlib (enable/disable use of ZLIB) diff --git a/doc/INSTALL-PP b/doc/INSTALL-PP index 46fd4e946d..2f3fc57087 100644 --- a/doc/INSTALL-PP +++ b/doc/INSTALL-PP @@ -251,13 +251,13 @@ indicate a variable is true by defining it to some nonempty string (e.g. "yes" or "1"), and false by defining it to nothing. For example: - #define HAVE_DX8 1 + #define HAVE_DX9 1 Indicates you have the DirectX SDK installed, while - #define HAVE_DX8 + #define HAVE_DX9 -Indicates you do not. Do not be tempted to define HAVE_DX8 to no or 0; +Indicates you do not. Do not be tempted to define HAVE_DX9 to no or 0; since these are both nonempty strings, they are considered to represent true! Also, don't try to use a pair of quotation marks to represent the empty string, since the quotation marks become part of @@ -312,11 +312,6 @@ find useful are: header and library files, and the name of the VRPN libraries, if VRPN is installed on your system. - DX8_IPATH / DX8_LPATH / DX8_LIBS - the full pathname to the - DirectX 8.1 SDK header and library files, if you have installed - this SDK. (You must currently install this SDK in order to - build DirectX8 support for Panda.) - DX9_IPATH / DX9_LPATH / DX9_LIBS - the full pathname to the DirectX 9 SDK header and library files, if you have installed this SDK. (You must currently install this SDK in order to diff --git a/dtool/Config.Android.pp b/dtool/Config.Android.pp index d5fe1f9eef..ff4e57f89e 100644 --- a/dtool/Config.Android.pp +++ b/dtool/Config.Android.pp @@ -45,7 +45,6 @@ // We don't have these, of course, so let's disable // them for convenience in case they were autodetected. -#define HAVE_DX8 #define HAVE_DX9 #define HAVE_CG diff --git a/dtool/Config.pp b/dtool/Config.pp index 08e0d31ded..cf59d047b6 100644 --- a/dtool/Config.pp +++ b/dtool/Config.pp @@ -588,12 +588,6 @@ #define CGGL_LIBS $[if $[WINDOWS_PLATFORM],cgGL.lib,CgGL] #defer HAVE_CGGL $[or $[CGGL_FRAMEWORK],$[and $[HAVE_CG],$[libtest $[CGGL_LPATH],$[CGGL_LIBS]]]] -// Is CgDX8 installed, and where? -#defer CGDX8_IPATH $[CG_IPATH] -#defer CGDX8_LPATH $[CG_LPATH] -#define CGDX8_LIBS $[if $[WINDOWS_PLATFORM],cgD3D8.lib,CgDX8] -#defer HAVE_CGDX8 $[and $[HAVE_CG],$[libtest $[CGDX8_LPATH],$[CGDX8_LIBS]]] - // Is CgDX9 installed, and where? #defer CGDX9_IPATH $[CG_IPATH] #defer CGDX9_LPATH $[CG_LPATH] @@ -740,12 +734,6 @@ #define HAVE_COCOA #define HAVE_CARBON -// Is DirectX8 available, and should we try to build with it? -#define DX8_IPATH -#define DX8_LPATH -#define DX8_LIBS d3d8.lib d3dx8.lib dxerr8.lib -#defer HAVE_DX8 $[libtest $[DX8_LPATH],$[DX8_LIBS]] - // Is DirectX9 available, and should we try to build with it? #define DX9_IPATH #define DX9_LPATH diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index c9b9efddcf..a014ba608d 100644 --- a/dtool/LocalSetup.pp +++ b/dtool/LocalSetup.pp @@ -66,11 +66,6 @@ #else #print - Did not find Cg OpenGL API #endif -#if $[HAVE_CGDX8] -#print + Cg DX8 API -#else -#print - Did not find Cg DX8 API -#endif #if $[HAVE_CGDX9] #print + Cg DX9 API #else @@ -151,11 +146,6 @@ #else #print - Did not find OpenGL ES 2 #endif -#if $[HAVE_DX8] -#print + DirectX8 -#else -#print - Did not find DirectX8 -#endif #if $[HAVE_DX9] #print + DirectX9 #else @@ -389,9 +379,6 @@ $[cdefine HAVE_CG] /* Define if we have CGGL installed. */ $[cdefine HAVE_CGGL] -/* Define if we have CGDX8 installed. */ -$[cdefine HAVE_CGDX8] - /* Define if we have CGDX9 installed. */ $[cdefine HAVE_CGDX9] @@ -441,9 +428,6 @@ $[cdefine HAVE_EGL] /* Define if we have Windows-GL installed and want to build for Wgl. */ $[cdefine HAVE_WGL] -/* Define if we have DirectX installed and want to build for DX. */ -$[cdefine HAVE_DX8] - /* Define if we have DirectX installed and want to build for DX. */ $[cdefine HAVE_DX9] diff --git a/dtool/Package.pp b/dtool/Package.pp index 64f361ae82..b0b787eb42 100644 --- a/dtool/Package.pp +++ b/dtool/Package.pp @@ -191,11 +191,6 @@ #set CGGL_LIBS $[CGGL_LIBS] #set HAVE_CGGL $[HAVE_CGGL] -#set CGDX8_IPATH $[unixfilename $[CGDX8_IPATH]] -#set CGDX8_LPATH $[unixfilename $[CGDX8_LPATH]] -#set CGDX8_LIBS $[CGDX8_LIBS] -#set HAVE_CGDX8 $[HAVE_CGDX8] - #set CGDX9_IPATH $[unixfilename $[CGDX9_IPATH]] #set CGDX9_LPATH $[unixfilename $[CGDX9_LPATH]] #set CGDX9_LIBS $[CGDX9_LIBS] @@ -250,11 +245,6 @@ #set HAVE_COCOA $[HAVE_COCOA] #set HAVE_CARBON $[HAVE_CARBON] -#set DX8_IPATH $[unixfilename $[DX8_IPATH]] -#set DX8_LPATH $[unixfilename $[DX8_LPATH]] -#set DX8_LIBS $[DX8_LIBS] -#set HAVE_DX8 $[HAVE_DX8] - #set DX9_IPATH $[unixfilename $[DX9_IPATH]] #set DX9_LPATH $[unixfilename $[DX9_LPATH]] #set DX9_LIBS $[DX9_LIBS] diff --git a/dtool/pptempl/Global.pp b/dtool/pptempl/Global.pp index 22adc27ae0..7cf3ab660f 100644 --- a/dtool/pptempl/Global.pp +++ b/dtool/pptempl/Global.pp @@ -199,13 +199,6 @@ #define egl_libs $[EGL_LIBS] #endif -#if $[HAVE_DX8] - #define dx8_ipath $[wildcard $[DX8_IPATH]] - #define dx8_lpath $[wildcard $[DX8_LPATH]] - #define dx8_cflags $[DX8_CFLAGS] - #define dx8_libs $[DX8_LIBS] -#endif - #if $[HAVE_DX9] #define dx9_ipath $[wildcard $[DX9_IPATH]] #define dx9_lpath $[wildcard $[DX9_LPATH]] @@ -329,13 +322,6 @@ #define cggl_framework $[CGGL_FRAMEWORK] #endif -#if $[HAVE_CGDX8] - #define cgdx8_ipath $[wildcard $[CGDX8_IPATH]] - #define cgdx8_lpath $[wildcard $[CGDX8_LPATH]] - #define cgdx8_cflags $[CGDX8_CFLAGS] - #define cgdx8_libs $[CGDX8_LIBS] -#endif - #if $[HAVE_CGDX9] #define cgdx9_ipath $[wildcard $[CGDX9_IPATH]] #define cgdx9_lpath $[wildcard $[CGDX9_LPATH]] diff --git a/makepanda/config.in b/makepanda/config.in index 2e441d0d92..9b0943918d 100755 --- a/makepanda/config.in +++ b/makepanda/config.in @@ -14,7 +14,6 @@ load-display pandagl #load-display pandadx9 -#load-display pandadx8 #load-display pandagles #load-display p3tinydisplay diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 1921a71fe8..04b1df78cd 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1933,7 +1933,6 @@ DTOOL_CONFIG=[ ("HAVE_GLX", 'UNDEF', '1'), ("HAVE_EGL", 'UNDEF', 'UNDEF'), ("HAVE_WGL", '1', 'UNDEF'), - ("HAVE_DX8", 'UNDEF', 'UNDEF'), ("HAVE_DX9", 'UNDEF', 'UNDEF'), ("HAVE_CHROMIUM", 'UNDEF', 'UNDEF'), ("HAVE_THREADS", '1', '1'), @@ -2491,7 +2490,6 @@ if (GetTarget() == 'windows'): configprc = configprc.replace("$HOME/.panda3d", "$USER_APPDATA/Panda3D-%s" % MAJOR_VERSION) else: configprc = configprc.replace("aux-display pandadx9", "") - configprc = configprc.replace("aux-display pandadx8", "") if (GetTarget() == 'darwin'): configprc = configprc.replace(".panda3d/cache", "Library/Caches/Panda3D-%s" % MAJOR_VERSION) @@ -2663,8 +2661,6 @@ CopyAllHeaders('panda/src/audiotraits') CopyAllHeaders('panda/src/distort') CopyAllHeaders('panda/src/downloadertools') CopyAllHeaders('panda/src/windisplay') -CopyAllHeaders('panda/src/dxgsg8') -CopyAllHeaders('panda/metalibs/pandadx8') CopyAllHeaders('panda/src/dxgsg9') CopyAllHeaders('panda/metalibs/pandadx9') CopyAllHeaders('panda/src/egg') @@ -3922,30 +3918,12 @@ if (PkgSkip("ZLIB")==0 and not RTDIST and not RUNTIME and PkgSkip("DEPLOYTOOLS") if (GetTarget() == 'windows' and not RUNTIME): OPTS=['DIR:panda/src/windisplay', 'BUILDING:PANDAWIN'] TargetAdd('p3windisplay_composite1.obj', opts=OPTS+["BIGOBJ"], input='p3windisplay_composite1.cxx') - TargetAdd('p3windisplay_windetectdx8.obj', opts=OPTS + ["DX8"], input='winDetectDx8.cxx') TargetAdd('p3windisplay_windetectdx9.obj', opts=OPTS + ["DX9"], input='winDetectDx9.cxx') TargetAdd('libp3windisplay.dll', input='p3windisplay_composite1.obj') - TargetAdd('libp3windisplay.dll', input='p3windisplay_windetectdx8.obj') TargetAdd('libp3windisplay.dll', input='p3windisplay_windetectdx9.obj') TargetAdd('libp3windisplay.dll', input=COMMON_PANDA_LIBS) TargetAdd('libp3windisplay.dll', opts=['WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM',"BIGOBJ"]) -# -# DIRECTORY: panda/metalibs/pandadx8/ -# - -if PkgSkip("DX8")==0 and not RUNTIME: - OPTS=['DIR:panda/src/dxgsg8', 'DIR:panda/metalibs/pandadx8', 'BUILDING:PANDADX', 'DX8'] - TargetAdd('p3dxgsg8_dxGraphicsStateGuardian8.obj', opts=OPTS, input='dxGraphicsStateGuardian8.cxx') - TargetAdd('p3dxgsg8_composite1.obj', opts=OPTS, input='p3dxgsg8_composite1.cxx') - TargetAdd('pandadx8_pandadx8.obj', opts=OPTS, input='pandadx8.cxx') - TargetAdd('libpandadx8.dll', input='pandadx8_pandadx8.obj') - TargetAdd('libpandadx8.dll', input='p3dxgsg8_dxGraphicsStateGuardian8.obj') - TargetAdd('libpandadx8.dll', input='p3dxgsg8_composite1.obj') - TargetAdd('libpandadx8.dll', input='libp3windisplay.dll') - TargetAdd('libpandadx8.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libpandadx8.dll', opts=['MODULE', 'ADVAPI', 'WINGDI', 'WINKERNEL', 'WINUSER', 'WINMM', 'DX8']) - # # DIRECTORY: panda/metalibs/pandadx9/ # diff --git a/makepanda/makepanda.vcproj b/makepanda/makepanda.vcproj index 93ca29fffc..1d8df0eeff 100755 --- a/makepanda/makepanda.vcproj +++ b/makepanda/makepanda.vcproj @@ -2462,7 +2462,6 @@ - diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 0f25cdac75..795d601b2b 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -93,7 +93,7 @@ MAXVERSIONINFO = [("MAX6", "SOFTWARE\\Autodesk\\3DSMAX\\6.0", "installdir", "max MAYAVERSIONS = [] MAXVERSIONS = [] -DXVERSIONS = ["DX8","DX9"] +DXVERSIONS = ["DX9"] for (ver,key) in MAYAVERSIONINFO: MAYAVERSIONS.append(ver) @@ -1644,7 +1644,6 @@ def GetSdkDir(sdkname, sdkkey = None): def SdkLocateDirectX( strMode = 'default' ): if (GetHost() != "windows"): return if strMode == 'default': - GetSdkDir("directx8", "DX8") GetSdkDir("directx9", "DX9") if ("DX9" not in SDK): strMode = 'latest' @@ -1681,18 +1680,12 @@ def SdkLocateDirectX( strMode = 'default' ): print("Using DirectX SDK March 2009") SDK["DX9"] = dir.replace("\\", "/").rstrip("/") archStr = GetTargetArch() - if ("DX9" not in SDK) or ("DX8" not in SDK): + if ("DX9" not in SDK): uninstaller = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" for subdir in ListRegistryKeys(uninstaller): if (subdir[0]=="{"): dir = GetRegistryKey(uninstaller+"\\"+subdir, "InstallLocation") if (dir != 0): - if (("DX8" not in SDK) and - (os.path.isfile(dir+"\\Include\\d3d8.h")) and - (os.path.isfile(dir+"\\Include\\d3dx8.h")) and - (os.path.isfile(dir+"\\Lib\\d3d8.lib")) and - (os.path.isfile(dir+"\\Lib\\d3dx8.lib"))): - SDK["DX8"] = dir.replace("\\", "/").rstrip("/") if (("DX9" not in SDK) and (os.path.isfile(dir+"\\Include\\d3d9.h")) and (os.path.isfile(dir+"\\Include\\d3dx9.h")) and @@ -1743,18 +1736,12 @@ def SdkLocateDirectX( strMode = 'default' ): exit("Couldn't find DirectX March 2009 SDK") elif strMode == 'aug2006': archStr = GetTargetArch() - if ("DX9" not in SDK) or ("DX8" not in SDK): + if ("DX9" not in SDK): uninstaller = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" for subdir in ListRegistryKeys(uninstaller): if (subdir[0]=="{"): dir = GetRegistryKey(uninstaller+"\\"+subdir, "InstallLocation") if (dir != 0): - if (("DX8" not in SDK) and - (os.path.isfile(dir+"\\Include\\d3d8.h")) and - (os.path.isfile(dir+"\\Include\\d3dx8.h")) and - (os.path.isfile(dir+"\\Lib\\d3d8.lib")) and - (os.path.isfile(dir+"\\Lib\\d3dx8.lib"))): - SDK["DX8"] = dir.replace("\\", "/").rstrip("/") if (("DX9" not in SDK) and (os.path.isfile(dir+"\\Include\\d3d9.h")) and (os.path.isfile(dir+"\\Include\\d3dx9.h")) and @@ -2074,7 +2061,7 @@ def SdkLocateAndroid(): ######################################################################## def SdkAutoDisableDirectX(): - for ver in ["DX8","DX9","DIRECTCAM"]: + for ver in ["DX9", "DIRECTCAM"]: if (PkgSkip(ver)==0): if (ver not in SDK): if (GetHost() == "windows"): diff --git a/panda/metalibs/pandadx8/Sources.pp b/panda/metalibs/pandadx8/Sources.pp deleted file mode 100644 index aae0fed0b8..0000000000 --- a/panda/metalibs/pandadx8/Sources.pp +++ /dev/null @@ -1,24 +0,0 @@ -#define BUILD_DIRECTORY $[HAVE_DX8] - -// DIR_TYPE "metalib" indicates we are building a shared library that -// consists mostly of references to other shared libraries. Under -// Windows, this directly produces a DLL (as opposed to the regular -// src libraries, which don't produce anything but a pile of OBJ files -// under Windows). - -#define DIR_TYPE metalib -#define BUILDING_DLL BUILDING_PANDADX - -#define COMPONENT_LIBS \ - p3dxgsg8 -#define LOCAL_LIBS p3gsgbase p3display p3express p3gobj -#define OTHER_LIBS p3dtoolconfig p3dtool - -#begin metalib_target - #define TARGET pandadx8 - #define SOURCES pandadx8.cxx - #define WIN_SYS_LIBS \ - ddraw.lib dxguid.lib winmm.lib \ - kernel32.lib gdi32.lib user32.lib advapi32.lib $[WIN_SYS_LIBS] -#end metalib_target - diff --git a/panda/metalibs/pandadx8/pandadx8.cxx b/panda/metalibs/pandadx8/pandadx8.cxx deleted file mode 100644 index 32adf5ad1b..0000000000 --- a/panda/metalibs/pandadx8/pandadx8.cxx +++ /dev/null @@ -1,38 +0,0 @@ -// Filename: pandadx.cxx -// Created by: drose (15May00) -// -//////////////////////////////////////////////////////////////////// - -#include "pandadx8.h" - -#include "config_dxgsg8.h" -#include "wdxGraphicsPipe8.h" - -// By including checkPandaVersion.h, we guarantee that runtime -// attempts to load libpandadx8.dll will fail if they -// inadvertently link with the wrong version of libdtool.dll. - -#include "checkPandaVersion.h" - -//////////////////////////////////////////////////////////////////// -// Function: init_libpandadx -// Description: Initializes the library. This must be called at -// least once before any of the functions or classes in -// this library can be used. Normally it will be -// called by the static initializers and need not be -// called explicitly, but special cases exist. -//////////////////////////////////////////////////////////////////// -void -init_libpandadx8() { - init_libdxgsg8(); -} - -//////////////////////////////////////////////////////////////////// -// Function: get_pipe_type_pandadx8 -// Description: Returns the TypeHandle index of the recommended -// graphics pipe type defined by this module. -//////////////////////////////////////////////////////////////////// -int -get_pipe_type_pandadx8() { - return wdxGraphicsPipe8::get_class_type().get_index(); -} diff --git a/panda/metalibs/pandadx8/pandadx8.h b/panda/metalibs/pandadx8/pandadx8.h deleted file mode 100644 index 6c6fc75306..0000000000 --- a/panda/metalibs/pandadx8/pandadx8.h +++ /dev/null @@ -1,14 +0,0 @@ -// Filename: pandadx.h -// Created by: drose (2Jan01) -// -//////////////////////////////////////////////////////////////////// - -#ifndef PANDADX8_H -#define PANDADX8_H - -#include "pandabase.h" - -EXPCL_PANDADX void init_libpandadx8(); -extern "C" EXPCL_PANDADX int get_pipe_type_pandadx8(); - -#endif diff --git a/panda/src/configfiles/panda.prc.pp b/panda/src/configfiles/panda.prc.pp index 6cf74d0407..1a7f6099fa 100644 --- a/panda/src/configfiles/panda.prc.pp +++ b/panda/src/configfiles/panda.prc.pp @@ -27,9 +27,6 @@ aux-display pandadx9 #if $[HAVE_GL] aux-display pandagl #endif -#if $[HAVE_DX8] -aux-display pandadx8 -#endif #if $[HAVE_TINYDISPLAY] aux-display p3tinydisplay #endif diff --git a/panda/src/dxgsg8/Sources.pp b/panda/src/dxgsg8/Sources.pp deleted file mode 100644 index 515ad29c6f..0000000000 --- a/panda/src/dxgsg8/Sources.pp +++ /dev/null @@ -1,42 +0,0 @@ -#define BUILD_DIRECTORY $[HAVE_DX8] - -#define OTHER_LIBS \ - p3interrogatedb:c p3dconfig:c p3dtoolconfig:m \ - p3dtoolutil:c p3dtoolbase:c p3dtool:m - -#define USE_PACKAGES dx8 - -#begin lib_target - #define TARGET p3dxgsg8 - #define LOCAL_LIBS \ - p3gsgbase p3gobj p3display p3windisplay \ - p3putil p3linmath p3mathutil p3pnmimage p3event - - #define COMBINED_SOURCES $[TARGET]_composite1.cxx - - // build dxGraphicsStateGuardian separately since its so big - - #define SOURCES \ - dxGraphicsStateGuardian8.cxx \ - dxGraphicsDevice8.h \ - wdxGraphicsPipe8.I wdxGraphicsPipe8.h \ - wdxGraphicsWindow8.I wdxGraphicsWindow8.h \ - dxgsg8base.h config_dxgsg8.h dxGraphicsStateGuardian8.I dxGraphicsStateGuardian8.h \ - dxVertexBufferContext8.h dxVertexBufferContext8.I \ - dxIndexBufferContext8.h dxIndexBufferContext8.I \ - dxTextureContext8.h dxTextureContext8.I \ - dxGeomMunger8.h dxGeomMunger8.I \ - dxGraphicsDevice8.h - - #define INCLUDED_SOURCES \ - config_dxgsg8.cxx \ - dxVertexBufferContext8.cxx \ - dxIndexBufferContext8.cxx \ - dxTextureContext8.cxx \ - dxGeomMunger8.cxx \ - dxGraphicsDevice8.cxx \ - wdxGraphicsPipe8.cxx \ - wdxGraphicsWindow8.cxx \ - wdxGraphicsBuffer8.cxx - -#end lib_target diff --git a/panda/src/dxgsg8/config_dxgsg8.cxx b/panda/src/dxgsg8/config_dxgsg8.cxx deleted file mode 100644 index 8f93af0a0c..0000000000 --- a/panda/src/dxgsg8/config_dxgsg8.cxx +++ /dev/null @@ -1,155 +0,0 @@ -// Filename: config_dxgsg8.cxx -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "config_dxgsg8.h" -#include "dxGraphicsStateGuardian8.h" -#include "dxTextureContext8.h" -#include "dxVertexBufferContext8.h" -#include "dxIndexBufferContext8.h" -#include "dxGeomMunger8.h" -#include "graphicsPipeSelection.h" -#include "wdxGraphicsWindow8.h" -#include "wdxGraphicsPipe8.h" -#include "pandaSystem.h" - -#include "dconfig.h" - -Configure(config_dxgsg8); -NotifyCategoryDef(dxgsg8, ":display:gsg"); -NotifyCategoryDef(wdxdisplay8, "display"); - -// Configure this variable true to cause the DXGSG to show each -// transform space it renders by drawing a little unit axis. This -// cannot be enabled when the player is compiled in NDEBUG mode. -ConfigVariableBool dx_show_transforms -("dx-show-transforms", false); - -// Set Level of MultiSampling to be used, if HW supports it. Valid values are 2-16. -ConfigVariableInt dx_multisample_antialiasing_level -("dx-multisample-antialiasing-level", 0); - -// if true, if card only supports per-vertex fog, it will be treated as no-HW fog capability -ConfigVariableBool dx_no_vertex_fog -("dx-no-vertex-fog", false); - -// if true, overwrite cursor bitmap tip with "D3D" to distinguish it from GDI cursor -ConfigVariableBool dx_show_cursor_watermark -("dx-show-cursor-watermark", -#ifdef _DEBUG - true -#else - false -#endif - ); - -// if true, triangle filter will be used to generate mipmap levels instead of default box filter -ConfigVariableBool dx_use_triangle_mipgen_filter -("dx-use-triangle-mipgen-filter", false); - -ConfigVariableBool dx_broken_max_index -("dx-broken-max-index", false, - PRC_DESC("Configure this true if you have a buggy graphics driver that " - "doesn't correctly implement the third parameter, NumVertices, " - "of DrawIndexedPrimitive(). In particular, the NVIDIA Quadro " - "driver version 6.14.10.7184 seems to treat this as a maximum " - "vertex index, rather than a delta between the maximum and " - "minimum vertex index. Turn this on if you are seeing stray " - "triangles, or you are not seeing all of your triangles. Enabling " - "this should work around this bug, at the cost of some additional " - "rendering overhead on the GPU.")); - -#ifndef NDEBUG -// debugging flag -// values are same as D3DCULL enumtype, 0 - no force, 1 - force none, 2 - force CW, 3 - force CCW -ConfigVariableInt dx_force_backface_culling -("dx-force-backface-culling", 0); -#endif - -ConfigVariableBool dx_mipmap_everything -("dx-mipmap-everything", false); -ConfigVariableBool dx_ignore_mipmaps -("dx-ignore-mipmaps", false); - -// if this is set, more accurate but more expensive fog computations are performed -ConfigVariableBool dx_use_rangebased_fog -("dx-use-rangebased-fog", false); -ConfigVariableBool dx_no_dithering -("dx-no-dithering", false); -ConfigVariableBool dx_force_16bpp_zbuffer -("dx-force-16bpp-zbuffer", false); -ConfigVariableBool dx_do_vidmemsize_check -("do-vidmemsize-check", true); -// Setting this true theoretically hinders render performance, because -// it forces the FPU to go through some extra work to clean itself up -// after rendering a frame, but the performance cost seems to be -// small. On the other hand, setting it false can force the -// application to run in single-precision arithmetic mode, even if -// it believes it is using double-precision variables. -ConfigVariableBool dx_preserve_fpu_state -("dx-preserve-fpu-state", true); - -ConfigVariableInt dx_preferred_device_id -("dx-preferred-device-id", -1); - -#ifdef _DEBUG -ConfigVariableDouble dx_global_miplevel_bias -("dx-global-miplevel-bias", 0.0); -ConfigVariableBool dx_debug_view_mipmaps -("dx-debug-view-mipmaps", false); -#endif - -ConfigVariableBool dx_force_anisotropic_filtering -("dx-force-anisotropic-filtering", false); - -// set 'retained-mode #t' and this to have prepare_geom concatenate all tristrips within a geom -// together using degenerate tris -ConfigVariableBool link_tristrips -("link-tristrips", false); - -ConfigureFn(config_dxgsg8) { - init_libdxgsg8(); -} - -//////////////////////////////////////////////////////////////////// -// Function: init_libdxgsg -// Description: Initializes the library. This must be called at -// least once before any of the functions or classes in -// this library can be used. Normally it will be -// called by the static initializers and need not be -// called explicitly, but special cases exist. -//////////////////////////////////////////////////////////////////// -void -init_libdxgsg8() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - DXGraphicsStateGuardian8::init_type(); - DXTextureContext8::init_type(); - DXVertexBufferContext8::init_type(); - DXIndexBufferContext8::init_type(); - DXGeomMunger8::init_type(); - - wdxGraphicsPipe8::init_type(); - wdxGraphicsWindow8::init_type(); - - GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); - selection->add_pipe_type(wdxGraphicsPipe8::get_class_type(), - wdxGraphicsPipe8::pipe_constructor); - - PandaSystem *ps = PandaSystem::get_global_ptr(); - ps->add_system("DirectX8"); -} diff --git a/panda/src/dxgsg8/config_dxgsg8.h b/panda/src/dxgsg8/config_dxgsg8.h deleted file mode 100644 index 8980c1c75b..0000000000 --- a/panda/src/dxgsg8/config_dxgsg8.h +++ /dev/null @@ -1,60 +0,0 @@ -// Filename: config_dxgsg.h -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef CONFIG_DXGSG8_H -#define CONFIG_DXGSG8_H - -#include "pandabase.h" -#include "notifyCategoryProxy.h" -#include "dxgsg8base.h" -#include "configVariableBool.h" -#include "configVariableInt.h" -#include "configVariableDouble.h" - -NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX); -NotifyCategoryDecl(wdxdisplay8, EXPCL_PANDADX, EXPTP_PANDADX); - -extern ConfigVariableBool dx_no_vertex_fog; -extern ConfigVariableBool dx_show_cursor_watermark; -extern ConfigVariableBool dx_full_screen_antialiasing; -extern ConfigVariableBool dx_use_rangebased_fog; -extern ConfigVariableBool link_tristrips; -extern ConfigVariableInt dx_multisample_antialiasing_level; -extern ConfigVariableBool dx_use_triangle_mipgen_filter; -extern ConfigVariableBool dx_broken_max_index; - - -// debug flags we might want to use in full optimized build -extern ConfigVariableBool dx_ignore_mipmaps; -extern ConfigVariableBool dx_mipmap_everything; -extern ConfigVariableBool dx_show_transforms; -extern ConfigVariableBool dx_no_dithering; -extern ConfigVariableBool dx_force_anisotropic_filtering; -extern ConfigVariableBool dx_force_16bpp_zbuffer; -extern ConfigVariableBool dx_do_vidmemsize_check; -extern ConfigVariableBool dx_preserve_fpu_state; -extern ConfigVariableInt dx_preferred_device_id; - -#ifndef NDEBUG -extern ConfigVariableInt dx_force_backface_culling; -#endif - -#ifdef _DEBUG -extern ConfigVariableDouble dx_global_miplevel_bias; -extern ConfigVariableBool dx_debug_view_mipmaps; -#endif - -extern EXPCL_PANDADX void init_libdxgsg8(); - -#endif diff --git a/panda/src/dxgsg8/dxGeomMunger8.I b/panda/src/dxgsg8/dxGeomMunger8.I deleted file mode 100644 index b0a3911417..0000000000 --- a/panda/src/dxgsg8/dxGeomMunger8.I +++ /dev/null @@ -1,40 +0,0 @@ -// Filename: dxGeomMunger8.I -// Created by: drose (11Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: DXGeomMunger8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE DXGeomMunger8:: -DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state) : - StandardMunger(gsg, state, 1, NT_packed_dabc, C_color), - _texture(DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()))), - _tex_gen(DCAST(TexGenAttrib, state->get_attrib(TexGenAttrib::get_class_slot()))) -{ - _filtered_texture = (TextureAttrib *)NULL; - _reffed_filtered_texture = false; - if (_texture != (TextureAttrib *)NULL) { - _filtered_texture = _texture->filter_to_max(gsg->get_max_texture_stages()); - if (_filtered_texture != _texture) { - _filtered_texture->ref(); - _reffed_filtered_texture = true; - } - } - // Set a callback to unregister ourselves when either the Texture or - // the TexGen object gets deleted. - _texture.set_callback(this); - _tex_gen.set_callback(this); -} diff --git a/panda/src/dxgsg8/dxGeomMunger8.cxx b/panda/src/dxgsg8/dxGeomMunger8.cxx deleted file mode 100644 index 4037a34865..0000000000 --- a/panda/src/dxgsg8/dxGeomMunger8.cxx +++ /dev/null @@ -1,322 +0,0 @@ -// Filename: dxGeomMunger8.cxx -// Created by: drose (11Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "dxGeomMunger8.h" -#include "geomVertexReader.h" -#include "geomVertexWriter.h" -#include "config_dxgsg8.h" - -GeomMunger *DXGeomMunger8::_deleted_chain = NULL; -TypeHandle DXGeomMunger8::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: DXGeomMunger8::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -DXGeomMunger8:: -~DXGeomMunger8() { - if (_reffed_filtered_texture) { - unref_delete(_filtered_texture); - _reffed_filtered_texture = false; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGeomMunger8::wp_callback -// Access: Public, Virtual -// Description: This callback is set to be made whenever the -// associated _texture or _tex_gen attributes are -// destructed, in which case the GeomMunger is invalid -// and should no longer be used. -//////////////////////////////////////////////////////////////////// -void DXGeomMunger8:: -wp_callback(void *) { - unregister_myself(); - - if (_reffed_filtered_texture) { - unref_delete(_filtered_texture); - _reffed_filtered_texture = false; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGeomMunger8::munge_format_impl -// Access: Protected, Virtual -// Description: Given a source GeomVertexFormat, converts it if -// necessary to the appropriate format for rendering. -//////////////////////////////////////////////////////////////////// -CPT(GeomVertexFormat) DXGeomMunger8:: -munge_format_impl(const GeomVertexFormat *orig, - const GeomVertexAnimationSpec &animation) { - if (dxgsg8_cat.is_debug()) { - if (animation.get_animation_type() != AT_none) { - dxgsg8_cat.debug() - << "preparing animation type " << animation << " for " << *orig - << "\n"; - } - } - // We have to build a completely new format that includes only the - // appropriate components, in the appropriate order, in just one - // array. - PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig); - new_format->set_animation(animation); - PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat; - - const GeomVertexColumn *vertex_type = orig->get_vertex_column(); - const GeomVertexColumn *normal_type = orig->get_normal_column(); - const GeomVertexColumn *color_type = orig->get_color_column(); - - if (vertex_type != (const GeomVertexColumn *)NULL) { - new_array_format->add_column - (InternalName::get_vertex(), 3, NT_float32, - vertex_type->get_contents()); - new_format->remove_column(vertex_type->get_name()); - - } else { - // If we don't have a vertex type, not much we can do. - return orig; - } - - if (animation.get_animation_type() == AT_hardware && - animation.get_num_transforms() > 0) { - if (animation.get_num_transforms() > 1) { - // If we want hardware animation, we need to reserve space for the - // blend weights. - new_array_format->add_column - (InternalName::get_transform_weight(), animation.get_num_transforms() - 1, - NT_float32, C_other); - } - - if (animation.get_indexed_transforms()) { - // Also, if we'll be indexing into the transform table, reserve - // space for the index. - new_array_format->add_column - (InternalName::get_transform_index(), 1, - NT_packed_dcba, C_index); - } - - // Make sure the old weights and indices are removed, just in - // case. - new_format->remove_column(InternalName::get_transform_weight()); - new_format->remove_column(InternalName::get_transform_index()); - - // And we don't need the transform_blend table any more. - new_format->remove_column(InternalName::get_transform_blend()); - } - - if (normal_type != (const GeomVertexColumn *)NULL) { - new_array_format->add_column - (InternalName::get_normal(), 3, NT_float32, C_vector); - new_format->remove_column(normal_type->get_name()); - } - - if (color_type != (const GeomVertexColumn *)NULL) { - new_array_format->add_column - (InternalName::get_color(), 1, NT_packed_dabc, C_color); - new_format->remove_column(color_type->get_name()); - } - - // To support multitexture, we will need to add all of the relevant - // texcoord types, and in the order specified by the TextureAttrib. - - // Now set up each of the active texture coordinate stages--or at - // least those for which we're not generating texture coordinates - // automatically. - - if (_filtered_texture != (TextureAttrib *)NULL) { - int num_stages = _filtered_texture->get_num_on_ff_stages(); - vector_int ff_tc_index(num_stages, 0); - - // Be sure we add the texture coordinates in the right order, as - // specified by the attrib. To ensure this, we first walk through - // the stages of the attrib and get the index numbers in the - // appropriate order. - int si, tc_index; - int max_tc_index = -1; - for (si = 0; si < num_stages; ++si) { - int tc_index = _filtered_texture->get_ff_tc_index(si); - nassertr(tc_index < num_stages, orig); - ff_tc_index[tc_index] = si; - max_tc_index = max(tc_index, max_tc_index); - } - - // Now walk through the texture coordinates in the order they will - // appear on the final geometry. For each one, get the texture - // coordinate name from the associated stage. - for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) { - si = ff_tc_index[tc_index]; - TextureStage *stage = _filtered_texture->get_on_ff_stage(si); - InternalName *name = stage->get_texcoord_name(); - - const GeomVertexColumn *texcoord_type = orig->get_column(name); - - if (texcoord_type != (const GeomVertexColumn *)NULL) { - new_array_format->add_column - (name, texcoord_type->get_num_values(), NT_float32, C_texcoord); - } else { - // We have to add something as a placeholder, even if the - // texture coordinates aren't defined. - new_array_format->add_column(name, 2, NT_float32, C_texcoord); - } - new_format->remove_column(name); - } - } - - // Make sure the FVF-style array we just built up is first in the - // list. - new_format->insert_array(0, new_array_format); - - return GeomVertexFormat::register_format(new_format); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGeomMunger8::premunge_format_impl -// Access: Protected, Virtual -// Description: Given a source GeomVertexFormat, converts it if -// necessary to the appropriate format for rendering. -//////////////////////////////////////////////////////////////////// -CPT(GeomVertexFormat) DXGeomMunger8:: -premunge_format_impl(const GeomVertexFormat *orig) { - // We have to build a completely new format that includes only the - // appropriate components, in the appropriate order, in just one - // array. - PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig); - PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat; - - const GeomVertexColumn *vertex_type = orig->get_vertex_column(); - const GeomVertexColumn *normal_type = orig->get_normal_column(); - const GeomVertexColumn *color_type = orig->get_color_column(); - - if (vertex_type != (const GeomVertexColumn *)NULL) { - new_array_format->add_column - (InternalName::get_vertex(), 3, NT_float32, - vertex_type->get_contents()); - new_format->remove_column(vertex_type->get_name()); - - } else { - // If we don't have a vertex type, not much we can do. - return orig; - } - - if (normal_type != (const GeomVertexColumn *)NULL) { - new_array_format->add_column - (InternalName::get_normal(), 3, NT_float32, C_vector); - new_format->remove_column(normal_type->get_name()); - } - - if (color_type != (const GeomVertexColumn *)NULL) { - new_array_format->add_column - (InternalName::get_color(), 1, NT_packed_dabc, C_color); - new_format->remove_column(color_type->get_name()); - } - - // To support multitexture, we will need to add all of the relevant - // texcoord types, and in the order specified by the TextureAttrib. - - // Now set up each of the active texture coordinate stages--or at - // least those for which we're not generating texture coordinates - // automatically. - - if (_filtered_texture != (TextureAttrib *)NULL) { - int num_stages = _filtered_texture->get_num_on_ff_stages(); - vector_int ff_tc_index(num_stages, 0); - - // Be sure we add the texture coordinates in the right order, as - // specified by the attrib. To ensure this, we first walk through - // the stages of the attrib and get the index numbers in the - // appropriate order. - int si, tc_index; - int max_tc_index = -1; - for (si = 0; si < num_stages; ++si) { - int tc_index = _filtered_texture->get_ff_tc_index(si); - nassertr(tc_index < num_stages, orig); - ff_tc_index[tc_index] = si; - max_tc_index = max(tc_index, max_tc_index); - } - - // Now walk through the texture coordinates in the order they will - // appear on the final geometry. For each one, get the texture - // coordinate name from the associated stage. - for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) { - si = ff_tc_index[tc_index]; - TextureStage *stage = _filtered_texture->get_on_ff_stage(si); - InternalName *name = stage->get_texcoord_name(); - - const GeomVertexColumn *texcoord_type = orig->get_column(name); - - if (texcoord_type != (const GeomVertexColumn *)NULL) { - new_array_format->add_column - (name, texcoord_type->get_num_values(), NT_float32, C_texcoord); - } else { - // We have to add something as a placeholder, even if the - // texture coordinates aren't defined. - new_array_format->add_column(name, 2, NT_float32, C_texcoord); - } - new_format->remove_column(name); - } - } - - // Make sure the FVF-style array we just built up is first in the - // list. - new_format->insert_array(0, new_array_format); - - return GeomVertexFormat::register_format(new_format); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGeomMunger8::compare_to_impl -// Access: Protected, Virtual -// Description: Called to compare two GeomMungers who are known to be -// of the same type, for an apples-to-apples comparison. -// This will never be called on two pointers of a -// different type. -//////////////////////////////////////////////////////////////////// -int DXGeomMunger8:: -compare_to_impl(const GeomMunger *other) const { - const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other); - if (_filtered_texture != om->_filtered_texture) { - return _filtered_texture < om->_filtered_texture ? -1 : 1; - } - if (_tex_gen != om->_tex_gen) { - return _tex_gen < om->_tex_gen ? -1 : 1; - } - - return StandardMunger::compare_to_impl(other); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGeomMunger8::geom_compare_to_impl -// Access: Protected, Virtual -// Description: Called to compare two GeomMungers who are known to be -// of the same type, for an apples-to-apples comparison. -// This will never be called on two pointers of a -// different type. -//////////////////////////////////////////////////////////////////// -int DXGeomMunger8:: -geom_compare_to_impl(const GeomMunger *other) const { - // Unlike GLGeomMunger, we do consider _filtered_texture and - // _tex_gen important for this purpose, since they control the - // number and order of texture coordinates we might put into the - // FVF. - const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other); - if (_filtered_texture != om->_filtered_texture) { - return _filtered_texture < om->_filtered_texture ? -1 : 1; - } - if (_tex_gen != om->_tex_gen) { - return _tex_gen < om->_tex_gen ? -1 : 1; - } - - return StandardMunger::geom_compare_to_impl(other); -} diff --git a/panda/src/dxgsg8/dxGeomMunger8.h b/panda/src/dxgsg8/dxGeomMunger8.h deleted file mode 100644 index f2edd56eac..0000000000 --- a/panda/src/dxgsg8/dxGeomMunger8.h +++ /dev/null @@ -1,82 +0,0 @@ -// Filename: dxGeomMunger8.h -// Created by: drose (11Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef DXGEOMMUNGER8_H -#define DXGEOMMUNGER8_H - -#include "pandabase.h" -#include "standardMunger.h" -#include "graphicsStateGuardian.h" -#include "weakPointerTo.h" -#include "weakPointerCallback.h" - -//////////////////////////////////////////////////////////////////// -// Class : DXGeomMunger8 -// Description : This specialization on GeomMunger finesses vertices -// for DirectX rendering. In particular, it makes sure -// colors are stored in DirectX's packed_argb format, -// and that all relevant components are packed into a -// single array, in the correct order. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXGeomMunger8 : public StandardMunger, public WeakPointerCallback { -public: - INLINE DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state); - virtual ~DXGeomMunger8(); - ALLOC_DELETED_CHAIN(DXGeomMunger8); - - virtual void wp_callback(void *); - -protected: - virtual CPT(GeomVertexFormat) munge_format_impl(const GeomVertexFormat *orig, - const GeomVertexAnimationSpec &animation); - virtual CPT(GeomVertexFormat) premunge_format_impl(const GeomVertexFormat *orig); - - virtual int compare_to_impl(const GeomMunger *other) const; - virtual int geom_compare_to_impl(const GeomMunger *other) const; - -private: - WCPT(TextureAttrib) _texture; - WCPT(TexGenAttrib) _tex_gen; - - // This pointer is derived from _texture, above. In the case that - // it is a different pointer, we maintain its reference count - // explicitly. If it is the same pointer, we don't reference count - // it at all (so we won't hold on to the reference count - // unnecessarily). - const TextureAttrib *_filtered_texture; - bool _reffed_filtered_texture; - - static GeomMunger *_deleted_chain; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - StandardMunger::init_type(); - register_type(_type_handle, "DXGeomMunger8", - StandardMunger::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 "dxGeomMunger8.I" - -#endif diff --git a/panda/src/dxgsg8/dxGraphicsDevice8.cxx b/panda/src/dxgsg8/dxGraphicsDevice8.cxx deleted file mode 100644 index c86b4c338e..0000000000 --- a/panda/src/dxgsg8/dxGraphicsDevice8.cxx +++ /dev/null @@ -1,42 +0,0 @@ -// Filename: dxGraphicsDevice.cxx -// Created by: masad (22Jul03) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "config_dxgsg8.h" -#include "dxGraphicsDevice8.h" - - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsDevice8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXGraphicsDevice8:: -DXGraphicsDevice8(wdxGraphicsPipe8 *pipe) : - GraphicsDevice(pipe) { - - ZeroMemory(&_Scrn,sizeof(_Scrn)); - _d3d_device = NULL; - _swap_chain = NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsDevice8::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXGraphicsDevice8:: -~DXGraphicsDevice8() { - -} - diff --git a/panda/src/dxgsg8/dxGraphicsDevice8.h b/panda/src/dxgsg8/dxGraphicsDevice8.h deleted file mode 100755 index dd6af7d44a..0000000000 --- a/panda/src/dxgsg8/dxGraphicsDevice8.h +++ /dev/null @@ -1,51 +0,0 @@ -// Filename: dxGraphicsDevice.h -// Created by: masad (22Jul03) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef DXGRAPHICSDEVICE_H -#define DXGRAPHICSDEVICE_H - -//#define GSG_VERBOSE 1 - -#include "dxgsg8base.h" -#include "graphicsDevice.h" -#include "wdxGraphicsPipe8.h" - - -//////////////////////////////////////////////////////////////////// -// Class : DXGraphicsDevice8 -// Description : A GraphicsDevice necessary for multi-window rendering -// in DX. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXGraphicsDevice8 : public GraphicsDevice { - friend class wdxGraphicsPipe8; - -public: - DXGraphicsDevice8(wdxGraphicsPipe8 *pipe); - ~DXGraphicsDevice8(); - - DXScreenData _Scrn; - LPDIRECT3DDEVICE8 _d3d_device; // same as Scrn._d3d_device, cached for spd - IDirect3DSwapChain8 *_swap_chain; - -#if 0 -protected: - static TypeHandle get_class_type(); - static void init_type(); - virtual TypeHandle get_type() const; - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} -#endif -}; - -#endif - diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.I b/panda/src/dxgsg8/dxGraphicsStateGuardian8.I deleted file mode 100644 index 58302f94b4..0000000000 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.I +++ /dev/null @@ -1,159 +0,0 @@ -// Filename: dxGraphicsStateGuardian8.I -// Created by: mike (02Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::LColor_to_D3DCOLOR -// Access: Public, Static -// Description: Converts Panda's floating-point LColor structure to -// DirectX's D3DCOLOR packed structure. -//////////////////////////////////////////////////////////////////// -INLINE DWORD DXGraphicsStateGuardian8:: -LColor_to_D3DCOLOR(const LColor &cLColor) { -// MS VC defines _M_IX86 for x86. gcc should define _X86_ -#if (defined(_M_IX86) || defined(_X86_)) && !defined(STDFLOAT_DOUBLE) - DWORD d3dcolor, tempcolorval=255; - - // note the default FPU rounding mode will give 255*0.5f=0x80, not 0x7F as VC would force it to by resetting rounding mode - // don't think this makes much difference - - __asm { - push ebx ; want to save this in case this fn is inlined - push ecx - mov ecx, cLColor - fild tempcolorval - fld DWORD PTR [ecx] - fmul ST(0), ST(1) - fistp tempcolorval ; no way to store directly to int register - mov eax, tempcolorval - shl eax, 16 - - fld DWORD PTR [ecx+4] ;grn - fmul ST(0), ST(1) - fistp tempcolorval - mov ebx, tempcolorval - shl ebx, 8 - or eax, ebx - - fld DWORD PTR [ecx+8] ;blue - fmul ST(0), ST(1) - fistp tempcolorval - or eax, tempcolorval - - fld DWORD PTR [ecx+12] ;alpha - fmul ST(0), ST(1) - fistp tempcolorval - ; simulate pop 255.0 off FP stack w/o store, mark top as empty and increment stk ptr - ffree ST(0) - fincstp - mov ebx, tempcolorval - shl ebx, 24 - or eax, ebx - mov d3dcolor, eax - pop ecx - pop ebx - } - - // dxgsg8_cat.debug() << (void*)d3dcolor << endl; - return d3dcolor; -#else //!_X86_ - return MY_D3DRGBA(cLColor[0], cLColor[1], cLColor[2], cLColor[3]); -#endif //!_X86_ -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_texture_wrap_mode -// Access: Protected, Static -// Description: Maps from the Texture's internal wrap mode symbols to -// GL's. -//////////////////////////////////////////////////////////////////// -INLINE D3DTEXTUREADDRESS DXGraphicsStateGuardian8:: -get_texture_wrap_mode(SamplerState::WrapMode wm) { - switch (wm) { - case SamplerState::WM_clamp: - return D3DTADDRESS_CLAMP; - case SamplerState::WM_repeat: - return D3DTADDRESS_WRAP; - case SamplerState::WM_mirror: - return D3DTADDRESS_MIRROR; - case SamplerState::WM_mirror_once: - return D3DTADDRESS_MIRRORONCE; - case SamplerState::WM_border_color: - return D3DTADDRESS_BORDER; - } - dxgsg8_cat.error() << "Invalid Texture::Mode value" << endl; - return D3DTADDRESS_WRAP; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_fog_mode_type -// Access: Protected, Static -// Description: Maps from the fog types to gl version -//////////////////////////////////////////////////////////////////// -INLINE D3DFOGMODE DXGraphicsStateGuardian8:: -get_fog_mode_type(Fog::Mode m) { - switch (m) { - case Fog::M_linear: - return D3DFOG_LINEAR; - case Fog::M_exponential: - return D3DFOG_EXP; - case Fog::M_exponential_squared: - return D3DFOG_EXP2; - } - dxgsg8_cat.error() << "Invalid Fog::Mode value" << endl; - return D3DFOG_EXP; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_tex_mat_sym -// Access: Protected, Static -// Description: Returns the nth D3DTS_TEXTURE(n) constant. -//////////////////////////////////////////////////////////////////// -INLINE D3DTRANSFORMSTATETYPE DXGraphicsStateGuardian8:: -get_tex_mat_sym(int stage_index) { - return (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage_index); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_safe_buffer_start -// Access: Protected, Static -// Description: Returns the address of a 64K buffer that is allocated -// at the beginning of a 64K block. -//////////////////////////////////////////////////////////////////// -INLINE unsigned char *DXGraphicsStateGuardian8:: -get_safe_buffer_start() { - if (_temp_buffer == NULL) { - // Guarantee we get a buffer of size 0x10000 bytes that begins - // on an even multiple of 0x10000. We do this by allocating - // double the required buffer, and then pointing to the first - // multiple of 0x10000 within that buffer. - _temp_buffer = new unsigned char[0x1ffff]; - _safe_buffer_start = (unsigned char *)(((long)_temp_buffer + 0xffff) & ~0xffff); - } - - return _safe_buffer_start; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_supports_render_texture -// Access: Published -// Description: Returns true if this particular GSG can render -// from a wdxGraphicsBuffer8 directly into a texture, or -// false if it must always copy-to-texture at the end of -// each frame to achieve this effect. -//////////////////////////////////////////////////////////////////// -INLINE bool DXGraphicsStateGuardian8:: -get_supports_render_texture() const { - return _supports_render_texture; -} diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx deleted file mode 100644 index 9d87cfa494..0000000000 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ /dev/null @@ -1,4674 +0,0 @@ -// Filename: dxGraphicsStateGuardian8.cxx -// Created by: mike (02Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "dxGraphicsStateGuardian8.h" -#include "config_dxgsg8.h" -#include "displayRegion.h" -#include "renderBuffer.h" -#include "geom.h" -#include "graphicsWindow.h" -#include "graphicsEngine.h" -#include "lens.h" -#include "ambientLight.h" -#include "directionalLight.h" -#include "pointLight.h" -#include "spotlight.h" -#include "textureAttrib.h" -#include "texGenAttrib.h" -#include "shadeModelAttrib.h" -#include "cullFaceAttrib.h" -#include "transparencyAttrib.h" -#include "alphaTestAttrib.h" -#include "depthTestAttrib.h" -#include "depthWriteAttrib.h" -#include "colorWriteAttrib.h" -#include "texMatrixAttrib.h" -#include "materialAttrib.h" -#include "renderModeAttrib.h" -#include "rescaleNormalAttrib.h" -#include "fogAttrib.h" -#include "depthOffsetAttrib.h" -#include "lightAttrib.h" -#include "stencilAttrib.h" -#include "scissorAttrib.h" -#include "clipPlaneAttrib.h" -#include "fog.h" -#include "throw_event.h" -#include "geomVertexFormat.h" -#include "geomVertexData.h" -#include "geomTriangles.h" -#include "geomTristrips.h" -#include "geomTrifans.h" -#include "geomLines.h" -#include "geomLinestrips.h" -#include "geomPoints.h" -#include "geomVertexReader.h" -#include "dxGeomMunger8.h" -#include "config_gobj.h" -#include "dxVertexBufferContext8.h" -#include "dxIndexBufferContext8.h" -#include "pStatTimer.h" -#include "pStatCollector.h" -#include "dxgsg8base.h" -#include "wdxGraphicsBuffer8.h" - -#include - -TypeHandle DXGraphicsStateGuardian8::_type_handle; - -D3DMATRIX DXGraphicsStateGuardian8::_d3d_ident_mat; - -unsigned char *DXGraphicsStateGuardian8::_temp_buffer = NULL; -unsigned char *DXGraphicsStateGuardian8::_safe_buffer_start = NULL; - -#define __D3DLIGHT_RANGE_MAX ((PN_stdfloat)sqrt(FLT_MAX)) //for some reason this is missing in dx8 hdrs - -#define MY_D3DRGBA(r, g, b, a) ((D3DCOLOR) D3DCOLOR_COLORVALUE(r, g, b, a)) - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXGraphicsStateGuardian8:: -DXGraphicsStateGuardian8(GraphicsEngine *engine, GraphicsPipe *pipe) : - GraphicsStateGuardian(CS_yup_left, engine, pipe) -{ - // Assume that we will get a hardware-accelerated context, unless - // the window tells us otherwise. - _is_hardware = true; - - _screen = NULL; - _d3d_device = NULL; - - _dx_is_ready = false; - _vertex_blending_enabled = false; - _overlay_windows_supported = false; - _tex_stats_retrieval_impossible = false; - _supports_render_texture = false; - - _active_vbuffer = NULL; - _active_ibuffer = NULL; - - // This is a static member, but we initialize it here in the - // constructor anyway. It won't hurt if it gets repeatedly - // initalized. - ZeroMemory(&_d3d_ident_mat, sizeof(D3DMATRIX)); - _d3d_ident_mat._11 = _d3d_ident_mat._22 = _d3d_ident_mat._33 = _d3d_ident_mat._44 = 1.0f; - - _cur_read_pixel_buffer = RenderBuffer::T_front; - - // DirectX drivers seem to consistently invert the texture when - // they copy framebuffer-to-texture. Ok. - _copy_texture_inverted = true; - - // D3DRS_POINTSPRITEENABLE doesn't seem to support remapping the - // texture coordinates via a texture matrix, so we don't advertise - // GR_point_sprite_tex_matrix. - _supported_geom_rendering = - Geom::GR_point | Geom::GR_point_uniform_size | - Geom::GR_point_perspective | Geom::GR_point_sprite | - Geom::GR_indexed_other | - Geom::GR_triangle_strip | Geom::GR_triangle_fan | - Geom::GR_flat_first_vertex; - - _scissor_mat = TransformState::make_identity(); - - get_gamma_table(); - atexit (atexit_function); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXGraphicsStateGuardian8:: -~DXGraphicsStateGuardian8() { - if (IS_VALID_PTR(_d3d_device)) { - _d3d_device->SetTexture(0, NULL); // this frees reference to the old texture - } - free_nondx_resources(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::prepare_texture -// Access: Public, Virtual -// Description: Creates a new retained-mode representation of the -// given texture, and returns a newly-allocated -// TextureContext pointer to reference it. It is the -// responsibility of the calling function to later -// call release_texture() with this same pointer (which -// will also delete the pointer). -// -// This function should not be called directly to -// prepare a texture. Instead, call Texture::prepare(). -//////////////////////////////////////////////////////////////////// -TextureContext *DXGraphicsStateGuardian8:: -prepare_texture(Texture *tex, int view) { - DXTextureContext8 *dtc = new DXTextureContext8(_prepared_objects, tex, view); - - if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) { - dxgsg8_cat.error() - << *dtc->get_texture() << " is stored in an unsupported compressed format.\n"; - return NULL; - } - - return dtc; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::apply_texture -// Access: Public -// Description: Makes the texture the currently available texture for -// rendering on the ith stage. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -apply_texture(int i, TextureContext *tc, const SamplerState &sampler) { - if (tc == (TextureContext *)NULL) { - // The texture wasn't bound properly or something, so ensure - // texturing is disabled and just return. - _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE); - return; - } - if (!update_texture(tc, false)) { - // Couldn't get the texture image or something. - _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE); - return; - } - - tc->set_active(true); - - DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc); - Texture *tex = tc->get_texture(); - - SamplerState::WrapMode wrap_u, wrap_v, wrap_w; - wrap_u = sampler.get_wrap_u(); - wrap_v = sampler.get_wrap_v(); - wrap_w = sampler.get_wrap_w(); - - _d3d_device->SetTextureStageState(i, D3DTSS_ADDRESSU, get_texture_wrap_mode(wrap_u)); - _d3d_device->SetTextureStageState(i, D3DTSS_ADDRESSV, get_texture_wrap_mode(wrap_v)); - _d3d_device->SetTextureStageState(i, D3DTSS_ADDRESSW, get_texture_wrap_mode(wrap_w)); - - _d3d_device->SetTextureStageState(i, D3DTSS_BORDERCOLOR, - LColor_to_D3DCOLOR(sampler.get_border_color())); - - uint aniso_degree = sampler.get_effective_anisotropic_degree(); - SamplerState::FilterType ft = sampler.get_effective_magfilter(); - - if (aniso_degree >= 1) { - _d3d_device->SetTextureStageState(i, D3DTSS_MAXANISOTROPY, aniso_degree); - } - - D3DTEXTUREFILTERTYPE new_mag_filter; - if (aniso_degree <= 1) { - new_mag_filter = ((ft != SamplerState::FT_nearest) ? D3DTEXF_LINEAR : D3DTEXF_POINT); - } else { - new_mag_filter = D3DTEXF_ANISOTROPIC; - } - - _d3d_device->SetTextureStageState(i, D3DTSS_MAGFILTER, new_mag_filter); - - // map Panda composite min+mip filter types to d3d's separate min & mip filter types - D3DTEXTUREFILTERTYPE new_min_filter = get_d3d_min_type(sampler.get_effective_minfilter()); - D3DTEXTUREFILTERTYPE new_mip_filter = get_d3d_mip_type(sampler.get_effective_minfilter()); - - if (!tex->might_have_ram_image()) { - // If the texture is completely dynamic, don't try to issue - // mipmaps--pandadx doesn't support auto-generated mipmaps at this - // point. - new_mip_filter = D3DTEXF_NONE; - } - - // sanity check - if (!dtc->has_mipmaps()) { - new_mip_filter = D3DTEXF_NONE; - } - - if (aniso_degree >= 2) { - new_min_filter = D3DTEXF_ANISOTROPIC; - } - - _d3d_device->SetTextureStageState(i, D3DTSS_MINFILTER, new_min_filter); - _d3d_device->SetTextureStageState(i, D3DTSS_MIPFILTER, new_mip_filter); - - _d3d_device->SetTexture(i, dtc->get_d3d_texture()); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::update_texture -// Access: Public, Virtual -// Description: Ensures that the current Texture data is refreshed -// onto the GSG. This means updating the texture -// properties and/or re-uploading the texture image, if -// necessary. This should only be called within the -// draw thread. -// -// If force is true, this function will not return until -// the texture has been fully uploaded. If force is -// false, the function may choose to upload a simple -// version of the texture instead, if the texture is not -// fully resident (and if get_incomplete_render() is -// true). -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -update_texture(TextureContext *tc, bool force) { - DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc); - - // If the texture image has changed, or if its use of mipmaps has - // changed, we need to re-create the image. - - if (dtc->was_modified()) { - if (!upload_texture(dtc, force)) { - // Oops, we can't re-create the texture for some reason. - Texture *tex = tc->get_texture(); - dxgsg8_cat.error() - << "Unable to re-create texture " << *tex << endl; - cerr << "b\n"; - return false; - } - } - dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru); - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::upload_texture -// Access: Public -// Description: Creates a texture surface on the graphics card and -// fills it with its pixel data. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -upload_texture(DXTextureContext8 *dtc, bool force) { - Texture *tex = dtc->get_texture(); - if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) { - dxgsg8_cat.error() - << *tex << " is stored in an unsupported compressed format.\n"; - return false; - } - - dtc->delete_texture(); - dtc->update_data_size_bytes(0); - dtc->mark_unloaded(); - - if (_effective_incomplete_render && !force) { - bool has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image(); - if (!has_image && tex->might_have_ram_image() && - tex->has_simple_ram_image() && - !_loader.is_null()) { - // If we don't have the texture data right now, go get it, but in - // the meantime load a temporary simple image in its place. - async_reload_texture(dtc); - has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image(); - if (!has_image) { - if (dtc->was_simple_image_modified()) { - return dtc->create_simple_texture(*_screen); - } - return true; - } - } - } - - return dtc->create_texture(*_screen); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::release_texture -// Access: Public, Virtual -// Description: Frees the GL resources previously allocated for the -// texture. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -release_texture(TextureContext *tc) { - DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc); - delete dtc; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::extract_texture_data -// Access: Public, Virtual -// Description: This method should only be called by the -// GraphicsEngine. Do not call it directly; call -// GraphicsEngine::extract_texture_data() instead. -// -// This method will be called in the draw thread to -// download the texture memory's image into its -// ram_image value. It returns true on success, false -// otherwise. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -extract_texture_data(Texture *tex) { - TextureContext *tc = tex->prepare_now(0, get_prepared_objects(), this); - nassertr(tc != (TextureContext *)NULL, false); - DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc); - - return dtc->extract_texture_data(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::prepare_vertex_buffer -// Access: Public, Virtual -// Description: Creates a new retained-mode representation of the -// given data, and returns a newly-allocated -// VertexBufferContext pointer to reference it. It is the -// responsibility of the calling function to later -// call release_vertex_buffer() with this same pointer (which -// will also delete the pointer). -// -// This function should not be called directly to -// prepare a buffer. Instead, call Geom::prepare(). -//////////////////////////////////////////////////////////////////// -VertexBufferContext *DXGraphicsStateGuardian8:: -prepare_vertex_buffer(GeomVertexArrayData *data) { - DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(_prepared_objects, data); - return dvbc; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::apply_vertex_buffer -// Access: Public -// Description: Updates the vertex buffer with the current data, and -// makes it the current vertex buffer for rendering. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -apply_vertex_buffer(VertexBufferContext *vbc, - const GeomVertexArrayDataHandle *reader, bool force) { - DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc); - - if (dvbc->_vbuffer == NULL) { - // Attempt to create a new vertex buffer. - if (vertex_buffers && - reader->get_usage_hint() != Geom::UH_client) { - dvbc->create_vbuffer(*_screen, reader); - } - - if (dvbc->_vbuffer != NULL) { - if (!dvbc->upload_data(reader, force)) { - return false; - } - - dvbc->mark_loaded(reader); - - _d3d_device->SetStreamSource - (0, dvbc->_vbuffer, reader->get_array_format()->get_stride()); - _active_vbuffer = dvbc; - _active_ibuffer = NULL; - dvbc->set_active(true); - - } else { - _active_vbuffer = NULL; - } - - } else { - if (dvbc->was_modified(reader)) { - if (dvbc->changed_size(reader)) { - // We have to destroy the old vertex buffer and create a new - // one. - dvbc->create_vbuffer(*_screen, reader); - } - - if (!dvbc->upload_data(reader, force)) { - return false; - } - dvbc->mark_loaded(reader); - _active_vbuffer = NULL; - } - - if (_active_vbuffer != dvbc) { - _d3d_device->SetStreamSource - (0, dvbc->_vbuffer, reader->get_array_format()->get_stride()); - _active_vbuffer = dvbc; - _active_ibuffer = NULL; - dvbc->set_active(true); - } - } - dvbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru); - - HRESULT hr = _d3d_device->SetVertexShader(dvbc->_fvf); -#ifndef NDEBUG - if (FAILED(hr)) { - dxgsg8_cat.error() - << "SetVertexShader(0x" << (void*)dvbc->_fvf - << ") failed" << D3DERRORSTRING(hr); - } -#endif - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::release_vertex_buffer -// Access: Public, Virtual -// Description: 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 DXGraphicsStateGuardian8:: -release_vertex_buffer(VertexBufferContext *vbc) { - DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc); - delete dvbc; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::prepare_index_buffer -// Access: Public, Virtual -// Description: Creates a new retained-mode representation of the -// given data, and returns a newly-allocated -// IndexBufferContext pointer to reference it. It is the -// responsibility of the calling function to later call -// release_index_buffer() with this same pointer (which -// will also delete the pointer). -// -// This function should not be called directly to -// prepare a buffer. Instead, call Geom::prepare(). -//////////////////////////////////////////////////////////////////// -IndexBufferContext *DXGraphicsStateGuardian8:: -prepare_index_buffer(GeomPrimitive *data) { - DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(_prepared_objects, data); - return dibc; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::apply_index_buffer -// Access: Public -// Description: Updates the index buffer with the current data, and -// makes it the current index buffer for rendering. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -apply_index_buffer(IndexBufferContext *ibc, - const GeomPrimitivePipelineReader *reader, bool force) { - DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, ibc); - - if (dibc->_ibuffer == NULL) { - // Attempt to create a new index buffer. - dibc->create_ibuffer(*_screen, reader); - - if (dibc->_ibuffer != NULL) { - if (!dibc->upload_data(reader, force)) { - return false; - } - dibc->mark_loaded(reader); - - _d3d_device->SetIndices(dibc->_ibuffer, 0); - _active_ibuffer = dibc; - dibc->set_active(true); - - } else { - _d3d_device->SetIndices(NULL, 0); - _active_ibuffer = NULL; - } - - } else { - if (dibc->was_modified(reader)) { - if (dibc->changed_size(reader)) { - // We have to destroy the old index buffer and create a new - // one. - dibc->create_ibuffer(*_screen, reader); - } - - if (!dibc->upload_data(reader, force)) { - return false; - } - - dibc->mark_loaded(reader); - _active_ibuffer = NULL; - } - - if (_active_ibuffer != dibc) { - _d3d_device->SetIndices(dibc->_ibuffer, 0); - _active_ibuffer = dibc; - dibc->set_active(true); - } - } - dibc->enqueue_lru(&_prepared_objects->_graphics_memory_lru); - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::release_index_buffer -// Access: Public, Virtual -// Description: 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 DXGraphicsStateGuardian8:: -release_index_buffer(IndexBufferContext *ibc) { - DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, ibc); - delete dibc; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::make_geom_munger -// Access: Public, Virtual -// Description: Creates a new GeomMunger object to munge vertices -// appropriate to this GSG for the indicated state. -//////////////////////////////////////////////////////////////////// -PT(GeomMunger) DXGraphicsStateGuardian8:: -make_geom_munger(const RenderState *state, Thread *current_thread) { - PT(DXGeomMunger8) munger = new DXGeomMunger8(this, state); - return GeomMunger::register_munger(munger, current_thread); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_clear -// Access: Public, Virtual -// Description: Clears all of the indicated buffers to their assigned -// colors. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -clear(DrawableRegion *clearable) { - - DWORD main_flags = 0; - DWORD aux_flags = 0; - - D3DCOLOR color_clear_value = LColor_to_D3DCOLOR(clearable->get_clear_color()); - PN_stdfloat depth_clear_value = clearable->get_clear_depth(); - DWORD stencil_clear_value = (DWORD)(clearable->get_clear_stencil()); - - //set appropriate flags - if (clearable->get_clear_color_active()) { - main_flags |= D3DCLEAR_TARGET; - } - - if (clearable->get_clear_depth_active()) { - aux_flags |= D3DCLEAR_ZBUFFER; - nassertv(_screen->_presentation_params.EnableAutoDepthStencil); - } - - if (clearable->get_clear_stencil_active()) { - // clear only if there is a stencil buffer - if (_screen->_presentation_params.EnableAutoDepthStencil && - IS_STENCIL_FORMAT(_screen->_presentation_params.AutoDepthStencilFormat)) { - aux_flags |= D3DCLEAR_STENCIL; - } - } - - if ((main_flags | aux_flags) != 0) { - HRESULT hr = _d3d_device->Clear(0, NULL, main_flags | aux_flags, color_clear_value, - depth_clear_value, stencil_clear_value); - if (FAILED(hr) && main_flags == D3DCLEAR_TARGET && aux_flags != 0) { - // Maybe there's a problem with the one or more of the auxiliary - // buffers. - hr = _d3d_device->Clear(0, NULL, D3DCLEAR_TARGET, color_clear_value, - depth_clear_value, stencil_clear_value); - if (!FAILED(hr)) { - // Yep, it worked without them. That's a problem. Which buffer - // poses the problem? - if (clearable->get_clear_depth_active()) { - aux_flags |= D3DCLEAR_ZBUFFER; - HRESULT hr2 = _d3d_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color_clear_value, - depth_clear_value, stencil_clear_value); - if (FAILED(hr2)) { - dxgsg8_cat.error() - << "Unable to clear depth buffer; removing.\n"; - // This is really hacky code. - ((FrameBufferProperties *)_current_properties)->set_depth_bits(0); - } - } - if (clearable->get_clear_stencil_active()) { - aux_flags |= D3DCLEAR_STENCIL; - HRESULT hr2 = _d3d_device->Clear(0, NULL, D3DCLEAR_STENCIL, color_clear_value, - stencil_clear_value, stencil_clear_value); - if (FAILED(hr2)) { - dxgsg8_cat.error() - << "Unable to clear stencil buffer; removing.\n"; - // This is really hacky code. - ((FrameBufferProperties *)_current_properties)->set_stencil_bits(0); - _supports_stencil = false; - } - } - } - } - - if (FAILED(hr)) { - dxgsg8_cat.error() - << "clear_buffer failed: Clear returned " << D3DERRORSTRING(hr); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::prepare_display_region -// Access: Public, Virtual -// Description: Prepare a display region for rendering (set up -// scissor region and viewport) -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -prepare_display_region(DisplayRegionPipelineReader *dr) { - nassertv(dr != (DisplayRegionPipelineReader *)NULL); - GraphicsStateGuardian::prepare_display_region(dr); - - int l, u, w, h; - dr->get_region_pixels_i(l, u, w, h); - - // Create the viewport - D3DVIEWPORT8 vp = { l, u, w, h, 0.0f, 1.0f }; - _current_viewport = vp; - set_scissor(0.0f, 1.0f, 0.0f, 1.0f); - - if (_screen->_can_direct_disable_color_writes) { - _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, _color_write_mask); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::calc_projection_mat -// Access: Public, Virtual -// Description: Given a lens, calculates the appropriate projection -// matrix for use with this gsg. Note that the -// projection matrix depends a lot upon the coordinate -// system of the rendering API. -// -// The return value is a TransformState if the lens is -// acceptable, NULL if it is not. -//////////////////////////////////////////////////////////////////// -CPT(TransformState) DXGraphicsStateGuardian8:: -calc_projection_mat(const Lens *lens) { - if (lens == (Lens *)NULL) { - return NULL; - } - - if (!lens->is_linear()) { - return NULL; - } - - // DirectX also uses a Z range of 0 to 1, whereas the Panda - // convention is for the projection matrix to produce a Z range of - // -1 to 1. We have to rescale to compensate. - static const LMatrix4 rescale_mat - (1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0.5, 0, - 0, 0, 0.5, 1); - - LMatrix4 result = - LMatrix4::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) * - lens->get_projection_mat(_current_stereo_channel) * - rescale_mat; - - if (_scene_setup->get_inverted()) { - // If the scene is supposed to be inverted, then invert the - // projection matrix. - result *= LMatrix4::scale_mat(1.0f, -1.0f, 1.0f); - } - - return TransformState::make_mat(result); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::prepare_lens -// Access: Public, Virtual -// Description: Makes the current lens (whichever lens was most -// recently specified with set_scene()) active, so -// that it will transform future rendered geometry. -// Normally this is only called from the draw process, -// and usually it is called by set_scene(). -// -// The return value is true if the lens is acceptable, -// false if it is not. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -prepare_lens() { - CPT(TransformState) scissor_proj_mat = _scissor_mat->compose(_projection_mat); - LMatrix4f mat = LCAST(float, scissor_proj_mat->get_mat()); - HRESULT hr = - _d3d_device->SetTransform(D3DTS_PROJECTION, - (D3DMATRIX*)mat.get_data()); - return SUCCEEDED(hr); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::begin_frame -// Access: Public, Virtual -// Description: Called before each frame is rendered, to allow the -// GSG a chance to do any internal cleanup before -// beginning the frame. -// -// The return value is true if successful (in which case -// the frame will be drawn and end_frame() will be -// called later), or false if unsuccessful (in which -// case nothing will be drawn and end_frame() will not -// be called). -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -begin_frame(Thread *current_thread) { - if (!GraphicsStateGuardian::begin_frame(current_thread)) { - return false; - } - - if (_d3d_device == NULL) { - dxgsg8_cat.debug() - << this << "::begin_frame(): no device.\n"; - return false; - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::begin_scene -// Access: Public, Virtual -// Description: Called between begin_frame() and end_frame() to mark -// the beginning of drawing commands for a "scene" -// (usually a particular DisplayRegion) within a frame. -// All 3-D drawing commands, except the clear operation, -// must be enclosed within begin_scene() .. end_scene(). -// -// The return value is true if successful (in which case -// the scene will be drawn and end_scene() will be -// called later), or false if unsuccessful (in which -// case nothing will be drawn and end_scene() will not -// be called). -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -begin_scene() { - if (!GraphicsStateGuardian::begin_scene()) { - return false; - } - - HRESULT hr = _d3d_device->BeginScene(); - - if (FAILED(hr)) { - if (hr == D3DERR_DEVICELOST) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "BeginScene returns D3DERR_DEVICELOST" << endl; - } - - check_cooperative_level(); - - } else { - dxgsg8_cat.error() - << "BeginScene failed, unhandled error hr == " - << D3DERRORSTRING(hr) << endl; - throw_event("panda3d-render-error"); - } - return false; - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::end_scene -// Access: Public, Virtual -// Description: Called between begin_frame() and end_frame() to mark -// the end of drawing commands for a "scene" (usually a -// particular DisplayRegion) within a frame. All 3-D -// drawing commands, except the clear operation, must be -// enclosed within begin_scene() .. end_scene(). -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -end_scene() { - GraphicsStateGuardian::end_scene(); - _dlights.clear(); - - HRESULT hr = _d3d_device->EndScene(); - - if (FAILED(hr)) { - if (hr == D3DERR_DEVICELOST) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "EndScene returns DeviceLost\n"; - } - check_cooperative_level(); - - } else { - dxgsg8_cat.error() - << "EndScene failed, unhandled error hr == " << D3DERRORSTRING(hr); - throw_event("panda3d-render-error"); - } - return; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::end_frame -// Access: Public, Virtual -// Description: Called after each frame is rendered, to allow the -// GSG a chance to do any internal cleanup after -// rendering the frame, and before the window flips. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -end_frame(Thread *current_thread) { - -#if defined(DO_PSTATS) - if (_texmgrmem_total_pcollector.is_active()) { -#define TICKS_PER_GETTEXINFO (2.5*1000) // 2.5 second interval - static DWORD last_tick_count = 0; - DWORD cur_tick_count = GetTickCount(); - - if (cur_tick_count - last_tick_count > TICKS_PER_GETTEXINFO) { - last_tick_count = cur_tick_count; - report_texmgr_stats(); - } - } -#endif - - // Note: regular GraphicsWindow::end_frame is being called, - // but we override gsg::end_frame, so need to explicitly call it here - // (currently it's an empty fn) - GraphicsStateGuardian::end_frame(current_thread); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::begin_draw_primitives -// Access: Public, Virtual -// Description: Called before a sequence of draw_primitive() -// functions are called, this should prepare the vertex -// data for rendering. It returns true if the vertices -// are ok, false to abort this group of primitives. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -begin_draw_primitives(const GeomPipelineReader *geom_reader, - const GeomMunger *munger, - const GeomVertexDataPipelineReader *data_reader, - bool force) { - if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger, - data_reader, force)) { - return false; - } - nassertr(_data_reader != (GeomVertexDataPipelineReader *)NULL, false); - - const GeomVertexFormat *format = _data_reader->get_format(); - - // The munger should have put the FVF data in the first array. - const GeomVertexArrayDataHandle *data = _data_reader->get_array_reader(0); - - VertexBufferContext *vbc = ((GeomVertexArrayData *)(data->get_object()))->prepare_now(get_prepared_objects(), this); - nassertr(vbc != (VertexBufferContext *)NULL, false); - if (!apply_vertex_buffer(vbc, data, force)) { - return false; - } - - const GeomVertexAnimationSpec &animation = - data_reader->get_format()->get_animation(); - if (animation.get_animation_type() == Geom::AT_hardware) { - // Set up vertex blending. - switch (animation.get_num_transforms()) { - case 1: - // The MSDN docs suggest we should use D3DVBF_0WEIGHTS here, but - // that doesn't seem to work at all. On the other hand, - // D3DVBF_DISABLE *does* work, because it disables special - // handling, meaning only the world matrix affects these - // vertices--and by accident or design, the first matrix, - // D3DTS_WORLDMATRIX(0), *is* the world matrix. - _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE); - break; - case 2: - _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_1WEIGHTS); - break; - case 3: - _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_2WEIGHTS); - break; - case 4: - _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_3WEIGHTS); - break; - } - - if (animation.get_indexed_transforms()) { - // Set up indexed vertex blending. - _d3d_device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE); - } else { - _d3d_device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); - } - - const TransformTable *table = data_reader->get_transform_table(); - if (table != (TransformTable *)NULL) { - for (int i = 0; i < table->get_num_transforms(); i++) { - LMatrix4 mat; - table->get_transform(i)->mult_matrix(mat, _internal_transform->get_mat()); - LMatrix4f matf = LCAST(float, mat); - const D3DMATRIX *d3d_mat = (const D3DMATRIX *)matf.get_data(); - _d3d_device->SetTransform(D3DTS_WORLDMATRIX(i), d3d_mat); - } - - // Setting the first animation matrix steps on the world matrix, - // so we have to set a flag to reload the world matrix later. - _transform_stale = true; - } - _vertex_blending_enabled = true; - - } else { - // We're not using vertex blending. - if (_vertex_blending_enabled) { - _d3d_device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); - _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE); - _vertex_blending_enabled = false; - } - - if (_transform_stale && !_data_reader->is_vertex_transformed()) { - LMatrix4f mat = LCAST(float, _internal_transform->get_mat()); - const D3DMATRIX *d3d_mat = (const D3DMATRIX *)mat.get_data(); - _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat); - _transform_stale = false; - } - } - - if (_data_reader->is_vertex_transformed()) { - // If the vertex data claims to be already transformed into clip - // coordinates, wipe out the current projection and modelview - // matrix (so we don't attempt to transform it again). - - // It's tempting just to use the D3DFVF_XYZRHW specification on - // these vertices, but that turns out to be a bigger hammer than - // we want: that also prevents lighting calculations and user clip - // planes. - _d3d_device->SetTransform(D3DTS_WORLD, &_d3d_ident_mat); - static const LMatrix4f rescale_mat - (1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0.5, 0, - 0, 0, 0.5, 1); - _transform_stale = true; - - _d3d_device->SetTransform(D3DTS_PROJECTION, (const D3DMATRIX *)rescale_mat.get_data()); - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::draw_triangles -// Access: Public, Virtual -// Description: Draws a series of disconnected triangles. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) { - //PStatTimer timer(_draw_primitive_pcollector); - _vertices_tri_pcollector.add_level(reader->get_num_vertices()); - _primitive_batches_tri_pcollector.add_level(1); - if (reader->is_indexed()) { - int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex(); - int max_vertex = reader->get_max_vertex(); - - if (_active_vbuffer != NULL) { - // Indexed, vbuffers. - IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this); - nassertr(ibc != (IndexBufferContext *)NULL, false); - if (!apply_index_buffer(ibc, reader, force)) { - return false; - } - - _d3d_device->DrawIndexedPrimitive - (D3DPT_TRIANGLELIST, - min_vertex, max_vertex - min_vertex + 1, - 0, reader->get_num_primitives()); - - } else { - // Indexed, client arrays. - const unsigned char *index_pointer = reader->get_read_pointer(force); - if (index_pointer == NULL) { - return false; - } - D3DFORMAT index_type = get_index_type(reader->get_index_type()); - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - draw_indexed_primitive_up - (D3DPT_TRIANGLELIST, - min_vertex, max_vertex, - reader->get_num_primitives(), - index_pointer, index_type, vertex_pointer, - _data_reader->get_format()->get_array(0)->get_stride()); - } - } else { - if (_active_vbuffer != NULL) { - // Nonindexed, vbuffers. - _d3d_device->DrawPrimitive - (D3DPT_TRIANGLELIST, - reader->get_first_vertex(), - reader->get_num_primitives()); - - } else { - // Nonindexed, client arrays. - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - draw_primitive_up(D3DPT_TRIANGLELIST, reader->get_num_primitives(), - reader->get_first_vertex(), - reader->get_num_vertices(), - vertex_pointer, - _data_reader->get_format()->get_array(0)->get_stride()); - } - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::draw_tristrips -// Access: Public, Virtual -// Description: Draws a series of triangle strips. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) { - //PStatTimer timer(_draw_primitive_pcollector); - if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) { - // One long triangle strip, connected by the degenerate vertices - // that have already been set up within the primitive. - _vertices_tristrip_pcollector.add_level(reader->get_num_vertices()); - _primitive_batches_tristrip_pcollector.add_level(1); - if (reader->is_indexed()) { - int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex(); - int max_vertex = reader->get_max_vertex(); - - if (_active_vbuffer != NULL) { - // Indexed, vbuffers, one line triangle strip. - IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this); - nassertr(ibc != (IndexBufferContext *)NULL, false); - if (!apply_index_buffer(ibc, reader, force)) { - return false; - } - - _d3d_device->DrawIndexedPrimitive - (D3DPT_TRIANGLESTRIP, - min_vertex, max_vertex - min_vertex + 1, - 0, reader->get_num_vertices() - 2); - - } else { - // Indexed, client arrays, one long triangle strip. - const unsigned char *index_pointer = reader->get_read_pointer(force); - if (index_pointer == NULL) { - return false; - } - D3DFORMAT index_type = get_index_type(reader->get_index_type()); - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - draw_indexed_primitive_up - (D3DPT_TRIANGLESTRIP, - min_vertex, max_vertex, - reader->get_num_vertices() - 2, - index_pointer, index_type, vertex_pointer, - _data_reader->get_format()->get_array(0)->get_stride()); - } - } else { - if (_active_vbuffer != NULL) { - // Nonindexed, vbuffers, one long triangle strip. - _d3d_device->DrawPrimitive - (D3DPT_TRIANGLESTRIP, - reader->get_first_vertex(), - reader->get_num_vertices() - 2); - - } else { - // Indexed, client arrays, one long triangle strip. - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - draw_primitive_up(D3DPT_TRIANGLESTRIP, - reader->get_num_vertices() - 2, - reader->get_first_vertex(), - reader->get_num_vertices(), - vertex_pointer, - _data_reader->get_format()->get_array(0)->get_stride()); - } - } - - } else { - // Send the individual triangle strips, stepping over the - // degenerate vertices. - CPTA_int ends = reader->get_ends(); - _primitive_batches_tristrip_pcollector.add_level(ends.size()); - - if (reader->is_indexed()) { - CPTA_int ends = reader->get_ends(); - int index_stride = reader->get_index_stride(); - _primitive_batches_tristrip_pcollector.add_level(ends.size()); - - GeomVertexReader mins(reader->get_mins(), 0); - GeomVertexReader maxs(reader->get_maxs(), 0); - nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() && - reader->get_maxs()->get_num_rows() == (int)ends.size(), false); - - if (_active_vbuffer != NULL) { - // Indexed, vbuffers, individual triangle strips. - IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this); - nassertr(ibc != (IndexBufferContext *)NULL, false); - if (!apply_index_buffer(ibc, reader, force)) { - return false; - } - - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_tristrip_pcollector.add_level(ends[i] - start); - unsigned int min = mins.get_data1i(); - unsigned int max = maxs.get_data1i(); - _d3d_device->DrawIndexedPrimitive - (D3DPT_TRIANGLESTRIP, - min, max - min + 1, - start, ends[i] - start - 2); - - start = ends[i] + 2; - } - - } else { - // Indexed, client arrays, individual triangle strips. - int stride = _data_reader->get_format()->get_array(0)->get_stride(); - const unsigned char *index_pointer = reader->get_read_pointer(force); - if (index_pointer == NULL) { - return false; - } - D3DFORMAT index_type = get_index_type(reader->get_index_type()); - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_tristrip_pcollector.add_level(ends[i] - start); - unsigned int min = mins.get_data1i(); - unsigned int max = maxs.get_data1i(); - draw_indexed_primitive_up - (D3DPT_TRIANGLESTRIP, - min, max, - ends[i] - start - 2, - index_pointer + start * index_stride, index_type, - vertex_pointer, stride); - - start = ends[i] + 2; - } - } - } else { - unsigned int first_vertex = reader->get_first_vertex(); - - if (_active_vbuffer != NULL) { - // Nonindexed, vbuffers, individual triangle strips. - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_tristrip_pcollector.add_level(ends[i] - start); - _d3d_device->DrawPrimitive - (D3DPT_TRIANGLESTRIP, - first_vertex + start, ends[i] - start - 2); - - start = ends[i] + 2; - } - - } else { - // Nonindexed, client arrays, individual triangle strips. - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - int stride = _data_reader->get_format()->get_array(0)->get_stride(); - - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_tristrip_pcollector.add_level(ends[i] - start); - draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2, - first_vertex + start, - ends[i] - start, - vertex_pointer, stride); - - start = ends[i] + 2; - } - } - } - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::draw_trifans -// Access: Public, Virtual -// Description: Draws a series of triangle fans. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) { - //PStatTimer timer(_draw_primitive_pcollector); - CPTA_int ends = reader->get_ends(); - _primitive_batches_trifan_pcollector.add_level(ends.size()); - - if (reader->is_indexed()) { - int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex(); - int max_vertex = reader->get_max_vertex(); - - // Send the individual triangle fans. There's no connecting fans - // with degenerate vertices, so no worries about that. - int index_stride = reader->get_index_stride(); - - GeomVertexReader mins(reader->get_mins(), 0); - GeomVertexReader maxs(reader->get_maxs(), 0); - nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() && - reader->get_maxs()->get_num_rows() == (int)ends.size(), false); - - if (_active_vbuffer != NULL) { - // Indexed, vbuffers. - IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this); - nassertr(ibc != (IndexBufferContext *)NULL, false); - if (!apply_index_buffer(ibc, reader, force)) { - return false; - } - - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_trifan_pcollector.add_level(ends[i] - start); - unsigned int min = mins.get_data1i(); - unsigned int max = maxs.get_data1i(); - _d3d_device->DrawIndexedPrimitive - (D3DPT_TRIANGLEFAN, - min, max - min + 1, - start, ends[i] - start - 2); - - start = ends[i]; - } - - } else { - // Indexed, client arrays. - int stride = _data_reader->get_format()->get_array(0)->get_stride(); - const unsigned char *index_pointer = reader->get_read_pointer(force); - if (index_pointer == NULL) { - return false; - } - D3DFORMAT index_type = get_index_type(reader->get_index_type()); - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_trifan_pcollector.add_level(ends[i] - start); - unsigned int min = mins.get_data1i(); - unsigned int max = maxs.get_data1i(); - draw_indexed_primitive_up - (D3DPT_TRIANGLEFAN, - min, max, - ends[i] - start - 2, - index_pointer + start * index_stride, index_type, - vertex_pointer, stride); - - start = ends[i]; - } - } - } else { - unsigned int first_vertex = reader->get_first_vertex(); - - if (_active_vbuffer != NULL) { - // Nonindexed, vbuffers. - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_trifan_pcollector.add_level(ends[i] - start); - _d3d_device->DrawPrimitive - (D3DPT_TRIANGLEFAN, - first_vertex + start, ends[i] - start - 2); - - start = ends[i]; - } - - } else { - // Nonindexed, client arrays. - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - int stride = _data_reader->get_format()->get_array(0)->get_stride(); - - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_trifan_pcollector.add_level(ends[i] - start); - draw_primitive_up(D3DPT_TRIANGLEFAN, - ends[i] - start - 2, - first_vertex, - ends[i] - start, - vertex_pointer, stride); - start = ends[i]; - } - } - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::draw_lines -// Access: Public, Virtual -// Description: Draws a series of disconnected line segments. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -draw_lines(const GeomPrimitivePipelineReader *reader, bool force) { - //PStatTimer timer(_draw_primitive_pcollector); - _vertices_other_pcollector.add_level(reader->get_num_vertices()); - _primitive_batches_other_pcollector.add_level(1); - - if (reader->is_indexed()) { - int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex(); - int max_vertex = reader->get_max_vertex(); - - if (_active_vbuffer != NULL) { - // Indexed, vbuffers. - IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this); - nassertr(ibc != (IndexBufferContext *)NULL, false); - if (!apply_index_buffer(ibc, reader, force)) { - return false; - } - - _d3d_device->DrawIndexedPrimitive - (D3DPT_LINELIST, - min_vertex, max_vertex - min_vertex + 1, - 0, reader->get_num_primitives()); - - } else { - // Indexed, client arrays. - const unsigned char *index_pointer = reader->get_read_pointer(force); - if (index_pointer == NULL) { - return false; - } - D3DFORMAT index_type = get_index_type(reader->get_index_type()); - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - - draw_indexed_primitive_up - (D3DPT_LINELIST, - min_vertex, max_vertex, - reader->get_num_primitives(), - index_pointer, index_type, vertex_pointer, - _data_reader->get_format()->get_array(0)->get_stride()); - } - } else { - if (_active_vbuffer != NULL) { - // Nonindexed, vbuffers. - _d3d_device->DrawPrimitive - (D3DPT_LINELIST, - reader->get_first_vertex(), - reader->get_num_primitives()); - - } else { - // Nonindexed, client arrays. - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - draw_primitive_up(D3DPT_LINELIST, reader->get_num_primitives(), - reader->get_first_vertex(), - reader->get_num_vertices(), - vertex_pointer, - _data_reader->get_format()->get_array(0)->get_stride()); - } - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::draw_linestrips -// Access: Public, Virtual -// Description: Draws a series of line strips. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) { - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::draw_points -// Access: Public, Virtual -// Description: Draws a series of disconnected points. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -draw_points(const GeomPrimitivePipelineReader *reader, bool force) { - //PStatTimer timer(_draw_primitive_pcollector); - _vertices_other_pcollector.add_level(reader->get_num_vertices()); - _primitive_batches_other_pcollector.add_level(1); - - // The munger should have protected us from indexed points--DirectX - // doesn't support them. - nassertr(!reader->is_indexed(), false); - - if (_active_vbuffer != NULL) { - // Nonindexed, vbuffers. - _d3d_device->DrawPrimitive - (D3DPT_POINTLIST, - reader->get_first_vertex(), - reader->get_num_primitives()); - - } else { - // Nonindexed, client arrays. - const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force); - if (vertex_pointer == NULL) { - return false; - } - draw_primitive_up(D3DPT_POINTLIST, reader->get_num_primitives(), - reader->get_first_vertex(), - reader->get_num_vertices(), - vertex_pointer, - _data_reader->get_format()->get_array(0)->get_stride()); - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::end_draw_primitives() -// Access: Public, Virtual -// Description: Called after a sequence of draw_primitive() -// functions are called, this should do whatever cleanup -// is appropriate. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -end_draw_primitives() { - // Turn off vertex blending--it seems to cause problems if we leave - // it on. - if (_vertex_blending_enabled) { - _d3d_device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); - _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE); - _vertex_blending_enabled = false; - } - - if (_data_reader->is_vertex_transformed()) { - // Restore the projection matrix that we wiped out above. - LMatrix4f mat = LCAST(float, _projection_mat->get_mat()); - _d3d_device->SetTransform(D3DTS_PROJECTION, - (D3DMATRIX*)mat.get_data()); - } - - GraphicsStateGuardian::end_draw_primitives(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::framebuffer_copy_to_texture -// Access: Public, Virtual -// Description: Copy the pixels within the indicated display -// region from the framebuffer into texture memory. -// -// If z > -1, it is the cube map index into which to -// copy. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -framebuffer_copy_to_texture(Texture *tex, int view, int z, - const DisplayRegion *dr, const RenderBuffer &rb) { - set_read_buffer(rb); - - int orig_x = tex->get_x_size(); - int orig_y = tex->get_y_size(); - - HRESULT hr; - int xo, yo, w, h; - dr->get_region_pixels_i(xo, yo, w, h); - tex->set_size_padded(w, h); - - TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this); - if (tc == (TextureContext *)NULL) { - return false; - } - DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc); - if (!dtc->create_texture(*_screen)) { - // Oops, we can't re-create the texture for some reason. - dxgsg8_cat.error() - << "Unable to re-create texture " << *dtc->get_texture() << endl; - return false; - } - - if (tex->get_texture_type() != Texture::TT_2d_texture) { - // For a specialty texture like a cube map, go the slow route - // through RAM for now. - return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, true); - } - nassertr(dtc->get_d3d_2d_texture() != NULL, false); - - IDirect3DSurface8 *tex_level_0; - hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0); - if (FAILED(hr)) { - dxgsg8_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr); - return false; - } - - // If the texture is the wrong size, we need to do something about it. - D3DSURFACE_DESC texdesc; - hr = tex_level_0->GetDesc(&texdesc); - if (FAILED(hr)) { - dxgsg8_cat.error() << "GetDesc failed in copy_texture" << D3DERRORSTRING(hr); - SAFE_RELEASE(tex_level_0); - return false; - } - if ((texdesc.Width != tex->get_x_size())||(texdesc.Height != tex->get_y_size())) { - if ((orig_x != tex->get_x_size()) || (orig_y != tex->get_y_size())) { - // Texture might be wrong size because we resized it and need to recreate. - SAFE_RELEASE(tex_level_0); - if (!dtc->create_texture(*_screen)) { - // Oops, we can't re-create the texture for some reason. - dxgsg8_cat.error() - << "Unable to re-create texture " << *dtc->get_texture() << endl; - return false; - } - hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0); - if (FAILED(hr)) { - dxgsg8_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr); - return false; - } - hr = tex_level_0->GetDesc(&texdesc); - if (FAILED(hr)) { - dxgsg8_cat.error() << "GetDesc 2 failed in copy_texture" << D3DERRORSTRING(hr); - SAFE_RELEASE(tex_level_0); - return false; - } - } - if ((texdesc.Width != tex->get_x_size())||(texdesc.Height != tex->get_y_size())) { - // If it's still the wrong size, it's because driver can't create size - // that we want. In that case, there's no helping it, we have to give up. - dxgsg8_cat.error() - << "Unable to copy to texture, texture is wrong size: " << *dtc->get_texture() << endl; - SAFE_RELEASE(tex_level_0); - return false; - } - } - - IDirect3DSurface8 *render_target; - hr = _d3d_device->GetRenderTarget(&render_target); - if (FAILED(hr)) { - dxgsg8_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr); - SAFE_RELEASE(tex_level_0); - return false; - } - - RECT src_rect; - - src_rect.left = xo; - src_rect.right = xo+w; - src_rect.top = yo; - src_rect.bottom = yo+h; - - // now copy from fb to tex - bool okflag = true; - hr = _d3d_device->CopyRects(render_target, &src_rect, 1, tex_level_0, 0); - if (FAILED(hr)) { - dxgsg8_cat.info() - << "CopyRects failed in copy_texture " << D3DERRORSTRING(hr); - okflag = framebuffer_copy_to_ram(tex, view, z, dr, rb); - } - - SAFE_RELEASE(render_target); - SAFE_RELEASE(tex_level_0); - - if (okflag) { - dtc->mark_loaded(); - dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru); - - } else { - // The copy failed. Fall back to copying it to RAM and back. - // Terribly slow, but what are you going to do? - return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, true); - } - - return true; -} - - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::framebuffer_copy_to_ram -// Access: Public, Virtual -// Description: Copy the pixels within the indicated display region -// from the framebuffer into system memory, not texture -// memory. Returns true on success, false on failure. -// -// This completely redefines the ram image of the -// indicated texture. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -framebuffer_copy_to_ram(Texture *tex, int view, int z, - const DisplayRegion *dr, const RenderBuffer &rb) { - return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, false); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_framebuffer_copy_to_ram -// Access: Public -// Description: This is the implementation of -// framebuffer_copy_to_ram(); it adds one additional -// parameter, which should be true if the framebuffer is -// to be inverted during the copy (as in the same way it -// copies to texture memory). -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -do_framebuffer_copy_to_ram(Texture *tex, int view, int z, - const DisplayRegion *dr, const RenderBuffer &rb, - bool inverted) { - set_read_buffer(rb); - - RECT rect; - nassertr(tex != NULL && dr != NULL, false); - - int xo, yo, w, h; - dr->get_region_pixels_i(xo, yo, w, h); - - Texture::Format format = tex->get_format(); - Texture::ComponentType component_type = tex->get_component_type(); - - switch (format) { - case Texture::F_depth_stencil: - // Sorry, not (yet?) supported in pandadx. - return false; - - default: - format = Texture::F_rgb; - component_type = Texture::T_unsigned_byte; - } - - Texture::TextureType texture_type; - if (z >= 0) { - texture_type = Texture::TT_cube_map; - } else { - texture_type = Texture::TT_2d_texture; - } - - if (tex->get_x_size() != w || tex->get_y_size() != h || - tex->get_component_type() != component_type || - tex->get_format() != format || - tex->get_texture_type() != texture_type) { - // Re-setup the texture; its properties have changed. - tex->setup_texture(texture_type, w, h, tex->get_z_size(), - component_type, format); - } - - rect.top = yo; - rect.left = xo; - rect.right = xo + w; - rect.bottom = yo + h; - bool copy_inverted = false; - - IDirect3DSurface8 *temp_surface = NULL; - HRESULT hr; - - // Note if you try to grab the backbuffer and full-screen - // anti-aliasing is on, the backbuffer might be larger than the - // window size. For screenshots it's safer to get the front buffer. - if (_cur_read_pixel_buffer & RenderBuffer::T_back) { - IDirect3DSurface8 *backbuffer = NULL; - // GetRenderTarget() seems to be a little more reliable than - // GetBackBuffer(). Might just be related to the swap_chain - // thing. - hr = _d3d_device->GetRenderTarget(&backbuffer); - - if (FAILED(hr)) { - dxgsg8_cat.error() << "GetRenderTarget failed" << D3DERRORSTRING(hr); - return false; - } - - // Since we might not be able to Lock the back buffer, we will - // need to copy it to a temporary surface of the appropriate type - // first. - hr = _d3d_device->CreateImageSurface(w, h, _screen->_display_mode.Format, - &temp_surface); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "CreateImageSurface failed in copy_pixel_buffer()" - << D3DERRORSTRING(hr); - backbuffer->Release(); - return false; - } - - // Now we must copy from the backbuffer to our temporary surface. - hr = _d3d_device->CopyRects(backbuffer, &rect, 1, temp_surface, NULL); - if (FAILED(hr)) { - dxgsg8_cat.error() << "CopyRects failed" << D3DERRORSTRING(hr); - temp_surface->Release(); - backbuffer->Release(); - return false; - } - - copy_inverted = true; - - RELEASE(backbuffer, dxgsg8, "backbuffer", RELEASE_ONCE); - - } else if (_cur_read_pixel_buffer & RenderBuffer::T_front) { - - if (_screen->_presentation_params.Windowed) { - // GetFrontBuffer() retrieves the entire desktop for a monitor, - // so we need to reserve space for that. - - // We have to use GetMonitorInfo(), since this GSG may not be - // for the primary monitor. - MONITORINFO minfo; - minfo.cbSize = sizeof(MONITORINFO); - GetMonitorInfo(_screen->_monitor, &minfo); - - w = RECT_XSIZE(minfo.rcMonitor); - h = RECT_YSIZE(minfo.rcMonitor); - - // set rect to client area of window in scrn coords - ClientToScreen(_screen->_window, (POINT*)&rect.left); - ClientToScreen(_screen->_window, (POINT*)&rect.right); - } - - // For GetFrontBuffer(), we need a temporary surface of type - // A8R8G8B8. Unlike GetBackBuffer(), GetFrontBuffer() implicitly - // performs a copy. - hr = _d3d_device->CreateImageSurface(w, h, D3DFMT_A8R8G8B8, &temp_surface); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "CreateImageSurface failed in copy_pixel_buffer()" - << D3DERRORSTRING(hr); - return false; - } - - hr = _d3d_device->GetFrontBuffer(temp_surface); - - if (hr == D3DERR_DEVICELOST) { - dxgsg8_cat.error() - << "copy_pixel_buffer failed: device lost\n"; - temp_surface->Release(); - return false; - } - - copy_inverted = true; - - } else { - dxgsg8_cat.error() - << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n"; - temp_surface->Release(); - return false; - } - - if (inverted) { - copy_inverted = !copy_inverted; - } - DXTextureContext8::d3d_surface_to_texture(rect, temp_surface, - copy_inverted, tex, view, z); - - RELEASE(temp_surface, dxgsg8, "temp_surface", RELEASE_ONCE); - - nassertr(tex->has_ram_image(), false); - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::reset -// Access: Public, Virtual -// Description: Resets all internal state as if the gsg were newly -// created. The GraphicsWindow pointer represents a -// typical window that might be used for this context; -// it may be required to set up the frame buffer -// properly the first time. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -reset() { - GraphicsStateGuardian::reset(); - - _auto_rescale_normal = false; - - // overwrite gsg defaults with these values - - HRESULT hr; - - // make sure gsg passes all current state down to us - // set_state_and_transform(RenderState::make_empty(), - // TransformState::make_identity()); - // want gsg to pass all state settings down so any non-matching defaults we set here get overwritten - - if (_d3d_device == NULL) { - return; - } - - nassertv(_screen->_d3d8 != NULL); - - D3DCAPS8 d3d_caps; - _d3d_device->GetDeviceCaps(&d3d_caps); - - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "\nHwTransformAndLight = " << ((d3d_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0) - << "\nMaxTextureWidth = " << d3d_caps.MaxTextureWidth - << "\nMaxTextureHeight = " << d3d_caps.MaxTextureHeight - << "\nMaxVolumeExtent = " << d3d_caps.MaxVolumeExtent - << "\nMaxTextureAspectRatio = " << d3d_caps.MaxTextureAspectRatio - << "\nTexCoordCount = " << (d3d_caps.FVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK) - << "\nMaxTextureBlendStages = " << d3d_caps.MaxTextureBlendStages - << "\nMaxSimultaneousTextures = " << d3d_caps.MaxSimultaneousTextures - << "\nMaxActiveLights = " << d3d_caps.MaxActiveLights - << "\nMaxUserClipPlanes = " << d3d_caps.MaxUserClipPlanes - << "\nMaxVertexBlendMatrices = " << d3d_caps.MaxVertexBlendMatrices - << "\nMaxVertexBlendMatrixIndex = " << d3d_caps.MaxVertexBlendMatrixIndex - << "\nMaxPointSize = " << d3d_caps.MaxPointSize - << "\nMaxPrimitiveCount = " << d3d_caps.MaxPrimitiveCount - << "\nMaxVertexIndex = " << d3d_caps.MaxVertexIndex - << "\nMaxStreams = " << d3d_caps.MaxStreams - << "\nMaxStreamStride = " << d3d_caps.MaxStreamStride - << "\nD3DTEXOPCAPS_MULTIPLYADD = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) != 0) - << "\nD3DTEXOPCAPS_LERP = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0) - << "\nD3DPMISCCAPS_TSSARGTEMP = " << ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0) - << "\nVertexShaderVersion = " << D3DSHADER_VERSION_MAJOR (d3d_caps.VertexShaderVersion) << "." << D3DSHADER_VERSION_MINOR (d3d_caps.VertexShaderVersion) - << "\nPixelShaderVersion = " << D3DSHADER_VERSION_MAJOR (d3d_caps.PixelShaderVersion) << "." << D3DSHADER_VERSION_MINOR (d3d_caps.PixelShaderVersion) - << "\nMaxVertexShaderConst = " << d3d_caps.MaxVertexShaderConst - << "\n"; - } - - if (support_stencil) { - int min_stencil = D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR; - if ((d3d_caps.StencilCaps & min_stencil) == min_stencil) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "Checking for stencil; mode = " - << D3DFormatStr(_screen->_presentation_params.AutoDepthStencilFormat) - << "\n"; - } - switch (_screen->_presentation_params.AutoDepthStencilFormat) { - // These are the only formats that support stencil. - case D3DFMT_D15S1: - case D3DFMT_D24S8: - case D3DFMT_D24X4S4: - _supports_stencil = true; - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "Stencils supported.\n"; - } - break; - - default: - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "Stencils NOT supported.\n"; - } - } - } - } - - _max_vertices_per_array = d3d_caps.MaxVertexIndex; - _max_vertices_per_primitive = d3d_caps.MaxPrimitiveCount; - - _max_texture_stages = d3d_caps.MaxSimultaneousTextures; - - _max_texture_dimension = min(d3d_caps.MaxTextureWidth, d3d_caps.MaxTextureHeight); - - _supports_texture_combine = ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0); - _supports_texture_saved_result = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0); - _supports_texture_dot3 = true; - - // check for render to texture support - D3DDEVICE_CREATION_PARAMETERS creation_parameters; - - _supports_render_texture = false; - _screen->_render_to_texture_d3d_format = D3DFMT_UNKNOWN; - _screen->_framebuffer_d3d_format = D3DFMT_UNKNOWN; - - #define TOTAL_RENDER_TO_TEXTURE_FORMATS 3 - - D3DFORMAT render_to_texture_formats [TOTAL_RENDER_TO_TEXTURE_FORMATS] = - { - D3DFMT_A8R8G8B8, // check for this format first - D3DFMT_X8R8G8B8, - D3DFMT_UNKNOWN, // place holder for _screen->_display_mode.Format - }; - - render_to_texture_formats [TOTAL_RENDER_TO_TEXTURE_FORMATS - 1] = _screen->_display_mode.Format; - - hr = _d3d_device->GetCreationParameters (&creation_parameters); - if (SUCCEEDED (hr)) { - _screen->_framebuffer_d3d_format = _screen->_display_mode.Format; - - int index; - for (index = 0; index < TOTAL_RENDER_TO_TEXTURE_FORMATS; index++) { - hr = _screen->_d3d8->CheckDeviceFormat ( - creation_parameters.AdapterOrdinal, - creation_parameters.DeviceType, - _screen->_display_mode.Format, - D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, - render_to_texture_formats [index]); - if (SUCCEEDED (hr)) { - _screen->_render_to_texture_d3d_format = render_to_texture_formats [index]; - _supports_render_texture = true; - } - if (_supports_render_texture) { - break; - } - } - } - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() << "Render to Texture Support = " << _supports_render_texture << "\n"; - } - - _supports_3d_texture = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) != 0); - if (_supports_3d_texture) { - _max_3d_texture_dimension = d3d_caps.MaxVolumeExtent; - } - _supports_cube_map = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) != 0); - if (_supports_cube_map) { - _max_cube_map_dimension = _max_texture_dimension; - } - - _num_active_texture_stages = 0; - - _max_lights = (int)d3d_caps.MaxActiveLights; - _max_clip_planes = (int)d3d_caps.MaxUserClipPlanes; - _max_vertex_transforms = d3d_caps.MaxVertexBlendMatrices; - _max_vertex_transform_indices = d3d_caps.MaxVertexBlendMatrixIndex; - - _d3d_device->SetRenderState(D3DRS_AMBIENT, 0x0); - - _clip_plane_bits = 0; - _d3d_device->SetRenderState(D3DRS_CLIPPLANEENABLE , 0x0); - - _d3d_device->SetRenderState(D3DRS_CLIPPING, true); - - _d3d_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); - - _d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - - _d3d_device->SetRenderState(D3DRS_EDGEANTIALIAS, false); - - _d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - - _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - - _d3d_device->SetRenderState(D3DRS_FOGENABLE, FALSE); - - _has_scene_graph_color = false; - - _last_testcooplevel_result = D3D_OK; - - for(int i = 0; i < MAX_POSSIBLE_TEXFMTS; i++) { - // look for all possible DX8 texture fmts - D3DFORMAT_FLAG fmtflag = D3DFORMAT_FLAG(1 << i); - hr = _screen->_d3d8->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format, - 0x0, D3DRTYPE_TEXTURE, g_D3DFORMATmap[fmtflag]); - if (SUCCEEDED(hr)){ - _screen->_supported_tex_formats_mask |= fmtflag; - } - } - - // check if compressed textures are supported - #define CHECK_FOR_DXTVERSION(num) \ - if (_screen->_supported_tex_formats_mask & DXT##num##_FLAG) {\ - if (dxgsg8_cat.is_debug()) {\ - dxgsg8_cat.debug() << "Compressed texture format DXT" << #num << " supported \n";\ - }\ - _supports_compressed_texture = true;\ - _compressed_texture_formats.set_bit(Texture::CM_dxt##num);\ - } - - CHECK_FOR_DXTVERSION(1) - CHECK_FOR_DXTVERSION(2) - CHECK_FOR_DXTVERSION(3) - CHECK_FOR_DXTVERSION(4) - CHECK_FOR_DXTVERSION(5) - - #undef CHECK_FOR_DXTVERSION - - // s3 virge drivers sometimes give crap values for these - if (_screen->_d3dcaps.MaxTextureWidth == 0) - _screen->_d3dcaps.MaxTextureWidth = 256; - - if (_screen->_d3dcaps.MaxTextureHeight == 0) - _screen->_d3dcaps.MaxTextureHeight = 256; - - if (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) { - // Watch out for drivers that emulate per-pixel fog with - // per-vertex fog (Riva128, Matrox Millen G200). Some of these - // require gouraud-shading to be set to work, as if you were using - // vertex fog - _do_fog_type = PerPixelFog; - } else { - // every card is going to have vertex fog, since it's implemented - // in d3d runtime. - nassertv((_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0); - - // vertex fog may look crappy if you have large polygons in the - // foreground and they get clipped, so you may want to disable it - - if (dx_no_vertex_fog) { - _do_fog_type = None; - } else { - _do_fog_type = PerVertexFog; - - // range-based fog only works with vertex fog in dx7/8 - if (dx_use_rangebased_fog && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE)) { - _d3d_device->SetRenderState(D3DRS_RANGEFOGENABLE, true); - } - } - } - - _screen->_can_direct_disable_color_writes = ((_screen->_d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0); - - // Lighting, let's turn it off initially. - _d3d_device->SetRenderState(D3DRS_LIGHTING, false); - - // turn on dithering if the rendertarget is < 8bits/color channel - bool dither_enabled = ((!dx_no_dithering) && IS_16BPP_DISPLAY_FORMAT(_screen->_presentation_params.BackBufferFormat) - && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)); - _d3d_device->SetRenderState(D3DRS_DITHERENABLE, dither_enabled); - - _d3d_device->SetRenderState(D3DRS_CLIPPING, true); - - // Stencil test is off by default - _d3d_device->SetRenderState(D3DRS_STENCILENABLE, FALSE); - - // Antialiasing. - _d3d_device->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE); - - _current_fill_mode = RenderModeAttrib::M_filled; - _d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - - // must do SetTSS here because redundant states are filtered out by - // our code based on current values above, so initial conditions - // must be correct - _d3d_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); // disables texturing - - _cull_face_mode = CullFaceAttrib::M_cull_none; - _d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - - _d3d_device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS); - _d3d_device->SetRenderState(D3DRS_ALPHAREF, 255); - _d3d_device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - - // this is a new DX8 state that lets you do additional operations other than ADD (e.g. subtract/max/min) - // must check (_screen->_d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) (yes on GF2/Radeon8500, no on TNT) - _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - - PRINT_REFCNT(dxgsg8, _d3d_device); - - // Now that the GSG has been initialized, make it available for - // optimizations. - add_gsg(this); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::apply_fog -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -apply_fog(Fog *fog) { - if (_do_fog_type == None) - return; - - Fog::Mode panda_fogmode = fog->get_mode(); - D3DFOGMODE d3dfogmode = get_fog_mode_type(panda_fogmode); - - _d3d_device->SetRenderState((D3DRENDERSTATETYPE)_do_fog_type, d3dfogmode); - - const LColor &fog_colr = fog->get_color(); - _d3d_device->SetRenderState(D3DRS_FOGCOLOR, - MY_D3DRGBA(fog_colr[0], fog_colr[1], fog_colr[2], 0.0f)); // Alpha bits are not used - - // do we need to adjust fog start/end values based on D3DPRASTERCAPS_WFOG/D3DPRASTERCAPS_ZFOG ? - // if not WFOG, then docs say we need to adjust values to range [0, 1] - - switch (panda_fogmode) { - case Fog::M_linear: - { - PN_stdfloat onset, opaque; - fog->get_linear_range(onset, opaque); - - _d3d_device->SetRenderState(D3DRS_FOGSTART, - *((LPDWORD) (&onset))); - _d3d_device->SetRenderState(D3DRS_FOGEND, - *((LPDWORD) (&opaque))); - } - break; - case Fog::M_exponential: - case Fog::M_exponential_squared: - { - // Exponential fog is always camera-relative. - PN_stdfloat fog_density = fog->get_exp_density(); - _d3d_device->SetRenderState(D3DRS_FOGDENSITY, - *((LPDWORD) (&fog_density))); - } - break; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_transform -// Access: Protected -// Description: Sends the indicated transform matrix to the graphics -// API to be applied to future vertices. -// -// This transform is the internal_transform, already -// converted into the GSG's internal coordinate system. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_transform() { - const TransformState *transform = _internal_transform; - DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1)); - - LMatrix4f mat = LCAST(float, transform->get_mat()); - const D3DMATRIX *d3d_mat = (const D3DMATRIX *)mat.get_data(); - _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat); - _transform_stale = false; - - if (_auto_rescale_normal) { - do_auto_rescale_normal(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_alpha_test -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_alpha_test() { - const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot())); - AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->get_mode(); - if (mode == AlphaTestAttrib::M_none) { - _d3d_device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - - } else { - // AlphaTestAttrib::PandaCompareFunc === D3DCMPFUNC - _d3d_device->SetRenderState(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode); - _d3d_device->SetRenderState(D3DRS_ALPHAREF, (UINT) (target_alpha_test->get_reference_alpha()*255.0f)); //d3d uses 0x0-0xFF, not a float - _d3d_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_render_mode -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_render_mode() { - const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot())); - RenderModeAttrib::Mode mode = target_render_mode->get_mode(); - - switch (mode) { - case RenderModeAttrib::M_unchanged: - case RenderModeAttrib::M_filled: - case RenderModeAttrib::M_filled_flat: - _d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - break; - - case RenderModeAttrib::M_wireframe: - _d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); - break; - - case RenderModeAttrib::M_point: - _d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT); - break; - - default: - dxgsg8_cat.error() - << "Unknown render mode " << (int)mode << endl; - } - - // This might also specify the point size. - PN_stdfloat point_size = target_render_mode->get_thickness(); - _d3d_device->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&point_size)); - - if (target_render_mode->get_perspective()) { - _d3d_device->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE); - - LVector3 height(0.0f, point_size, 1.0f); - height = height * _projection_mat->get_mat(); - PN_stdfloat s = height[1] / point_size; - - PN_stdfloat zero = 0.0f; - PN_stdfloat one_over_s2 = 1.0f / (s * s); - _d3d_device->SetRenderState(D3DRS_POINTSCALE_A, *((DWORD*)&zero)); - _d3d_device->SetRenderState(D3DRS_POINTSCALE_B, *((DWORD*)&zero)); - _d3d_device->SetRenderState(D3DRS_POINTSCALE_C, *((DWORD*)&one_over_s2)); - - } else { - _d3d_device->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); - } - - _current_fill_mode = mode; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_rescale_normal -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_rescale_normal() { - const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot())); - RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode(); - - _auto_rescale_normal = false; - - switch (mode) { - case RescaleNormalAttrib::M_none: - _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, false); - break; - - case RescaleNormalAttrib::M_rescale: - case RescaleNormalAttrib::M_normalize: - _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, true); - break; - - case RescaleNormalAttrib::M_auto: - _auto_rescale_normal = true; - do_auto_rescale_normal(); - break; - - default: - dxgsg8_cat.error() - << "Unknown rescale_normal mode " << (int)mode << endl; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_depth_test -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_depth_test() { - const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot())); - DepthTestAttrib::PandaCompareFunc mode = target_depth_test->get_mode(); - if (mode == DepthTestAttrib::M_none) { - _d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - } else { - _d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - _d3d_device->SetRenderState(D3DRS_ZFUNC, (D3DCMPFUNC) mode); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_depth_write -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_depth_write() { - const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot())); - if (target_depth_write->get_mode() == DepthWriteAttrib::M_on) { - _d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - } else { - _d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_cull_face -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_cull_face() { - const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot())); - _cull_face_mode = target_cull_face->get_effective_mode(); - - switch (_cull_face_mode) { - case CullFaceAttrib::M_cull_none: - _d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - break; - case CullFaceAttrib::M_cull_clockwise: - _d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); - break; - case CullFaceAttrib::M_cull_counter_clockwise: - _d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - break; - default: - dxgsg8_cat.error() - << "invalid cull face mode " << (int)_cull_face_mode << endl; - break; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_fog -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_fog() { - const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot())); - if (!target_fog->is_off()) { - _d3d_device->SetRenderState(D3DRS_FOGENABLE, TRUE); - Fog *fog = target_fog->get_fog(); - nassertv(fog != (Fog *)NULL); - apply_fog(fog); - } else { - _d3d_device->SetRenderState(D3DRS_FOGENABLE, FALSE); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_depth_offset -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_depth_offset() { - const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot())); - int offset = target_depth_offset->get_offset(); - _d3d_device->SetRenderState(D3DRS_ZBIAS, offset); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_shade_model -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_shade_model() { - const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot())); - switch (target_shade_model->get_mode()) { - case ShadeModelAttrib::M_smooth: - _d3d_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); - break; - - case ShadeModelAttrib::M_flat: - _d3d_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); - break; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_state_and_transform -// Access: Public, Virtual -// Description: Simultaneously resets the render state and the -// transform state. -// -// This transform specified is the "internal" net -// transform, already converted into the GSG's internal -// coordinate space by composing it to -// get_cs_transform(). (Previously, this used to be the -// "external" net transform, with the assumption that -// that GSG would convert it internally, but that is no -// longer the case.) -// -// Special case: if (state==NULL), then the target -// state is already stored in _target. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -set_state_and_transform(const RenderState *target, - const TransformState *transform) { -#ifndef NDEBUG - if (gsg_cat.is_spam()) { - gsg_cat.spam() << "Setting GSG state to " << (void *)target << ":\n"; - target->write(gsg_cat.spam(false), 2); - } -#endif - _state_pcollector.add_level(1); - PStatTimer timer1(_draw_set_state_pcollector); - - if (transform != _internal_transform) { - //PStatTimer timer(_draw_set_state_transform_pcollector); - _state_pcollector.add_level(1); - _internal_transform = transform; - do_issue_transform(); - } - - if (target == _state_rs) { - return; - } - _target_rs = target; - - int alpha_test_slot = AlphaTestAttrib::get_class_slot(); - if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) || - !_state_mask.get_bit(alpha_test_slot)) { - //PStatTimer timer(_draw_set_state_alpha_test_pcollector); - do_issue_alpha_test(); - _state_mask.set_bit(alpha_test_slot); - } - - int clip_plane_slot = ClipPlaneAttrib::get_class_slot(); - if (_target_rs->get_attrib(clip_plane_slot) != _state_rs->get_attrib(clip_plane_slot) || - !_state_mask.get_bit(clip_plane_slot)) { - //PStatTimer timer(_draw_set_state_clip_plane_pcollector); - do_issue_clip_plane(); - _state_mask.set_bit(clip_plane_slot); - } - - int color_slot = ColorAttrib::get_class_slot(); - int color_scale_slot = ColorScaleAttrib::get_class_slot(); - if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) || - _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) || - !_state_mask.get_bit(color_slot) || - !_state_mask.get_bit(color_scale_slot)) { - //PStatTimer timer(_draw_set_state_color_pcollector); - do_issue_color(); - do_issue_color_scale(); - _state_mask.set_bit(color_slot); - _state_mask.set_bit(color_scale_slot); - } - - int cull_face_slot = CullFaceAttrib::get_class_slot(); - if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) || - !_state_mask.get_bit(cull_face_slot)) { - //PStatTimer timer(_draw_set_state_cull_face_pcollector); - do_issue_cull_face(); - _state_mask.set_bit(cull_face_slot); - } - - int depth_offset_slot = DepthOffsetAttrib::get_class_slot(); - if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) || - !_state_mask.get_bit(depth_offset_slot)) { - //PStatTimer timer(_draw_set_state_depth_offset_pcollector); - do_issue_depth_offset(); - _state_mask.set_bit(depth_offset_slot); - } - - int depth_test_slot = DepthTestAttrib::get_class_slot(); - if (_target_rs->get_attrib(depth_test_slot) != _state_rs->get_attrib(depth_test_slot) || - !_state_mask.get_bit(depth_test_slot)) { - //PStatTimer timer(_draw_set_state_depth_test_pcollector); - do_issue_depth_test(); - _state_mask.set_bit(depth_test_slot); - } - - int depth_write_slot = DepthWriteAttrib::get_class_slot(); - if (_target_rs->get_attrib(depth_write_slot) != _state_rs->get_attrib(depth_write_slot) || - !_state_mask.get_bit(depth_write_slot)) { - //PStatTimer timer(_draw_set_state_depth_write_pcollector); - do_issue_depth_write(); - _state_mask.set_bit(depth_write_slot); - } - - int fog_slot = FogAttrib::get_class_slot(); - if (_target_rs->get_attrib(fog_slot) != _state_rs->get_attrib(fog_slot) || - !_state_mask.get_bit(fog_slot)) { - //PStatTimer timer(_draw_set_state_fog_pcollector); - do_issue_fog(); - _state_mask.set_bit(fog_slot); - } - - int render_mode_slot = RenderModeAttrib::get_class_slot(); - if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) || - !_state_mask.get_bit(render_mode_slot)) { - //PStatTimer timer(_draw_set_state_render_mode_pcollector); - do_issue_render_mode(); - _state_mask.set_bit(render_mode_slot); - } - - int rescale_normal_slot = RescaleNormalAttrib::get_class_slot(); - if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) || - !_state_mask.get_bit(rescale_normal_slot)) { - //PStatTimer timer(_draw_set_state_rescale_normal_pcollector); - do_issue_rescale_normal(); - _state_mask.set_bit(rescale_normal_slot); - } - - int shade_model_slot = ShadeModelAttrib::get_class_slot(); - if (_target_rs->get_attrib(shade_model_slot) != _state_rs->get_attrib(shade_model_slot) || - !_state_mask.get_bit(shade_model_slot)) { - //PStatTimer timer(_draw_set_state_shade_model_pcollector); - do_issue_shade_model(); - _state_mask.set_bit(shade_model_slot); - } - - int transparency_slot = TransparencyAttrib::get_class_slot(); - int color_write_slot = ColorWriteAttrib::get_class_slot(); - int color_blend_slot = ColorBlendAttrib::get_class_slot(); - if (_target_rs->get_attrib(transparency_slot) != _state_rs->get_attrib(transparency_slot) || - _target_rs->get_attrib(color_write_slot) != _state_rs->get_attrib(color_write_slot) || - _target_rs->get_attrib(color_blend_slot) != _state_rs->get_attrib(color_blend_slot) || - !_state_mask.get_bit(transparency_slot) || - !_state_mask.get_bit(color_write_slot) || - !_state_mask.get_bit(color_blend_slot)) { - //PStatTimer timer(_draw_set_state_blending_pcollector); - do_issue_blending(); - _state_mask.set_bit(transparency_slot); - _state_mask.set_bit(color_write_slot); - _state_mask.set_bit(color_blend_slot); - } - - int texture_slot = TextureAttrib::get_class_slot(); - int tex_matrix_slot = TexMatrixAttrib::get_class_slot(); - int tex_gen_slot = TexGenAttrib::get_class_slot(); - if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) || - _target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) || - _target_rs->get_attrib(tex_gen_slot) != _state_rs->get_attrib(tex_gen_slot) || - !_state_mask.get_bit(texture_slot) || - !_state_mask.get_bit(tex_matrix_slot) || - !_state_mask.get_bit(tex_gen_slot)) { - //PStatTimer timer(_draw_set_state_texture_pcollector); - determine_target_texture(); - - // For some mysterious and disturbing reason, making this call - // here--which should have no effect--actually prevents the DX - // context from going awry. If this call is omitted, the DX - // context goes foobar when switching states and refuses to draw - // anything at all. I strongly suspect memory corruption - // somewhere, but can't locate it. - // _target_texture->filter_to_max(_max_texture_stages); - - do_issue_texture(); - - _state_texture = _target_texture; - _state_mask.set_bit(texture_slot); - _state_mask.set_bit(tex_matrix_slot); - _state_mask.set_bit(tex_gen_slot); - } - - int material_slot = MaterialAttrib::get_class_slot(); - if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) || - !_state_mask.get_bit(material_slot)) { - //PStatTimer timer(_draw_set_state_material_pcollector); - do_issue_material(); - _state_mask.set_bit(material_slot); - } - - int light_slot = LightAttrib::get_class_slot(); - if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) || - !_state_mask.get_bit(light_slot)) { - //PStatTimer timer(_draw_set_state_light_pcollector); - do_issue_light(); - _state_mask.set_bit(light_slot); - } - - int stencil_slot = StencilAttrib::get_class_slot(); - if (_target_rs->get_attrib(stencil_slot) != _state_rs->get_attrib(stencil_slot) || - !_state_mask.get_bit(stencil_slot)) { - //PStatTimer timer(_draw_set_state_stencil_pcollector); - do_issue_stencil(); - _state_mask.set_bit(stencil_slot); - } - - int scissor_slot = ScissorAttrib::get_class_slot(); - if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) || - !_state_mask.get_bit(scissor_slot)) { - //PStatTimer timer(_draw_set_state_scissor_pcollector); - do_issue_scissor(); - _state_mask.set_bit(scissor_slot); - } - - _state_rs = _target_rs; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::bind_light -// Access: Public, Virtual -// Description: Called the first time a particular light has been -// bound to a given id within a frame, this should set -// up the associated hardware light with the light's -// properties. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -bind_light(PointLight *light_obj, const NodePath &light, int light_id) { - // Get the light in "world coordinates" (actually, view - // coordinates). This means the light in the coordinate space of - // the camera, converted to DX's coordinate system. - CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path()); - const LMatrix4 &light_mat = transform->get_mat(); - LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default); - LPoint3f pos = LCAST(float, light_obj->get_point() * rel_mat); - - D3DCOLORVALUE black; - black.r = black.g = black.b = black.a = 0.0f; - D3DLIGHT8 alight; - alight.Type = D3DLIGHT_POINT; - alight.Diffuse = get_light_color(light_obj); - alight.Ambient = black ; - LColorf color = LCAST(float, light_obj->get_specular_color()); - alight.Specular = *(D3DCOLORVALUE *)(color.get_data()); - - // Position needs to specify x, y, z, and w - // w == 1 implies non-infinite position - alight.Position = *(D3DVECTOR *)pos.get_data(); - - alight.Range = __D3DLIGHT_RANGE_MAX; - alight.Falloff = 1.0f; - - const LVecBase3 &att = light_obj->get_attenuation(); - alight.Attenuation0 = att[0]; - alight.Attenuation1 = att[1]; - alight.Attenuation2 = att[2]; - - HRESULT hr = _d3d_device->SetLight(light_id, &alight); - if (FAILED(hr)) { - wdxdisplay8_cat.warning() - << "Could not set light properties for " << light - << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n"; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::bind_light -// Access: Public, Virtual -// Description: Called the first time a particular light has been -// bound to a given id within a frame, this should set -// up the associated hardware light with the light's -// properties. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) { - static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional"); - //PStatTimer timer(_draw_set_state_light_bind_directional_pcollector); - - pair lookup = _dlights.insert(DirectionalLights::value_type(light, D3DLIGHT8())); - D3DLIGHT8 &fdata = (*lookup.first).second; - if (lookup.second) { - // Get the light in "world coordinates" (actually, view - // coordinates). This means the light in the coordinate space of - // the camera, converted to DX's coordinate system. - CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path()); - const LMatrix4 &light_mat = transform->get_mat(); - LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default); - LVector3f dir = LCAST(float, light_obj->get_direction() * rel_mat); - - D3DCOLORVALUE black; - black.r = black.g = black.b = black.a = 0.0f; - - ZeroMemory(&fdata, sizeof(D3DLIGHT8)); - - fdata.Type = D3DLIGHT_DIRECTIONAL; - fdata.Ambient = black ; - LColorf color = LCAST(float, light_obj->get_specular_color()); - fdata.Specular = *(D3DCOLORVALUE *)(color.get_data()); - - fdata.Direction = *(D3DVECTOR *)dir.get_data(); - - fdata.Range = __D3DLIGHT_RANGE_MAX; - fdata.Falloff = 1.0f; - - fdata.Attenuation0 = 1.0f; // constant - fdata.Attenuation1 = 0.0f; // linear - fdata.Attenuation2 = 0.0f; // quadratic - } - - // We have to reset the Diffuse color at each call, because it might - // have changed independently of the light object itself (due to - // color_scale_via_lighting being in effect). - fdata.Diffuse = get_light_color(light_obj); - - HRESULT hr = _d3d_device->SetLight(light_id, &fdata); - if (FAILED(hr)) { - wdxdisplay8_cat.warning() - << "Could not set light properties for " << light - << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n"; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::bind_light -// Access: Public, Virtual -// Description: Called the first time a particular light has been -// bound to a given id within a frame, this should set -// up the associated hardware light with the light's -// properties. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -bind_light(Spotlight *light_obj, const NodePath &light, int light_id) { - Lens *lens = light_obj->get_lens(); - nassertv(lens != (Lens *)NULL); - - // Get the light in "world coordinates" (actually, view - // coordinates). This means the light in the coordinate space of - // the camera, converted to DX's coordinate system. - CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path()); - const LMatrix4 &light_mat = transform->get_mat(); - LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default); - LPoint3f pos = LCAST(float, lens->get_nodal_point() * rel_mat); - LVector3f dir = LCAST(float, lens->get_view_vector() * rel_mat); - - D3DCOLORVALUE black; - black.r = black.g = black.b = black.a = 0.0f; - - D3DLIGHT8 alight; - ZeroMemory(&alight, sizeof(D3DLIGHT8)); - - alight.Type = D3DLIGHT_SPOT; - alight.Ambient = black ; - alight.Diffuse = get_light_color(light_obj); - LColorf color = LCAST(float, light_obj->get_specular_color()); - alight.Specular = *(D3DCOLORVALUE *)(color.get_data()); - - alight.Position = *(D3DVECTOR *)pos.get_data(); - - alight.Direction = *(D3DVECTOR *)dir.get_data(); - - alight.Range = __D3DLIGHT_RANGE_MAX; - - // I determined this formular empirically. It seems to mostly - // approximate the OpenGL spotlight equation, for a reasonable range - // of values for FOV. - PN_stdfloat fov = lens->get_hfov(); - alight.Falloff = light_obj->get_exponent() * (fov * fov * fov) / 1620000.0f; - - alight.Theta = 0.0f; - alight.Phi = deg_2_rad(fov); - - const LVecBase3 &att = light_obj->get_attenuation(); - alight.Attenuation0 = att[0]; - alight.Attenuation1 = att[1]; - alight.Attenuation2 = att[2]; - - HRESULT hr = _d3d_device->SetLight(light_id, &alight); - if (FAILED(hr)) { - wdxdisplay8_cat.warning() - << "Could not set light properties for " << light - << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n"; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_index_type -// Access: Protected, Static -// Description: Maps from the Geom's internal numeric type symbols -// to DirectX's. -//////////////////////////////////////////////////////////////////// -D3DFORMAT DXGraphicsStateGuardian8:: -get_index_type(Geom::NumericType numeric_type) { - switch (numeric_type) { - case Geom::NT_uint16: - return D3DFMT_INDEX16; - - case Geom::NT_uint32: - return D3DFMT_INDEX32; - } - - dxgsg8_cat.error() - << "Invalid index NumericType value (" << (int)numeric_type << ")\n"; - return D3DFMT_INDEX16; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_material -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_material() { - static Material empty; - const Material *material; - const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot())); - if (target_material->is_off()) { - material = ∅ - } else { - material = target_material->get_material(); - } - - D3DMATERIAL8 cur_material; - LColorf color = LCAST(float, material->get_diffuse()); - cur_material.Diffuse = *(D3DCOLORVALUE *)(color.get_data()); - color = LCAST(float, material->get_ambient()); - cur_material.Ambient = *(D3DCOLORVALUE *)(color.get_data()); - color = LCAST(float, material->get_specular()); - cur_material.Specular = *(D3DCOLORVALUE *)(color.get_data()); - color = LCAST(float, material->get_emission()); - cur_material.Emissive = *(D3DCOLORVALUE *)(color.get_data()); - cur_material.Power = material->get_shininess(); - - if (material->has_diffuse()) { - // If the material specifies an diffuse color, use it. - _d3d_device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); - } else { - // Otherwise, the diffuse color comes from the object color. - if (_has_material_force_color) { - color = LCAST(float, _material_force_color); - cur_material.Diffuse = *(D3DCOLORVALUE *)color.get_data(); - _d3d_device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); - } else { - _d3d_device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); - } - } - if (material->has_ambient()) { - // If the material specifies an ambient color, use it. - _d3d_device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); - } else { - // Otherwise, the ambient color comes from the object color. - if (_has_material_force_color) { - color = LCAST(float, _material_force_color); - cur_material.Ambient = *(D3DCOLORVALUE *)color.get_data(); - _d3d_device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); - } else { - _d3d_device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); - } - } - - if (material->has_specular()) { - _d3d_device->SetRenderState(D3DRS_SPECULARENABLE, TRUE); - } else { - _d3d_device->SetRenderState(D3DRS_SPECULARENABLE, FALSE); - } - - if (material->get_local()) { - _d3d_device->SetRenderState(D3DRS_LOCALVIEWER, TRUE); - } else { - _d3d_device->SetRenderState(D3DRS_LOCALVIEWER, FALSE); - } - - _d3d_device->SetMaterial(&cur_material); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_texture -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_texture() { - DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1)); - - int num_stages = _target_texture->get_num_on_ff_stages(); - nassertv(num_stages <= _max_texture_stages && - _num_active_texture_stages <= _max_texture_stages); - - _texture_involves_color_scale = false; - - // We have to match up the texcoord stage index to the order written - // out by the DXGeomMunger. This means the texcoord names are - // written in the order indicated by the TextureAttrib. - - int si; - for (si = 0; si < num_stages; si++) { - TextureStage *stage = _target_texture->get_on_ff_stage(si); - int texcoord_index = _target_texture->get_ff_tc_index(si); - - Texture *texture = _target_texture->get_on_texture(stage); - nassertv(texture != (Texture *)NULL); - const SamplerState &sampler = _target_texture->get_on_sampler(stage); - - // We always reissue every stage in DX, just in case the texcoord - // index or texgen mode or some other property has changed. - TextureContext *tc = texture->prepare_now(0, _prepared_objects, this); - apply_texture(si, tc, sampler); - set_texture_blend_mode(si, stage); - - int texcoord_dimensions = 2; - - CPT(TransformState) tex_mat = TransformState::make_identity(); - const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); - if (target_tex_matrix->has_stage(stage)) { - tex_mat = target_tex_matrix->get_transform(stage); - } - - // Issue the texgen mode. - TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage); - bool any_point_sprite = false; - - switch (mode) { - case TexGenAttrib::M_off: - case TexGenAttrib::M_light_vector: - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, texcoord_index); - break; - - case TexGenAttrib::M_eye_sphere_map: - { - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, - texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); - // This texture matrix, applied on top of the texcoord - // computed by D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR, - // approximates the effect produced by OpenGL's GL_SPHERE_MAP. - static CPT(TransformState) sphere_map = - TransformState::make_mat(LMatrix4(0.33, 0.0f, 0.0f, 0.0f, - 0.0f, 0.33, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.0f, 1.0f)); - tex_mat = tex_mat->compose(sphere_map); - texcoord_dimensions = 3; - } - break; - - case TexGenAttrib::M_world_cube_map: - // To achieve world reflection vector, we must transform camera - // coordinates to world coordinates; i.e. apply the camera - // transform. In the case of a vector, we should not apply the - // pos component of the transform. - { - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, - texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); - texcoord_dimensions = 3; - CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); - tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3::zero())); - } - break; - - case TexGenAttrib::M_eye_cube_map: - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, - texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); - tex_mat = tex_mat->compose(_inv_cs_transform); - texcoord_dimensions = 3; - break; - - case TexGenAttrib::M_world_normal: - // To achieve world normal, we must transform camera coordinates - // to world coordinates; i.e. apply the camera transform. In - // the case of a normal, we should not apply the pos component - // of the transform. - { - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, - texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL); - texcoord_dimensions = 3; - CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); - tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3::zero())); - } - break; - - case TexGenAttrib::M_eye_normal: - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, - texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL); - texcoord_dimensions = 3; - tex_mat = tex_mat->compose(_inv_cs_transform); - break; - - case TexGenAttrib::M_world_position: - // To achieve world position, we must transform camera - // coordinates to world coordinates; i.e. apply the - // camera transform. - { - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, - texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION); - texcoord_dimensions = 3; - CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); - tex_mat = tex_mat->compose(camera_transform); - } - break; - - case TexGenAttrib::M_eye_position: - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, - texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION); - texcoord_dimensions = 3; - tex_mat = tex_mat->compose(_inv_cs_transform); - break; - - case TexGenAttrib::M_point_sprite: - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, texcoord_index); - any_point_sprite = true; - break; - - case TexGenAttrib::M_constant: - // To generate a constant UV(w) coordinate everywhere, we use - // CAMERASPACEPOSITION coordinates, but we construct a special - // matrix that flattens the existing values to zero and then - // adds our desired value. - - // The only reason we need to specify CAMERASPACEPOSITION at - // all, instead of using whatever texture coordinates (if any) - // happen to be on the vertices, is because we need to guarantee - // that there are 3-d texture coordinates, because of the - // 3-component texture coordinate in get_constant_value(). - { - _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, - texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION); - texcoord_dimensions = 3; - - const LTexCoord3 &v = _target_tex_gen->get_constant_value(stage); - CPT(TransformState) squash = - TransformState::make_pos_hpr_scale(v, LVecBase3::zero(), - LVecBase3::zero()); - tex_mat = tex_mat->compose(squash); - } - break; - } - - _d3d_device->SetRenderState(D3DRS_POINTSPRITEENABLE, any_point_sprite); - - if (!tex_mat->is_identity()) { - if (/*tex_mat->is_2d() &&*/ texcoord_dimensions <= 2) { - // For 2-d texture coordinates, we have to reorder the matrix. - LMatrix4 m = tex_mat->get_mat(); - LMatrix4f mf; - mf.set(m(0, 0), m(0, 1), m(0, 3), 0.0f, - m(1, 0), m(1, 1), m(1, 3), 0.0f, - m(3, 0), m(3, 1), m(3, 3), 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); - _d3d_device->SetTransform(get_tex_mat_sym(si), (D3DMATRIX *)mf.get_data()); - _d3d_device->SetTextureStageState(si, D3DTSS_TEXTURETRANSFORMFLAGS, - D3DTTFF_COUNT2); - } else { - LMatrix4f m = LCAST(float, tex_mat->get_mat()); - _d3d_device->SetTransform(get_tex_mat_sym(si), (D3DMATRIX *)m.get_data()); - DWORD transform_flags = texcoord_dimensions; - if (m.get_col(3) != LVecBase4(0.0f, 0.0f, 0.0f, 1.0f)) { - // If we have a projected texture matrix, we also need to - // set D3DTTFF_COUNT4. - transform_flags = D3DTTFF_COUNT4 | D3DTTFF_PROJECTED; - } - _d3d_device->SetTextureStageState(si, D3DTSS_TEXTURETRANSFORMFLAGS, - transform_flags); - } - - } else { - _d3d_device->SetTextureStageState(si, D3DTSS_TEXTURETRANSFORMFLAGS, - D3DTTFF_DISABLE); - // For some reason, "disabling" texture coordinate transforms - // doesn't seem to be sufficient. We'll load an identity matrix - // to underscore the point. - _d3d_device->SetTransform(get_tex_mat_sym(si), &_d3d_ident_mat); - } - } - - // Disable the texture stages that are no longer used. - for (si = num_stages; si < _num_active_texture_stages; si++) { - _d3d_device->SetTextureStageState(si, D3DTSS_COLOROP, D3DTOP_DISABLE); - } - - // Save the count of texture stages for next time. - _num_active_texture_stages = num_stages; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::reissue_transforms -// Access: Protected, Virtual -// Description: Called by clear_state_and_transform() to ensure that -// the current modelview and projection matrices are -// properly loaded in the graphics state, after a -// callback might have mucked them up. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -reissue_transforms() { - prepare_lens(); - do_issue_transform(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::enable_lighting -// Access: Protected, Virtual -// Description: Intended to be overridden by a derived class to -// enable or disable the use of lighting overall. This -// is called by issue_light() according to whether any -// lights are in use or not. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -enable_lighting(bool enable) { - _d3d_device->SetRenderState(D3DRS_LIGHTING, (DWORD)enable); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_ambient_light -// Access: Protected, Virtual -// Description: Intended to be overridden by a derived class to -// indicate the color of the ambient light that should -// be in effect. This is called by issue_light() after -// all other lights have been enabled or disabled. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -set_ambient_light(const LColor &color) { - LColor c = color; - c.set(c[0] * _light_color_scale[0], - c[1] * _light_color_scale[1], - c[2] * _light_color_scale[2], - c[3] * _light_color_scale[3]); - - _d3d_device->SetRenderState(D3DRS_AMBIENT, LColor_to_D3DCOLOR(c)); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::enable_light -// Access: Protected, Virtual -// Description: Intended to be overridden by a derived class to -// enable the indicated light id. A specific Light will -// already have been bound to this id via bind_light(). -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -enable_light(int light_id, bool enable) { - HRESULT hr = _d3d_device->LightEnable(light_id, enable); - - if (FAILED(hr)) { - wdxdisplay8_cat.warning() - << "Could not enable light " << light_id << ": " - << D3DERRORSTRING(hr) << "\n"; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::enable_clip_plane -// Access: Protected, Virtual -// Description: Intended to be overridden by a derived class to -// enable the indicated clip_plane id. A specific -// PlaneNode will already have been bound to this id via -// bind_clip_plane(). -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -enable_clip_plane(int plane_id, bool enable) { - if (enable) { - _clip_plane_bits |= ((DWORD)1 << plane_id); - } else { - _clip_plane_bits &= ~((DWORD)1 << plane_id); - } - _d3d_device->SetRenderState(D3DRS_CLIPPLANEENABLE, _clip_plane_bits); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::bind_clip_plane -// Access: Protected, Virtual -// Description: Called the first time a particular clip_plane has been -// bound to a given id within a frame, this should set -// up the associated hardware clip_plane with the clip_plane's -// properties. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -bind_clip_plane(const NodePath &plane, int plane_id) { - // Get the plane in "world coordinates" (actually, view - // coordinates). This means the plane in the coordinate space of - // the camera, converted to DX's coordinate system. - CPT(TransformState) transform = plane.get_transform(_scene_setup->get_camera_path()); - const LMatrix4 &plane_mat = transform->get_mat(); - LMatrix4 rel_mat = plane_mat * LMatrix4::convert_mat(CS_yup_left, CS_default); - const PlaneNode *plane_node; - DCAST_INTO_V(plane_node, plane.node()); - LPlanef world_plane = LCAST(float, plane_node->get_plane() * rel_mat); - - HRESULT hr = _d3d_device->SetClipPlane(plane_id, world_plane.get_data()); - if (FAILED(hr)) { - wdxdisplay8_cat.warning() - << "Could not set clip plane for " << plane - << " to id " << plane_id << ": " << D3DERRORSTRING(hr) << "\n"; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_blend_mode -// Access: Protected, Virtual -// Description: Called after any of the things that might change -// blending state have changed, this function is -// responsible for setting the appropriate color -// blending mode based on the current properties. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_blending() { - - // Handle the color_write attrib. If color_write is off, then - // all the other blending-related stuff doesn't matter. If the - // device doesn't support color-write, we use blending tricks - // to effectively disable color write. - const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot())); - unsigned int color_channels = - target_color_write->get_channels() & _color_write_mask; - if (color_channels == ColorWriteAttrib::C_off) { - if (_screen->_can_direct_disable_color_writes) { - _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)0x0); - } else { - _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - _d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); - _d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - } - return; - } - - if (_screen->_can_direct_disable_color_writes) { - _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, color_channels); - } - - const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot())); - ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode(); - - const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot())); - TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode(); - - // Is there a color blend set? - if (color_blend_mode != ColorBlendAttrib::M_none) { - _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - switch (color_blend_mode) { - case ColorBlendAttrib::M_add: - _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - break; - - case ColorBlendAttrib::M_subtract: - _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT); - break; - - case ColorBlendAttrib::M_inv_subtract: - _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); - break; - - case ColorBlendAttrib::M_min: - _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN); - break; - - case ColorBlendAttrib::M_max: - _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX); - break; - } - - _d3d_device->SetRenderState(D3DRS_SRCBLEND, - get_blend_func(target_color_blend->get_operand_a())); - _d3d_device->SetRenderState(D3DRS_DESTBLEND, - get_blend_func(target_color_blend->get_operand_b())); - return; - } - - // No color blend; is there a transparency set? - switch (transparency_mode) { - case TransparencyAttrib::M_none: - case TransparencyAttrib::M_binary: - break; - - case TransparencyAttrib::M_alpha: - case TransparencyAttrib::M_multisample: - case TransparencyAttrib::M_multisample_mask: - case TransparencyAttrib::M_dual: - _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - _d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - _d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - return; - - default: - dxgsg8_cat.error() - << "invalid transparency mode " << (int)transparency_mode << endl; - break; - } - - // Nothing's set, so disable blending. - _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::close_gsg -// Access: Protected, Virtual -// Description: This is called by the associated GraphicsWindow when -// close_window() is called. It should null out the -// _win pointer and possibly free any open resources -// associated with the GSG. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -close_gsg() { - GraphicsStateGuardian::close_gsg(); - - // Unlike in OpenGL, in DX8 it is safe to try to explicitly release - // any textures here. And it may even be a good idea. - if (_prepared_objects->get_ref_count() == 1) { - release_all(); - - // Now we need to actually delete all of the objects we just - // released. - Thread *current_thread = Thread::get_current_thread(); - _prepared_objects->begin_frame(this, current_thread); - _prepared_objects->end_frame(current_thread); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::free_nondx_resources -// Access: Public -// Description: Frees some memory that was explicitly allocated -// within the dxgsg. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -free_nondx_resources() { -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::free_d3d_device -// Access: Public -// Description: setup for re-calling dx_init(), this is not the final -// exit cleanup routine (see dx_cleanup) -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -free_d3d_device() { - // don't want a full reset of gsg, just a state clear - _state_rs = RenderState::make_empty(); - _state_mask.clear(); - - // want gsg to pass all state settings through - - _dx_is_ready = false; - - if (_d3d_device != NULL) - for(int i = 0;iSetTexture(i, NULL); // d3d should release this stuff internally anyway, but whatever - - release_all(); - - if (_d3d_device != NULL) - RELEASE(_d3d_device, dxgsg8, "d3dDevice", RELEASE_DOWN_TO_ZERO); - - free_nondx_resources(); - - // obviously we don't release ID3D8, just ID3DDevice8 -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_draw_buffer -// Access: Protected -// Description: Sets up the glDrawBuffer to render into the buffer -// indicated by the RenderBuffer object. This only sets -// up the color bits; it does not affect the depth, -// stencil, accum layers. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -set_draw_buffer(const RenderBuffer &rb) { - dxgsg8_cat.fatal() << "DX set_draw_buffer unimplemented!!!"; - return; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_read_buffer -// Access: Protected -// Description: Vestigial analog of glReadBuffer -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -set_read_buffer(const RenderBuffer &rb) { - if (rb._buffer_type & RenderBuffer::T_front) { - _cur_read_pixel_buffer = RenderBuffer::T_front; - } else if (rb._buffer_type & RenderBuffer::T_back) { - _cur_read_pixel_buffer = RenderBuffer::T_back; - } else { - dxgsg8_cat.error() << "Invalid or unimplemented Argument to set_read_buffer!\n"; - } - return; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_auto_rescale_normal -// Access: Protected -// Description: Issues the appropriate GL commands to either rescale -// or normalize the normals according to the current -// transform. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_auto_rescale_normal() { - if (_internal_transform->has_identity_scale()) { - // If there's no scale, don't normalize anything. - _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, false); - - } else { - // If there is a scale, turn on normalization. - _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, true); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::get_light_color -// Access: Public -// Description: Returns the array of four floats that should be -// issued as the light's color, as scaled by the current -// value of _light_color_scale, in the case of -// color_scale_via_lighting. -//////////////////////////////////////////////////////////////////// -const D3DCOLORVALUE &DXGraphicsStateGuardian8:: -get_light_color(Light *light) const { - LColor c = light->get_color(); - static LColorf cf; - cf.set(c[0] * _light_color_scale[0], - c[1] * _light_color_scale[1], - c[2] * _light_color_scale[2], - c[3] * _light_color_scale[3]); - return *(D3DCOLORVALUE *)cf.get_data(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_blend_func -// Access: Protected, Static -// Description: Maps from ColorBlendAttrib::Operand to D3DBLEND -// value. -//////////////////////////////////////////////////////////////////// -D3DBLEND DXGraphicsStateGuardian8:: -get_blend_func(ColorBlendAttrib::Operand operand) { - switch (operand) { - case ColorBlendAttrib::O_zero: - return D3DBLEND_ZERO; - - case ColorBlendAttrib::O_one: - return D3DBLEND_ONE; - - case ColorBlendAttrib::O_incoming_color: - return D3DBLEND_SRCCOLOR; - - case ColorBlendAttrib::O_one_minus_incoming_color: - return D3DBLEND_INVSRCCOLOR; - - case ColorBlendAttrib::O_fbuffer_color: - return D3DBLEND_DESTCOLOR; - - case ColorBlendAttrib::O_one_minus_fbuffer_color: - return D3DBLEND_INVDESTCOLOR; - - case ColorBlendAttrib::O_incoming_alpha: - return D3DBLEND_SRCALPHA; - - case ColorBlendAttrib::O_one_minus_incoming_alpha: - return D3DBLEND_INVSRCALPHA; - - case ColorBlendAttrib::O_fbuffer_alpha: - return D3DBLEND_DESTALPHA; - - case ColorBlendAttrib::O_one_minus_fbuffer_alpha: - return D3DBLEND_INVDESTALPHA; - - case ColorBlendAttrib::O_constant_color: - // Not supported by DX. - return D3DBLEND_SRCCOLOR; - - case ColorBlendAttrib::O_one_minus_constant_color: - // Not supported by DX. - return D3DBLEND_INVSRCCOLOR; - - case ColorBlendAttrib::O_constant_alpha: - // Not supported by DX. - return D3DBLEND_SRCALPHA; - - case ColorBlendAttrib::O_one_minus_constant_alpha: - // Not supported by DX. - return D3DBLEND_INVSRCALPHA; - - case ColorBlendAttrib::O_incoming_color_saturate: - return D3DBLEND_SRCALPHASAT; - } - - dxgsg8_cat.error() - << "Unknown color blend operand " << (int)operand << endl; - return D3DBLEND_ZERO; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::report_texmgr_stats -// Access: Protected -// Description: Reports the DX texture manager's activity to PStats. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -report_texmgr_stats() { - -#ifdef DO_PSTATS - HRESULT hr; -#ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM - DWORD dwTexTotal, dwTexFree, dwVidTotal, dwVidFree; - - if (_total_texmem_pcollector.is_active()) { - DDSCAPS2 ddsCaps; - - ZeroMemory(&ddsCaps, sizeof(ddsCaps)); - - ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; - if (FAILED( hr = _d3d_device->GetAvailableVidMem(&ddsCaps, &dwVidTotal, &dwVidFree))) { - dxgsg8_cat.fatal() << "report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << D3DERRORSTRING(hr); - throw_event("panda3d-render-error"); - return; - } - - ddsCaps.dwCaps = DDSCAPS_TEXTURE; - if (FAILED( hr = _d3d_device->GetAvailableVidMem(&ddsCaps, &dwTexTotal, &dwTexFree))) { - dxgsg8_cat.fatal() << "report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << D3DERRORSTRING(hr); - throw_event("panda3d-render-error"); - return; - } - } -#endif // TEXMGRSTATS_USES_GETAVAILVIDMEM - - D3DDEVINFO_RESOURCEMANAGER all_resource_stats; - ZeroMemory(&all_resource_stats, sizeof(D3DDEVINFO_RESOURCEMANAGER)); - - if (!_tex_stats_retrieval_impossible) { - hr = _d3d_device->GetInfo(D3DDEVINFOID_RESOURCEMANAGER, &all_resource_stats, sizeof(D3DDEVINFO_RESOURCEMANAGER)); - if (hr != D3D_OK) { - if (hr == S_FALSE) { - static int PrintedMsg = 2; - if (PrintedMsg>0) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "texstats GetInfo() requires debug DX DLLs to be installed!!\n"; - } - ZeroMemory(&all_resource_stats, sizeof(D3DDEVINFO_RESOURCEMANAGER)); - _tex_stats_retrieval_impossible = true; - } - } else { - dxgsg8_cat.error() << "GetInfo(RESOURCEMANAGER) failed to get tex stats: result = " << D3DERRORSTRING(hr); - return; - } - } - } - - // Tell PStats about the state of the texture memory. - - if (_texmgrmem_total_pcollector.is_active()) { - // report zero if no debug dlls, to signal this info is invalid - _texmgrmem_total_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].TotalBytes); - _texmgrmem_resident_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].WorkingSetBytes); - } -#ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM - if (_total_texmem_pcollector.is_active()) { - _total_texmem_pcollector.set_level(dwTexTotal); - _used_texmem_pcollector.set_level(dwTexTotal - dwTexFree); - } -#endif // TEXMGRSTATS_USES_GETAVAILVIDMEM -#endif // DO_PSTATS -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_context -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -set_context(DXScreenData *new_context) { - nassertv(new_context != NULL); - _screen = new_context; - _d3d_device = _screen->_d3d_device; //copy this one field for speed of deref - _swap_chain = _screen->_swap_chain; //copy this one field for speed of deref - - _screen->_dxgsg8 = this; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_render_target -// Access: Protected -// Description: Set render target to the backbuffer of current swap -// chain. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -set_render_target() { - if (_d3d_device == NULL) { - return; - } - - LPDIRECT3DSURFACE8 back = NULL, stencil = NULL; - - if (!_swap_chain) //maybe fullscreen mode or main/single window - _d3d_device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back); - else - _swap_chain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back); - - //wdxdisplay8_cat.debug() << "swapchain is " << _swap_chain << "\n"; - //wdxdisplay8_cat.debug() << "back buffer is " << back << "\n"; - - _d3d_device->GetDepthStencilSurface(&stencil); - _d3d_device->SetRenderTarget(back, stencil); - if (back) { - back->Release(); - } - if (stencil) { - stencil->Release(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_texture_blend_mode -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -set_texture_blend_mode(int i, const TextureStage *stage) { - switch (stage->get_mode()) { - case TextureStage::M_modulate: - case TextureStage::M_modulate_glow: - case TextureStage::M_modulate_gloss: - // emulates GL_MODULATE glTexEnv mode - _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT); - break; - - case TextureStage::M_decal: - // emulates GL_DECAL glTexEnv mode - _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); - - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - break; - - case TextureStage::M_replace: - _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); - - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - break; - - case TextureStage::M_add: - _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_ADD); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); - - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT); - break; - - case TextureStage::M_blend: - case TextureStage::M_blend_color_scale: - { - _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_LERP); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_TEXTURE); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); - _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TFACTOR); - - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT); - } - break; - - case TextureStage::M_combine: - // M_combine mode begins a collection of more sophisticated modes, - // which match up more closely with DirectX's built-in modes. - _d3d_device->SetTextureStageState - (i, D3DTSS_COLOROP, - get_texture_operation(stage->get_combine_rgb_mode(), - stage->get_rgb_scale())); - - switch (stage->get_num_combine_rgb_operands()) { - case 3: - _d3d_device->SetTextureStageState - (i, D3DTSS_COLORARG0, - get_texture_argument(stage->get_combine_rgb_source2(), - stage->get_combine_rgb_operand2())); - // fall through - - case 2: - _d3d_device->SetTextureStageState - (i, D3DTSS_COLORARG2, - get_texture_argument(stage->get_combine_rgb_source1(), - stage->get_combine_rgb_operand1())); - // fall through - - case 1: - _d3d_device->SetTextureStageState - (i, D3DTSS_COLORARG1, - get_texture_argument(stage->get_combine_rgb_source0(), - stage->get_combine_rgb_operand0())); - // fall through - - default: - break; - } - - _d3d_device->SetTextureStageState - (i, D3DTSS_ALPHAOP, - get_texture_operation(stage->get_combine_alpha_mode(), - stage->get_alpha_scale())); - - switch (stage->get_num_combine_alpha_operands()) { - case 3: - _d3d_device->SetTextureStageState - (i, D3DTSS_ALPHAARG0, - get_texture_argument(stage->get_combine_alpha_source2(), - stage->get_combine_alpha_operand2())); - // fall through - - case 2: - _d3d_device->SetTextureStageState - (i, D3DTSS_ALPHAARG2, - get_texture_argument(stage->get_combine_alpha_source1(), - stage->get_combine_alpha_operand1())); - // fall through - - case 1: - _d3d_device->SetTextureStageState - (i, D3DTSS_ALPHAARG1, - get_texture_argument(stage->get_combine_alpha_source0(), - stage->get_combine_alpha_operand0())); - // fall through - - default: - break; - } - break; - - default: - dxgsg8_cat.error() - << "Unknown texture mode " << (int)stage->get_mode() << endl; - break; - } - - if (stage->get_saved_result()) { - _d3d_device->SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_TEMP); - } else { - _d3d_device->SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT); - } - - if (stage->uses_color()) { - // Set up the constant color for this stage. - - // Actually, DX8 doesn't support a per-stage constant color, but - // it does support one TEXTUREFACTOR color for the whole pipeline. - // This does mean you can't have two different blends in effect - // with different colors on the same object. However, DX9 does - // support a per-stage constant color with the D3DTA_CONSTANT - // argument--so we should implement that when this code gets - // ported to DX9. - - D3DCOLOR texture_factor; - if (stage->involves_color_scale() && _color_scale_enabled) { - LColor color = stage->get_color(); - color.set(color[0] * _current_color_scale[0], - color[1] * _current_color_scale[1], - color[2] * _current_color_scale[2], - color[3] * _current_color_scale[3]); - _texture_involves_color_scale = true; - texture_factor = LColor_to_D3DCOLOR(color); - } else { - texture_factor = LColor_to_D3DCOLOR(stage->get_color()); - } - _d3d_device->SetRenderState(D3DRS_TEXTUREFACTOR, texture_factor); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::dx_cleanup -// Access: Protected -// Description: Clean up the DirectX environment, accounting for exit() -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -dx_cleanup() { - if (!_d3d_device) { - return; - } - - free_nondx_resources(); - PRINT_REFCNT(dxgsg8, _d3d_device); - - // Do a safe check for releasing the D3DDEVICE. RefCount should be zero. - // if we're called from exit(), _d3d_device may already have been released - RELEASE(_d3d_device, dxgsg8, "d3dDevice", RELEASE_DOWN_TO_ZERO); - _screen->_d3d_device = NULL; - - // Releasing pD3D is now the responsibility of the GraphicsPipe destructor -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::reset_d3d_device -// Access: Protected -// Description: This function checks current device's framebuffer -// dimension against passed p_presentation_params backbuffer -// dimension to determine a device reset if there is -// only one window or it is the main window or -// fullscreen mode then, it resets the device. Finally -// it returns the new DXScreenData through parameter -// screen -//////////////////////////////////////////////////////////////////// -HRESULT DXGraphicsStateGuardian8:: -reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, - DXScreenData **screen) { - HRESULT hr; - - nassertr(IS_VALID_PTR(presentation_params), E_FAIL); - nassertr(IS_VALID_PTR(_screen->_d3d8), E_FAIL); - nassertr(IS_VALID_PTR(_d3d_device), E_FAIL); - - // for windowed mode make sure our format matches the desktop fmt, - // in case the desktop mode has been changed - _screen->_d3d8->GetAdapterDisplayMode(_screen->_card_id, &_screen->_display_mode); - presentation_params->BackBufferFormat = _screen->_display_mode.Format; - - // here we have to look at the _presentation_reset frame buffer dimension - // if current window's dimension is bigger than _presentation_reset - // we have to reset the device before creating new swapchain. - // inorder to reset properly, we need to release all swapchains - - if (true || !(_screen->_swap_chain) - || (_presentation_reset.BackBufferWidth < presentation_params->BackBufferWidth) - || (_presentation_reset.BackBufferHeight < presentation_params->BackBufferHeight)) { - if (wdxdisplay8_cat.is_debug()) { - wdxdisplay8_cat.debug() - << "swap_chain = " << _screen->_swap_chain << " _presentation_reset = " - << _presentation_reset.BackBufferWidth << "x" << _presentation_reset.BackBufferHeight - << " presentation_params = " - << presentation_params->BackBufferWidth << "x" << presentation_params->BackBufferHeight << "\n"; - } - - get_engine()->reset_all_windows(false);// reset old swapchain by releasing - - if (_screen->_swap_chain) { //other windows might be using bigger buffers - _presentation_reset.BackBufferWidth = max(_presentation_reset.BackBufferWidth, presentation_params->BackBufferWidth); - _presentation_reset.BackBufferHeight = max(_presentation_reset.BackBufferHeight, presentation_params->BackBufferHeight); - - } else { // single window, must reset to the new presentation_params dimension - _presentation_reset.BackBufferWidth = presentation_params->BackBufferWidth; - _presentation_reset.BackBufferHeight = presentation_params->BackBufferHeight; - } - - // Calling this forces all of the textures and vbuffers to be - // regenerated, a prerequisite to calling Reset(). Actually, this - // shouldn't be necessary, because all of our textures and - // vbuffers are stored in the D3DPOOL_MANAGED memory class. - release_all(); - - // Just to be extra-conservative for now, we'll go ahead and - // release the vbuffers and ibuffers at least; they're relatively - // cheap to replace. - release_all_vertex_buffers(); - release_all_index_buffers(); - - Thread *current_thread = Thread::get_current_thread(); - _prepared_objects->begin_frame(this, current_thread); - - // release graphics buffer surfaces - { - wdxGraphicsBuffer8 *graphics_buffer; - list ::iterator graphics_buffer_iterator; - - for (graphics_buffer_iterator = _graphics_buffer_list.begin( ); graphics_buffer_iterator != _graphics_buffer_list.end( ); graphics_buffer_iterator++) - { - graphics_buffer = **graphics_buffer_iterator; - if (graphics_buffer -> _color_backing_store) - { - graphics_buffer -> _color_backing_store -> Release ( ); - graphics_buffer -> _color_backing_store = 0; - } - if (graphics_buffer -> _depth_backing_store) - { - graphics_buffer -> _depth_backing_store -> Release ( ); - graphics_buffer -> _depth_backing_store = 0; - } - } - } - - this -> mark_new(); - hr = _d3d_device->Reset(&_presentation_reset); - if (FAILED(hr)) { - return hr; - } - - get_engine()->reset_all_windows(true);// reset with new swapchains by creating - if (screen) { - *screen = NULL; - } - - if (presentation_params != &_screen->_presentation_params) { - memcpy(&_screen->_presentation_params, presentation_params, sizeof(D3DPRESENT_PARAMETERS)); - } - - return hr; - } - - // release the old swapchain and create a new one - if (_screen && _screen->_swap_chain) { - _screen->_swap_chain->Release(); - wdxdisplay8_cat.debug() - << "swap chain " << _screen->_swap_chain << " is released\n"; - _screen->_swap_chain = NULL; - hr = _d3d_device->CreateAdditionalSwapChain(presentation_params, &_screen->_swap_chain); - } - if (SUCCEEDED(hr)) { - if (presentation_params != &_screen->_presentation_params) { - memcpy(&_screen->_presentation_params, presentation_params, sizeof(D3DPRESENT_PARAMETERS)); - } - if (screen) { - *screen = _screen; - } - } - return hr; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::check_cooperative_level -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -check_cooperative_level() { - bool bDoReactivateWindow = false; - if (_d3d_device == NULL) { - return false; - } - HRESULT hr = _d3d_device->TestCooperativeLevel(); - - if (SUCCEEDED(hr)) { - nassertr(SUCCEEDED(_last_testcooplevel_result), false); - return true; - } - - switch (hr) { - case D3DERR_DEVICENOTRESET: - _dx_is_ready = false; - - // call this just in case - _prepared_objects->begin_frame(this, Thread::get_current_thread()); - - hr = reset_d3d_device(&_screen->_presentation_params); - if (FAILED(hr)) { - // I think this shouldnt fail unless I've screwed up the - // _presentation_params from the original working ones somehow - dxgsg8_cat.error() - << "check_cooperative_level Reset() failed, hr = " << D3DERRORSTRING(hr); - } - - hr = _d3d_device->TestCooperativeLevel(); - if (FAILED(hr)) { - // internal chk, shouldnt fail - dxgsg8_cat.error() - << "TestCooperativeLevel following Reset() failed, hr = " << D3DERRORSTRING(hr); - - } - - _dx_is_ready = TRUE; - break; - - case D3DERR_DEVICELOST: - // sleep while the device is lost to free up the CPU - Sleep (10); - - if (SUCCEEDED(_last_testcooplevel_result)) { - if (_dx_is_ready) { - _dx_is_ready = false; - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() << "D3D Device was Lost, waiting...\n"; - } - } - } - } - - _last_testcooplevel_result = hr; - return SUCCEEDED(hr); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::show_frame -// Access: Protected -// Description: redraw primary buffer -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -show_frame() { - if (_d3d_device == NULL) { - return; - } - - HRESULT hr; - - if (_swap_chain) { - hr = _swap_chain->Present((CONST RECT*)NULL, (CONST RECT*)NULL, (HWND)NULL, NULL); - } else { - hr = _d3d_device->Present((CONST RECT*)NULL, (CONST RECT*)NULL, (HWND)NULL, NULL); - } - - if (FAILED(hr)) { - if (hr == D3DERR_DEVICELOST) { - check_cooperative_level(); - } else { - dxgsg8_cat.error() - << "show_frame() - Present() failed" << D3DERRORSTRING(hr); - throw_event("panda3d-render-error"); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::create_swap_chain -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -create_swap_chain(DXScreenData *new_context) { - // Instead of creating a device and rendering as d3ddevice->present() - // we should render using SwapChain->present(). This is done to support - // multiple windows rendering. For that purpose, we need to set additional - // swap chains here. - - HRESULT hr; - hr = new_context->_d3d_device->CreateAdditionalSwapChain(&new_context->_presentation_params, &new_context->_swap_chain); - if (FAILED(hr)) { - wdxdisplay8_cat.debug() << "Swapchain creation failed :"<_swap_chain << "\n"; - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::release_swap_chain -// Access: Protected -// Description: Release the swap chain on this DXScreenData -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -release_swap_chain(DXScreenData *new_context) { - HRESULT hr; - wdxdisplay8_cat.debug() - << "Releasing swap chain " << new_context->_swap_chain << "\n"; - if (new_context->_swap_chain) { - hr = new_context->_swap_chain->Release(); - if (FAILED(hr)) { - wdxdisplay8_cat.debug() << "Swapchain release failed:" << D3DERRORSTRING(hr) << "\n"; - return false; - } - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::copy_pres_reset -// Access: Protected -// Description: copies the PresReset from passed DXScreenData -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -copy_pres_reset(DXScreenData *screen) { - memcpy(&_presentation_reset, &_screen->_presentation_params, sizeof(D3DPRESENT_PARAMETERS)); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_d3d_min_type -// Access: Protected, Static -// Description: -//////////////////////////////////////////////////////////////////// -D3DTEXTUREFILTERTYPE DXGraphicsStateGuardian8:: -get_d3d_min_type(SamplerState::FilterType filter_type) { - switch (filter_type) { - case SamplerState::FT_nearest: - return D3DTEXF_POINT; - - case SamplerState::FT_linear: - return D3DTEXF_LINEAR; - - case SamplerState::FT_nearest_mipmap_nearest: - return D3DTEXF_POINT; - - case SamplerState::FT_linear_mipmap_nearest: - return D3DTEXF_LINEAR; - - case SamplerState::FT_nearest_mipmap_linear: - return D3DTEXF_POINT; - - case SamplerState::FT_linear_mipmap_linear: - return D3DTEXF_LINEAR; - - case SamplerState::FT_shadow: - case SamplerState::FT_default: - return D3DTEXF_LINEAR; - } - - dxgsg8_cat.error() - << "Invalid FilterType value (" << (int)filter_type << ")\n"; - return D3DTEXF_POINT; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_d3d_mip_type -// Access: Protected, Static -// Description: -//////////////////////////////////////////////////////////////////// -D3DTEXTUREFILTERTYPE DXGraphicsStateGuardian8:: -get_d3d_mip_type(SamplerState::FilterType filter_type) { - switch (filter_type) { - case SamplerState::FT_nearest: - return D3DTEXF_NONE; - - case SamplerState::FT_linear: - return D3DTEXF_NONE; - - case SamplerState::FT_nearest_mipmap_nearest: - return D3DTEXF_POINT; - - case SamplerState::FT_linear_mipmap_nearest: - return D3DTEXF_POINT; - - case SamplerState::FT_nearest_mipmap_linear: - return D3DTEXF_LINEAR; - - case SamplerState::FT_linear_mipmap_linear: - return D3DTEXF_LINEAR; - - case SamplerState::FT_shadow: - case SamplerState::FT_default: - return D3DTEXF_NONE; - } - - dxgsg8_cat.error() - << "Invalid FilterType value (" << (int)filter_type << ")\n"; - return D3DTEXF_NONE; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_texture_operation -// Access: Protected, Static -// Description: Returns the D3DTEXTUREOP value corresponding to the -// indicated TextureStage::CombineMode enumerated type. -//////////////////////////////////////////////////////////////////// -D3DTEXTUREOP DXGraphicsStateGuardian8:: -get_texture_operation(TextureStage::CombineMode mode, int scale) { - switch (mode) { - case TextureStage::CM_undefined: - case TextureStage::CM_replace: - return D3DTOP_SELECTARG1; - - case TextureStage::CM_modulate: - if (scale < 2) { - return D3DTOP_MODULATE; - } else if (scale < 4) { - return D3DTOP_MODULATE2X; - } else { - return D3DTOP_MODULATE4X; - } - - case TextureStage::CM_add: - return D3DTOP_ADD; - - case TextureStage::CM_add_signed: - if (scale < 2) { - return D3DTOP_ADDSIGNED; - } else { - return D3DTOP_ADDSIGNED2X; - } - - case TextureStage::CM_interpolate: - return D3DTOP_LERP; - - case TextureStage::CM_subtract: - return D3DTOP_SUBTRACT; - - case TextureStage::CM_dot3_rgb: - case TextureStage::CM_dot3_rgba: - return D3DTOP_DOTPRODUCT3; - } - - dxgsg8_cat.error() - << "Invalid TextureStage::CombineMode value (" << (int)mode << ")\n"; - return D3DTOP_DISABLE; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_texture_argument -// Access: Protected, Static -// Description: Returns the D3DTA value corresponding to the -// indicated TextureStage::CombineSource and -// TextureStage::CombineOperand enumerated types. -//////////////////////////////////////////////////////////////////// -DWORD DXGraphicsStateGuardian8:: -get_texture_argument(TextureStage::CombineSource source, - TextureStage::CombineOperand operand) { - switch (source) { - case TextureStage::CS_undefined: - case TextureStage::CS_texture: - return D3DTA_TEXTURE | get_texture_argument_modifier(operand); - - case TextureStage::CS_constant: - case TextureStage::CS_constant_color_scale: - return D3DTA_TFACTOR | get_texture_argument_modifier(operand); - - case TextureStage::CS_primary_color: - return D3DTA_DIFFUSE | get_texture_argument_modifier(operand); - - case TextureStage::CS_previous: - return D3DTA_CURRENT | get_texture_argument_modifier(operand); - - case TextureStage::CS_last_saved_result: - return D3DTA_TEMP | get_texture_argument_modifier(operand); - } - dxgsg8_cat.error() - << "Invalid TextureStage::CombineSource value (" << (int)source << ")\n"; - return D3DTA_CURRENT; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_texture_argument_modifier -// Access: Protected, Static -// Description: Returns the extra bits that modify the D3DTA -// argument, according to the indicated -// TextureStage::CombineOperand enumerated type. -//////////////////////////////////////////////////////////////////// -DWORD DXGraphicsStateGuardian8:: -get_texture_argument_modifier(TextureStage::CombineOperand operand) { - switch (operand) { - case TextureStage::CO_src_color: - return 0; - - case TextureStage::CO_one_minus_src_color: - return D3DTA_COMPLEMENT; - - case TextureStage::CO_src_alpha: - return D3DTA_ALPHAREPLICATE; - - case TextureStage::CO_one_minus_src_alpha: - return D3DTA_ALPHAREPLICATE | D3DTA_COMPLEMENT; - - case TextureStage::CO_undefined: - break; - } - dxgsg8_cat.error() - << "Invalid TextureStage::CombineOperand value (" << (int)operand << ")\n"; - return 0; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::draw_primitive_up -// Access: Protected -// Description: Issues the DrawPrimitiveUP call to draw the indicated -// primitive_type from the given buffer. We add the -// num_vertices parameter, so we can determine the size -// of the buffer. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -draw_primitive_up(D3DPRIMITIVETYPE primitive_type, - unsigned int primitive_count, - unsigned int first_vertex, - unsigned int num_vertices, - const unsigned char *buffer, size_t stride) { - - // It appears that the common ATI driver seems to fail to draw - // anything in the DrawPrimitiveUP() call if the address range of - // the buffer supplied crosses over a multiple of 0x10000. That's - // incredibly broken, yet it undeniably appears to be true. We'll - // have to hack around it. - - const unsigned char *buffer_start = buffer + stride * first_vertex; - const unsigned char *buffer_end = buffer_start + stride * num_vertices; - - if (buffer_end - buffer_start > 0x10000) { - // Actually, the buffer doesn't fit within the required limit - // anyway. Go ahead and draw it and hope for the best. - _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count, - buffer_start, stride); - - } else if ((((long)buffer_end ^ (long)buffer_start) & ~0xffff) == 0) { - // No problem; we can draw the buffer directly. - _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count, - buffer_start, stride); - - } else { - // We have a problem--the buffer crosses over a 0x10000 boundary. - // We have to copy the buffer to a temporary buffer that we can - // draw from. - unsigned char *safe_buffer_start = get_safe_buffer_start(); - memcpy(safe_buffer_start, buffer_start, buffer_end - buffer_start); - _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count, - safe_buffer_start, stride); - - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::draw_indexed_primitive_up -// Access: Protected -// Description: Issues the DrawIndexedPrimitiveUP call to draw the -// indicated primitive_type from the given buffer. As -// in draw_primitive_up(), above, the parameter list is -// not exactly one-for-one with the -// DrawIndexedPrimitiveUP() call, but it's similar (in -// particular, we pass max_index instead of NumVertices, -// which always seemed ambiguous to me). -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -draw_indexed_primitive_up(D3DPRIMITIVETYPE primitive_type, - unsigned int min_index, unsigned int max_index, - unsigned int num_primitives, - const unsigned char *index_data, - D3DFORMAT index_type, - const unsigned char *buffer, size_t stride) { - // As above, we'll hack the case of the buffer crossing the 0x10000 - // boundary. - const unsigned char *buffer_start = buffer + stride * min_index; - const unsigned char *buffer_end = buffer + stride * (max_index + 1); - - if (buffer_end - buffer > 0x10000) { - // Actually, the buffer doesn't fit within the required limit - // anyway. Go ahead and draw it and hope for the best. - _d3d_device->DrawIndexedPrimitiveUP - (primitive_type, min_index, max_index - min_index + 1, num_primitives, - index_data, index_type, buffer, stride); - - } else if ((((long)buffer_end ^ (long)buffer) & ~0xffff) == 0) { - // No problem; we can draw the buffer directly. - _d3d_device->DrawIndexedPrimitiveUP - (primitive_type, min_index, max_index - min_index + 1, num_primitives, - index_data, index_type, buffer, stride); - - } else { - // We have a problem--the buffer crosses over a 0x10000 boundary. - // We have to copy the buffer to a temporary buffer that we can - // draw from. - unsigned char *safe_buffer_start = get_safe_buffer_start(); - size_t offset = buffer_start - buffer; - memcpy(safe_buffer_start + offset, buffer_start, buffer_end - buffer_start); - _d3d_device->DrawIndexedPrimitiveUP - (primitive_type, min_index, max_index - min_index + 1, num_primitives, - index_data, index_type, safe_buffer_start, stride); - } -} - -//////////////////////////////////////////////////////////////////// -// DX stencil code section -//////////////////////////////////////////////////////////////////// -static int dx_stencil_comparison_function_array[] = { - D3DCMP_NEVER, - D3DCMP_LESS, - D3DCMP_EQUAL, - D3DCMP_LESSEQUAL, - D3DCMP_GREATER, - D3DCMP_NOTEQUAL, - D3DCMP_GREATEREQUAL, - D3DCMP_ALWAYS, -}; - -static int dx_stencil_operation_array[] = { - D3DSTENCILOP_KEEP, - D3DSTENCILOP_ZERO, - D3DSTENCILOP_REPLACE, - D3DSTENCILOP_INCR, - D3DSTENCILOP_DECR, - D3DSTENCILOP_INVERT, - - D3DSTENCILOP_INCRSAT, - D3DSTENCILOP_DECRSAT, -}; - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::do_issue_stencil -// Access: Protected -// Description: Set stencil render states. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_stencil() { - if (!_supports_stencil) { - return; - } - - const StencilAttrib *stencil = DCAST(StencilAttrib, _target_rs->get_attrib(StencilAttrib::get_class_slot())); - - if (stencil != (const StencilAttrib *)NULL) { - // DEBUG - if (false) { - dxgsg8_cat.debug() << "STENCIL STATE CHANGE\n"; - dxgsg8_cat.debug() << "\n" - << "SRS_front_comparison_function " << stencil->get_render_state(StencilAttrib::SRS_front_comparison_function) << "\n" - << "SRS_front_stencil_fail_operation " << stencil->get_render_state(StencilAttrib::SRS_front_stencil_fail_operation) << "\n" - << "SRS_front_stencil_pass_z_fail_operation " << stencil->get_render_state(StencilAttrib::SRS_front_stencil_pass_z_fail_operation) << "\n" - << "SRS_front_stencil_pass_z_pass_operation " << stencil->get_render_state(StencilAttrib::SRS_front_stencil_pass_z_pass_operation) << "\n" - << "SRS_reference " << stencil->get_render_state(StencilAttrib::SRS_reference) << "\n" - << "SRS_read_mask " << stencil->get_render_state(StencilAttrib::SRS_read_mask) << "\n" - << "SRS_write_mask " << stencil->get_render_state(StencilAttrib::SRS_write_mask) << "\n"; - } - - unsigned int front_compare; - front_compare = stencil->get_render_state(StencilAttrib::SRS_front_comparison_function); - if (front_compare != RenderAttrib::M_none) { - set_render_state(D3DRS_STENCILENABLE, TRUE); - set_render_state(D3DRS_STENCILFUNC, dx_stencil_comparison_function_array[front_compare]); - set_render_state(D3DRS_STENCILFAIL, dx_stencil_operation_array[ - stencil->get_render_state(StencilAttrib::SRS_front_stencil_fail_operation)]); - set_render_state(D3DRS_STENCILZFAIL, dx_stencil_operation_array[ - stencil->get_render_state(StencilAttrib::SRS_front_stencil_pass_z_fail_operation)]); - set_render_state(D3DRS_STENCILPASS, dx_stencil_operation_array[ - stencil->get_render_state(StencilAttrib::SRS_front_stencil_pass_z_pass_operation)]); - - set_render_state(D3DRS_STENCILREF, stencil->get_render_state(StencilAttrib::SRS_reference)); - set_render_state(D3DRS_STENCILMASK, stencil->get_render_state(StencilAttrib::SRS_read_mask)); - set_render_state(D3DRS_STENCILWRITEMASK, stencil->get_render_state(StencilAttrib::SRS_write_mask)); - } else { - set_render_state(D3DRS_STENCILENABLE, FALSE); - } - - if (stencil->get_render_state(StencilAttrib::SRS_clear)) { - _d3d_device->Clear(0, NULL, D3DCLEAR_STENCIL, 0, 0.0f, stencil->get_render_state(StencilAttrib::SRS_clear_value)); - } - - } else { - // DEBUG - if (false) { - dxgsg8_cat.debug() << "STENCIL STATE CHANGE TO OFF\n"; - } - - set_render_state(D3DRS_STENCILENABLE, FALSE); - } -} - -LPDIRECT3DDEVICE8 DXGraphicsStateGuardian8:: -get_d3d_device() { - return _d3d_device; -} - -//////////////////////////////////////////////////////////////////// -// Function: dxGraphicsStateGuardian8::do_issue_scissor -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -do_issue_scissor() { - const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot())); - const LVecBase4 &frame = target_scissor->get_frame(); - set_scissor(frame[0], frame[1], frame[2], frame[3]); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_scissor -// Access: Private -// Description: Sets up the scissor region, as a set of coordinates -// relative to the current viewport. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) { - // DirectX8 doesn't have an explicit scissor control, independent of - // the viewport, so we have to do it by hand, by moving the viewport - // smaller but adjusting the projection matrix to compensate. - - // First, constrain the viewport to the scissor region. - D3DVIEWPORT8 vp; - vp.Width = _current_viewport.Width * (right - left); - vp.X = _current_viewport.X + _current_viewport.Width * left; - vp.Height = _current_viewport.Height * (top - bottom); - vp.Y = _current_viewport.Y + _current_viewport.Height * (1.0f - top); - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - - HRESULT hr = _d3d_device->SetViewport(&vp); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "_screen->_swap_chain = " << _screen->_swap_chain << " _swap_chain = " << _swap_chain << "\n"; - dxgsg8_cat.error() - << "SetViewport(" << vp.X << ", " << vp.Y << ", " << vp.Width << ", " << vp.Height - << ") failed" << D3DERRORSTRING(hr); - - D3DVIEWPORT8 vp_old; - _d3d_device->GetViewport(&vp_old); - dxgsg8_cat.error() - << "GetViewport(" << vp_old.X << ", " << vp_old.Y << ", " << vp_old.Width << ", " - << vp_old.Height << ") returned: Trying to set that vp---->\n"; - hr = _d3d_device->SetViewport(&vp_old); - - if (FAILED(hr)) { - dxgsg8_cat.error() << "Failed again\n"; - throw_event("panda3d-render-error"); - nassertv(false); - } - } - - // Now, compute _scissor_mat, which we use to compensate the - // projection matrix. - PN_stdfloat xsize = right - left; - PN_stdfloat ysize = top - bottom; - PN_stdfloat xcenter = (left + right) - 1.0f; - PN_stdfloat ycenter = (bottom + top) - 1.0f; - if (xsize == 0.0f || ysize == 0.0f) { - // If the scissor region is zero, nothing will be drawn anyway, so - // don't worry about it. - _scissor_mat = TransformState::make_identity(); - } else { - _scissor_mat = TransformState::make_scale(LVecBase3(1.0f / xsize, 1.0f / ysize, 1.0f))->compose(TransformState::make_pos(LPoint3(-xcenter, -ycenter, 0.0f))); - } - prepare_lens(); -} - -//////////////////////////////////////////////////////////////////// -// Function: dxGraphicsStateGuardian8::calc_fb_properties -// Access: Public -// Description: Convert DirectX framebuffer format ids into a -// FrameBufferProperties structure. -//////////////////////////////////////////////////////////////////// -FrameBufferProperties DXGraphicsStateGuardian8:: -calc_fb_properties(DWORD cformat, DWORD dformat, DWORD multisampletype) { - FrameBufferProperties props; - int index=0; - int r=0, g=0, b=0, a=0; - switch (cformat) { - case D3DFMT_R8G8B8: r=8; g=8; b=8; a=0; break; - case D3DFMT_A8R8G8B8: r=8; g=8; b=8; a=8; break; - case D3DFMT_X8R8G8B8: r=8; g=8; b=8; a=0; break; - case D3DFMT_R5G6B5: r=5; g=6; b=5; a=0; break; - case D3DFMT_X1R5G5B5: r=5; g=5; b=5; a=0; break; - case D3DFMT_A1R5G5B5: r=5; g=5; b=5; a=1; break; - case D3DFMT_A4R4G4B4: r=4; g=4; b=4; a=4; break; - case D3DFMT_R3G3B2: r=3; g=3; b=2; a=0; break; - case D3DFMT_A8R3G3B2: r=3; g=3; b=2; a=8; break; - case D3DFMT_X4R4G4B4: r=4; g=4; b=4; a=0; break; - case D3DFMT_A2B10G10R10: r=10;g=10;b=10;a=2; break; - case D3DFMT_A8P8: index=8; a=8; break; - case D3DFMT_P8: index=8; a=0; break; - default: break; - } - if (index > 0) { - props.set_rgb_color(0); - props.set_indexed_color(1); - props.set_color_bits(index); - } else if (r + g + b > 0) { - props.set_rgb_color(1); - props.set_indexed_color(0); - props.set_rgba_bits(r, g, b, a); - } - props.set_alpha_bits(a); - - int depth=0; - int stencil=0; - switch (dformat) { - case D3DFMT_D32: depth=32; stencil=0; break; - case D3DFMT_D15S1: depth=15; stencil=1; break; - case D3DFMT_D24S8: depth=24; stencil=8; break; - case D3DFMT_D16: depth=16; stencil=0; break; - case D3DFMT_D24X8: depth=24; stencil=0; break; - case D3DFMT_D24X4S4: depth=24; stencil=4; break; - default: break; - } - props.set_depth_bits(depth); - props.set_stencil_bits(stencil); - props.set_multisamples(multisampletype); - return props; -} - -#define GAMMA_1 (255.0 * 256.0) - -static bool _gamma_table_initialized = false; -static unsigned short _orignial_gamma_table [256 * 3]; - -void _create_gamma_table (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) { - int i; - double gamma_correction; - - if (gamma <= 0.0) { - // avoid divide by zero and negative exponents - gamma = 1.0; - } - gamma_correction = 1.0 / (double) gamma; - - for (i = 0; i < 256; i++) { - double r; - double g; - double b; - - if (original_red_table) { - r = (double) original_red_table [i] / GAMMA_1; - g = (double) original_green_table [i] / GAMMA_1; - b = (double) original_blue_table [i] / GAMMA_1; - } - else { - r = ((double) i / 255.0); - g = r; - b = r; - } - - r = pow (r, gamma_correction); - g = pow (g, gamma_correction); - b = pow (b, gamma_correction); - - if (r > 1.00) { - r = 1.0; - } - if (g > 1.00) { - g = 1.0; - } - if (b > 1.00) { - b = 1.0; - } - - r = r * GAMMA_1; - g = g * GAMMA_1; - b = b * GAMMA_1; - - red_table [i] = r; - green_table [i] = g; - blue_table [i] = b; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::get_gamma_table -// Access: Public, Static -// Description: Static function for getting the original gamma. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -get_gamma_table(void) { - bool get; - - get = false; - if (_gamma_table_initialized == false) { - HDC hdc = GetDC(NULL); - - if (hdc) { - if (GetDeviceGammaRamp (hdc, (LPVOID) _orignial_gamma_table)) { - _gamma_table_initialized = true; - get = true; - } - - ReleaseDC (NULL, hdc); - } - } - - return get; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::static_set_gamma -// Access: Public, Static -// Description: Static function for setting gamma which is needed -// for atexit. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -static_set_gamma(bool restore, PN_stdfloat gamma) { - bool set; - HDC hdc = GetDC(NULL); - - set = false; - if (hdc) { - unsigned short ramp [256 * 3]; - - if (restore && _gamma_table_initialized) { - _create_gamma_table (gamma, &_orignial_gamma_table [0], &_orignial_gamma_table [256], &_orignial_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]); - } - else { - _create_gamma_table (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]); - } - - if (SetDeviceGammaRamp (hdc, ramp)) { - set = true; - } - - ReleaseDC (NULL, hdc); - } - - return set; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::set_gamma -// Access: Published -// Description: Non static version of setting gamma. Returns true -// on success. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -set_gamma(PN_stdfloat gamma) { - bool set; - - set = static_set_gamma(false, gamma); - if (set) { - _gamma = gamma; - } - - return set; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::restore_gamma -// Access: Published -// Description: Restore original gamma. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -restore_gamma() { - static_set_gamma(true, 1.0f); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::atexit_function -// Access: Public, Static -// Description: This function is passed to the atexit function. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -atexit_function(void) { - static_set_gamma(true, 1.0); -} diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h deleted file mode 100644 index 029ec5e2de..0000000000 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ /dev/null @@ -1,309 +0,0 @@ -// Filename: dxGraphicsStateGuardian8.h -// Created by: mike (02Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef DXGRAPHICSSTATEGUARDIAN8_H -#define DXGRAPHICSSTATEGUARDIAN8_H - -#include "dxgsg8base.h" -#include "dxTextureContext8.h" -#include "config_dxgsg8.h" - -#include "graphicsStateGuardian.h" -#include "texture.h" -#include "displayRegion.h" -#include "material.h" -#include "depthTestAttrib.h" -#include "cullFaceAttrib.h" -#include "renderModeAttrib.h" -#include "colorBlendAttrib.h" -#include "fog.h" -#include "pointerToArray.h" - -class Light; - -class DXTextureContext8; -class DXVertexBufferContext8; -class DXIndexBufferContext8; - -//////////////////////////////////////////////////////////////////// -// Class : DXGraphicsStateGuardian8 -// Description : A GraphicsStateGuardian for rendering into DirectX8 -// contexts. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXGraphicsStateGuardian8 : public GraphicsStateGuardian { -public: - DXGraphicsStateGuardian8(GraphicsEngine *engine, GraphicsPipe *pipe); - ~DXGraphicsStateGuardian8(); - - FrameBufferProperties - calc_fb_properties(DWORD cformat, DWORD dformat, DWORD multisampletype); - - virtual TextureContext *prepare_texture(Texture *tex, int view); - void apply_texture(int i, TextureContext *tc, const SamplerState &sampler); - virtual bool update_texture(TextureContext *tc, bool force); - bool upload_texture(DXTextureContext8 *dtc, bool force); - virtual void release_texture(TextureContext *tc); - virtual bool extract_texture_data(Texture *tex); - - virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data); - bool apply_vertex_buffer(VertexBufferContext *vbc, - const GeomVertexArrayDataHandle *reader, bool force); - virtual void release_vertex_buffer(VertexBufferContext *vbc); - - virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data); - bool apply_index_buffer(IndexBufferContext *ibc, - const GeomPrimitivePipelineReader *reader, bool force); - virtual void release_index_buffer(IndexBufferContext *ibc); - - virtual PT(GeomMunger) make_geom_munger(const RenderState *state, - Thread *current_thread); - - virtual void clear(DrawableRegion *region); - - virtual void prepare_display_region(DisplayRegionPipelineReader *dr); - virtual CPT(TransformState) calc_projection_mat(const Lens *lens); - virtual bool prepare_lens(); - - virtual bool begin_frame(Thread *current_thread); - virtual bool begin_scene(); - virtual void end_scene(); - virtual void end_frame(Thread *current_thread); - - virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, - const GeomMunger *munger, - const GeomVertexDataPipelineReader *data_reader, - bool force); - virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, - bool force); - virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, - bool force); - virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader, - bool force); - virtual bool draw_lines(const GeomPrimitivePipelineReader *reader, - bool force); - virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader, - bool force); - virtual bool draw_points(const GeomPrimitivePipelineReader *reader, - bool force); - virtual void end_draw_primitives(); - - virtual bool framebuffer_copy_to_texture(Texture *tex, int view, int z, - const DisplayRegion *dr, - const RenderBuffer &rb); - virtual bool framebuffer_copy_to_ram(Texture *tex, int view, int z, - const DisplayRegion *dr, - const RenderBuffer &rb); - bool do_framebuffer_copy_to_ram(Texture *tex, int view, int z, - const DisplayRegion *dr, - const RenderBuffer &rb, - bool inverted); - - virtual void reset(); - - virtual void apply_fog(Fog *fog); - - virtual void bind_light(PointLight *light_obj, const NodePath &light, - int light_id); - virtual void bind_light(DirectionalLight *light_obj, const NodePath &light, - int light_id); - virtual void bind_light(Spotlight *light_obj, const NodePath &light, - int light_id); - - static D3DFORMAT get_index_type(Geom::NumericType numeric_type); - INLINE static DWORD LColor_to_D3DCOLOR(const LColor &cLColor); - - virtual void set_state_and_transform(const RenderState *state, - const TransformState *transform); - LPDIRECT3DDEVICE8 get_d3d_device(); - INLINE bool get_supports_render_texture() const; - - static bool get_gamma_table(void); - static bool static_set_gamma(bool restore, PN_stdfloat gamma); - bool set_gamma(PN_stdfloat gamma); - void restore_gamma(); - static void atexit_function(void); - -protected: - void do_issue_transform(); - void do_issue_alpha_test(); - void do_issue_render_mode(); - void do_issue_rescale_normal(); - void do_issue_color_write(); - void do_issue_depth_test(); - void do_issue_depth_write(); - void do_issue_cull_face(); - void do_issue_fog(); - void do_issue_depth_offset(); - void do_issue_tex_gen(); - void do_issue_shade_model(); - void do_issue_material(); - void do_issue_texture(); - void do_issue_blending(); - void do_issue_stencil(); - void do_issue_scissor(); - - void set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top); - - virtual void reissue_transforms(); - - virtual void enable_lighting(bool enable); - virtual void set_ambient_light(const LColor &color); - virtual void enable_light(int light_id, bool enable); - - virtual void enable_clip_plane(int plane_id, bool enable); - virtual void bind_clip_plane(const NodePath &plane, int plane_id); - - virtual void close_gsg(); - void free_nondx_resources(); - void free_d3d_device(); - - void set_draw_buffer(const RenderBuffer &rb); - void set_read_buffer(const RenderBuffer &rb); - - void do_auto_rescale_normal(); - -protected: - INLINE static D3DTEXTUREADDRESS get_texture_wrap_mode(SamplerState::WrapMode wm); - INLINE static D3DFOGMODE get_fog_mode_type(Fog::Mode m); - const D3DCOLORVALUE &get_light_color(Light *light) const; - INLINE static D3DTRANSFORMSTATETYPE get_tex_mat_sym(int stage_index); - - static D3DBLEND get_blend_func(ColorBlendAttrib::Operand operand); - void report_texmgr_stats(); - - void set_context(DXScreenData *new_context); - void set_render_target(); - - void set_texture_blend_mode(int i, const TextureStage *stage); - - void dx_cleanup(); - HRESULT reset_d3d_device(D3DPRESENT_PARAMETERS *p_presentation_params, - DXScreenData **screen = NULL); - - bool check_cooperative_level(); - - void show_frame(); - - bool create_swap_chain (DXScreenData *new_context); - bool release_swap_chain (DXScreenData *new_context); - void copy_pres_reset(DXScreenData *new_context); - - static D3DTEXTUREFILTERTYPE get_d3d_min_type(SamplerState::FilterType filter_type); - static D3DTEXTUREFILTERTYPE get_d3d_mip_type(SamplerState::FilterType filter_type); - static D3DTEXTUREOP get_texture_operation(TextureStage::CombineMode mode, int scale); - static DWORD get_texture_argument(TextureStage::CombineSource source, - TextureStage::CombineOperand operand); - static DWORD get_texture_argument_modifier(TextureStage::CombineOperand operand); - - void draw_primitive_up(D3DPRIMITIVETYPE primitive_type, - unsigned int primitive_count, - unsigned int first_vertex, - unsigned int num_vertices, - const unsigned char *buffer, size_t stride); - void draw_indexed_primitive_up(D3DPRIMITIVETYPE primitive_type, - unsigned int min_index, unsigned int max_index, - unsigned int num_primitives, - const unsigned char *index_data, - D3DFORMAT index_type, - const unsigned char *buffer, size_t stride); - - INLINE static unsigned char *get_safe_buffer_start(); - -protected: - DXScreenData *_screen; - LPDIRECT3DDEVICE8 _d3d_device; // same as _screen->_d3d_device, cached for spd - IDirect3DSwapChain8 *_swap_chain; - D3DPRESENT_PARAMETERS _presentation_reset; // This is built during reset device - - bool _dx_is_ready; - HRESULT _last_testcooplevel_result; - - bool _vertex_blending_enabled; - bool _supports_render_texture; - - RenderBuffer::Type _cur_read_pixel_buffer; // source for copy_pixel_buffer operation - bool _auto_rescale_normal; - - PN_stdfloat _material_ambient; - PN_stdfloat _material_diffuse; - PN_stdfloat _material_specular; - PN_stdfloat _material_shininess; - PN_stdfloat _material_emission; - - enum DxgsgFogType { - None, - PerVertexFog=D3DRS_FOGVERTEXMODE, - PerPixelFog=D3DRS_FOGTABLEMODE - }; - DxgsgFogType _do_fog_type; - - D3DVIEWPORT8 _current_viewport; - - DWORD _clip_plane_bits; - CullFaceAttrib::Mode _cull_face_mode; - RenderModeAttrib::Mode _current_fill_mode; //point/wireframe/solid - - const DXVertexBufferContext8 *_active_vbuffer; - const DXIndexBufferContext8 *_active_ibuffer; - - int _num_active_texture_stages; - - // Cache the data necessary to bind each particular light each - // frame, so if we bind a given light multiple times, we only have - // to compute its data once. - typedef pmap DirectionalLights; - DirectionalLights _dlights; - - bool _overlay_windows_supported; - bool _tex_stats_retrieval_impossible; - - static D3DMATRIX _d3d_ident_mat; - CPT(TransformState) _scissor_mat; - - static unsigned char *_temp_buffer; - static unsigned char *_safe_buffer_start; - - list _graphics_buffer_list; - -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; - } - -public: - static void init_type() { - GraphicsStateGuardian::init_type(); - register_type(_type_handle, "DXGraphicsStateGuardian8", - GraphicsStateGuardian::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class wdxGraphicsWindow8; - friend class wdxGraphicsBuffer8; - friend class wdxGraphicsPipe8; - friend class wdxGraphicsWindowGroup8; - friend class DXTextureContext8; -}; - -#include "dxGraphicsStateGuardian8.I" - -#endif - diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.I b/panda/src/dxgsg8/dxIndexBufferContext8.I deleted file mode 100644 index 81ec205c07..0000000000 --- a/panda/src/dxgsg8/dxIndexBufferContext8.I +++ /dev/null @@ -1,14 +0,0 @@ -// Filename: dxIndexBufferContext8.I -// Created by: drose (18Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.cxx b/panda/src/dxgsg8/dxIndexBufferContext8.cxx deleted file mode 100644 index 51b9745dd7..0000000000 --- a/panda/src/dxgsg8/dxIndexBufferContext8.cxx +++ /dev/null @@ -1,173 +0,0 @@ -// Filename: dxIndexBufferContext8.cxx -// Created by: drose (18Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "dxIndexBufferContext8.h" -#include "geomPrimitive.h" -#include "config_dxgsg8.h" -#include "graphicsStateGuardian.h" -#include "pStatTimer.h" -#include "dxgsg8base.h" - -TypeHandle DXIndexBufferContext8::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: DXIndexBufferContext8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXIndexBufferContext8:: -DXIndexBufferContext8(PreparedGraphicsObjects *pgo, GeomPrimitive *data) : - IndexBufferContext(pgo, data), - _ibuffer(NULL) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: DXIndexBufferContext8::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXIndexBufferContext8:: -~DXIndexBufferContext8() { - if (_ibuffer != NULL) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "deleting index buffer " << _ibuffer << "\n"; - } - - RELEASE(_ibuffer, dxgsg8, "index buffer", RELEASE_ONCE); - _ibuffer = NULL; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXIndexBufferContext8::evict_lru -// Access: Public, Virtual -// Description: 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 DXIndexBufferContext8:: -evict_lru() { - dequeue_lru(); - - if (_ibuffer != NULL) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "deleting index buffer " << _ibuffer << "\n"; - } - - RELEASE(_ibuffer, dxgsg8, "index buffer", RELEASE_ONCE); - _ibuffer = NULL; - } - - update_data_size_bytes(0); - mark_unloaded(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXIndexBufferContext8::create_ibuffer -// Access: Public -// Description: Creates a new index buffer (but does not upload data -// to it). -//////////////////////////////////////////////////////////////////// -void DXIndexBufferContext8:: -create_ibuffer(DXScreenData &scrn, - const GeomPrimitivePipelineReader *reader) { - nassertv(reader->get_object() == get_data()); - Thread *current_thread = reader->get_current_thread(); - - if (_ibuffer != NULL) { - RELEASE(_ibuffer, dxgsg8, "index buffer", RELEASE_ONCE); - _ibuffer = NULL; - } - - PStatTimer timer(GraphicsStateGuardian::_create_index_buffer_pcollector, - current_thread); - - D3DFORMAT index_type = - DXGraphicsStateGuardian8::get_index_type(reader->get_index_type()); - - HRESULT hr = scrn._d3d_device->CreateIndexBuffer -// (reader->get_data_size_bytes(), D3DUSAGE_WRITEONLY, -// index_type, D3DPOOL_MANAGED, &_ibuffer); - (reader->get_data_size_bytes(), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, - index_type, D3DPOOL_DEFAULT, &_ibuffer); - if (FAILED(hr)) { - dxgsg8_cat.warning() - << "CreateIndexBuffer failed" << D3DERRORSTRING(hr); - _ibuffer = NULL; - } else { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "creating index buffer " << _ibuffer << ": " - << reader->get_num_vertices() << " indices (" - << reader->get_vertices_reader()->get_array_format()->get_column(0)->get_numeric_type() - << ")\n"; - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXIndexBufferContext8::upload_data -// Access: Public -// Description: Copies the latest data from the client store to -// DirectX. -//////////////////////////////////////////////////////////////////// -bool DXIndexBufferContext8:: -upload_data(const GeomPrimitivePipelineReader *reader, bool force) { - nassertr(reader->get_object() == get_data(), false); - Thread *current_thread = reader->get_current_thread(); - - nassertr(_ibuffer != NULL, false); - - const unsigned char *data_pointer = reader->get_read_pointer(force); - if (data_pointer == NULL) { - return false; - } - int data_size = reader->get_data_size_bytes(); - - if (dxgsg8_cat.is_spam()) { - dxgsg8_cat.spam() - << "copying " << data_size - << " bytes into index buffer " << _ibuffer << "\n"; - } - - PStatTimer timer(GraphicsStateGuardian::_load_index_buffer_pcollector, - current_thread); - - BYTE *local_pointer; -// HRESULT hr = _ibuffer->Lock(0, data_size, &local_pointer, 0); - HRESULT hr = _ibuffer->Lock(0, data_size, &local_pointer, D3DLOCK_DISCARD); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "IndexBuffer::Lock failed" << D3DERRORSTRING(hr); - return false; - } - - GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size); - memcpy(local_pointer, data_pointer, data_size); - - _ibuffer->Unlock(); - return true; -} - diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.h b/panda/src/dxgsg8/dxIndexBufferContext8.h deleted file mode 100644 index 8322463800..0000000000 --- a/panda/src/dxgsg8/dxIndexBufferContext8.h +++ /dev/null @@ -1,62 +0,0 @@ -// Filename: dxIndexBufferContext8.h -// Created by: drose (18Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef DXINDEXBUFFERCONTEXT8_H -#define DXINDEXBUFFERCONTEXT8_H - -#include "pandabase.h" -#include "dxgsg8base.h" -#include "indexBufferContext.h" - -//////////////////////////////////////////////////////////////////// -// Class : DXIndexBufferContext8 -// Description : Caches a GeomPrimitive in the DirectX device as -// an index buffer. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXIndexBufferContext8 : public IndexBufferContext { -public: - DXIndexBufferContext8(PreparedGraphicsObjects *pgo, GeomPrimitive *data); - virtual ~DXIndexBufferContext8(); - - virtual void evict_lru(); - - void create_ibuffer(DXScreenData &scrn, - const GeomPrimitivePipelineReader *reader); - bool upload_data(const GeomPrimitivePipelineReader *reader, bool force); - - IDirect3DIndexBuffer8 *_ibuffer; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - IndexBufferContext::init_type(); - register_type(_type_handle, "DXIndexBufferContext8", - IndexBufferContext::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 "dxIndexBufferContext8.I" - -#endif - - diff --git a/panda/src/dxgsg8/dxInput8.cxx b/panda/src/dxgsg8/dxInput8.cxx deleted file mode 100644 index a26e23679a..0000000000 --- a/panda/src/dxgsg8/dxInput8.cxx +++ /dev/null @@ -1,272 +0,0 @@ -// Filename: dxInput8.cxx -// Created by: angelina jolie (07Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "config_wdxdisplay8.h" -#include "dxInput8.h" - -#define AXIS_RESOLUTION 2000 // use this many levels of resolution by default (could be more if needed and device supported it) -#define AXIS_RANGE_CENTERED // if defined, axis range is centered on 0, instead of starting on 0 - -BOOL CALLBACK EnumGameCtrlsCallback( const DIDEVICEINSTANCE* pdidInstance, - VOID* pContext ) { - DI_DeviceInfos *pDevInfos = (DI_DeviceInfos *)pContext; - - (*pDevInfos).push_back(*pdidInstance); - - if(wdxdisplay_cat.is_debug()) - wdxdisplay_cat.debug() << "Found DevType 0x" << (void*)pdidInstance->dwDevType << ": " << pdidInstance->tszInstanceName << ": " << pdidInstance->tszProductName <Unacquire(); - SAFE_RELEASE(_DeviceList[i]); - } - - // bugbug: need to handle this - // if(_JoystickPollTimer!=NULL) - // KillTimer(...) - - SAFE_RELEASE(_pDInput8); - if(_hDInputDLL) { - FreeLibrary(_hDInputDLL); - _hDInputDLL=NULL; - } -} - -bool DInput8Info::InitDirectInput() { - HRESULT hr; - - // assumes dx8 exists - // use dynamic load so non-dinput programs don't have to load dinput - #define DLLNAME "dinput8.dll" - #define DINPUTCREATE "DirectInput8Create" - - HINSTANCE _hDInputDLL = LoadLibrary(DLLNAME); - if(_hDInputDLL == 0) { - wdxdisplay_cat.fatal() << "LoadLibrary(" << DLLNAME <<") failed!, error=" << GetLastError() << endl; - exit(1); - } - - typedef HRESULT (WINAPI * LPDIRECTINPUT8CREATE)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter); - LPDIRECTINPUT8CREATE pDInputCreate8; - - pDInputCreate8 = (LPDIRECTINPUT8CREATE) GetProcAddress(_hDInputDLL,DINPUTCREATE); - if(pDInputCreate8 == NULL) { - wdxdisplay_cat.fatal() << "GetProcAddr failed for " << DINPUTCREATE << endl; - exit(1); - } - - // Register with the DirectInput subsystem and get a pointer - // to a IDirectInput interface we can use. - // Create a DInput object - if( FAILED( hr = (*pDInputCreate8)(GetModuleHandle(NULL), DIRECTINPUT_VERSION, - IID_IDirectInput8, (VOID**)&_pDInput8, NULL ) ) ) { - wdxdisplay_cat.error() << DINPUTCREATE << "failed" << D3DERRORSTRING(hr); - return false; - } - - // enum all the joysticks,etc (but not keybd/mouse) - if( FAILED( hr = _pDInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, - EnumGameCtrlsCallback, - (LPVOID)&_DevInfos, DIEDFL_ATTACHEDONLY ) ) ) { - wdxdisplay_cat.error() << "EnumDevices failed" << D3DERRORSTRING(hr); - return false; - } - - return true; -} - -bool DInput8Info::CreateJoystickOrPad(HWND _window) { - bool bFoundDev = false; - UINT devnum=0; - char *errstr=NULL; - - // look through the list for the first joystick or gamepad - for(;devnum<_DevInfos.size();devnum++) { - DWORD devType = GET_DIDEVICE_TYPE(_DevInfos[devnum].dwDevType); - if((devType==DI8DEVTYPE_GAMEPAD) ||(devType==DI8DEVTYPE_JOYSTICK)) { - bFoundDev=true; - break; - } - } - - if(!bFoundDev) { - wdxdisplay_cat.error() << "Cant find an attached Joystick or GamePad!\n"; - return false; - } - - LPDIRECTINPUTDEVICE8 pJoyDevice; - - // Obtain an interface to the enumerated joystick. - HRESULT hr = _pDInput8->CreateDevice(_DevInfos[devnum].guidInstance, &pJoyDevice, NULL ); - if(FAILED(hr)) { - errstr="CreateDevice"; - goto handle_error; - } - - nassertr(pJoyDevice!=NULL, false); - _DeviceList.push_back(pJoyDevice); - - // Set the data format to "simple joystick" - a predefined data format - // - // A data format specifies which controls on a device we are interested in, - // and how they should be reported. This tells DInput that we will be - // passing a DIJOYSTATE2 structure to IDirectInputDevice::GetDeviceState(). - hr = pJoyDevice->SetDataFormat(&c_dfDIJoystick2); - if(FAILED(hr)) { - errstr="SetDataFormat"; - goto handle_error; - } - - // must be called AFTER SetDataFormat to get all the proper flags - DX_DECLARE_CLEAN(DIDEVCAPS, DIDevCaps); - hr = pJoyDevice->GetCapabilities(&DIDevCaps); - nassertr(SUCCEEDED(hr), false); - - _DevCaps.push_back(DIDevCaps); - - if(wdxdisplay_cat.is_debug()) - wdxdisplay_cat.debug() << "Joy/Pad has " << DIDevCaps.dwAxes << " Axes, " << DIDevCaps.dwButtons << " Buttons, " << DIDevCaps.dwPOVs << " POVs" << endl; - - // Set the cooperative level to let DInput know how this device should - // interact with the system and with other DInput applications. - hr = pJoyDevice->SetCooperativeLevel( _window, DISCL_EXCLUSIVE | DISCL_FOREGROUND); - if(FAILED(hr)) { - errstr="SetCooperativeLevel"; - goto handle_error; - } - - // set the min/max values property for discovered axes. - hr = pJoyDevice->EnumObjects(EnumObjectsCallbackJoystick, (LPVOID)pJoyDevice, DIDFT_AXIS); - if(FAILED(hr)) { - errstr="EnumObjects"; - goto handle_error; - } - - return true; - - handle_error: - wdxdisplay_cat.error() << errstr << " failed for (" << _DevInfos[devnum].tszInstanceName << ":" << _DevInfos[devnum].tszProductName << ")" << D3DERRORSTRING(hr); - return false; -} - -//----------------------------------------------------------------------------- -// Name: EnumObjectsCallback() -// Desc: Callback function for enumerating objects (axes, buttons, POVs) on a -// joystick. This function enables user interface elements for objects -// that are found to exist, and scales axes min/max values. -//----------------------------------------------------------------------------- -BOOL CALLBACK EnumObjectsCallbackJoystick( const DIDEVICEOBJECTINSTANCE* pdidoi, - VOID* pContext ) { - - LPDIRECTINPUTDEVICE8 pJoyDevice = (LPDIRECTINPUTDEVICE8) pContext; - HRESULT hr; - - // For axes that are returned, set the DIPROP_RANGE property for the - // enumerated axis in order to scale min/max values. - if( pdidoi->dwType & DIDFT_AXIS ) { - DIPROPRANGE diprg; - diprg.diph.dwSize = sizeof(DIPROPRANGE); - diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); - diprg.diph.dwHow = DIPH_BYID; - diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis - - #ifdef AXIS_RANGE_CENTERED - diprg.lMin = -AXIS_RESOLUTION/2; - diprg.lMax = +AXIS_RESOLUTION/2; - #else - diprg.lMin = 0; - diprg.lMax = +AXIS_RESOLUTION; - #endif - - // Set the range for the axis - hr = pJoyDevice->SetProperty( DIPROP_RANGE, &diprg.diph); - if(FAILED(hr)) { - wdxdisplay_cat.error() << "SetProperty on axis failed" << D3DERRORSTRING(hr); - return DIENUM_STOP; - } - } - - return DIENUM_CONTINUE; -} - -bool DInput8Info::ReadJoystick(int devnum, DIJOYSTATE2 &js) { - LPDIRECTINPUTDEVICE8 pJoystick = _DeviceList[devnum]; - nassertr(pJoystick!=NULL, false); - HRESULT hr; - char *errstr; - - // Poll the device to read the current state - - hr = pJoystick->Poll(); - - if( FAILED(hr) ) { - // DInput is telling us that the input stream has been - // interrupted. We aren't tracking any state between polls, so - // we don't have any special reset that needs to be done. We - // just re-acquire and try again. - - if((hr==DIERR_NOTACQUIRED)||(hr == DIERR_INPUTLOST)) { - hr = pJoystick->Acquire(); - - if(FAILED(hr)) { - if(wdxdisplay_cat.is_spam()) - wdxdisplay_cat.spam() << "Acquire failed" << D3DERRORSTRING(hr); - - // hr may be DIERR_OTHERAPPHASPRIO or other errors. This - // may occur when the app is minimized or in the process of - // switching, so just try again later - return false; - } - - hr = pJoystick->Poll(); - if(FAILED(hr)) { - // should never happen! - errstr = "Poll after successful Acquire failed"; - goto handle_error; - } - } else { - errstr = "Unknown Poll failure"; - goto handle_error; - } - } - - // should we make a vector of devstate dataformats to generalize this fn for all device types? - - // Get the input's device state - hr = pJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &js); - if(FAILED(hr)) { - errstr = "GetDeviceState failed"; - goto handle_error; - } - - return true; - - handle_error: - wdxdisplay_cat.fatal() << errstr << D3DERRORSTRING(hr); - return false; -} - - diff --git a/panda/src/dxgsg8/dxInput8.h b/panda/src/dxgsg8/dxInput8.h deleted file mode 100644 index a5f1c5f8b3..0000000000 --- a/panda/src/dxgsg8/dxInput8.h +++ /dev/null @@ -1,41 +0,0 @@ -// Filename: dxInput8.h -// Created by: blllyjo (07Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef DXINPUT8_H -#define DXINPUT8_H - -#define DIRECTINPUT_VERSION 0x800 -#include -typedef vector DI_DeviceInfos; -typedef vector DI_DeviceObjInfos; - -class DInput8Info { -public: - DInput8Info(); - ~DInput8Info(); - bool InitDirectInput(); - bool CreateJoystickOrPad(HWND _window); - bool ReadJoystick(int devnum, DIJOYSTATE2 &js); - - HINSTANCE _hDInputDLL; - UINT_PTR _JoystickPollTimer; - LPDIRECTINPUT8 _pDInput8; - DI_DeviceInfos _DevInfos; - // arrays for all created devices. Should probably put these together in a struct, - // along with the data fmt info - vector _DeviceList; - vector _DevCaps; -}; - -#endif diff --git a/panda/src/dxgsg8/dxTextureContext8.I b/panda/src/dxgsg8/dxTextureContext8.I deleted file mode 100644 index 8fdd3bb9b4..0000000000 --- a/panda/src/dxgsg8/dxTextureContext8.I +++ /dev/null @@ -1,69 +0,0 @@ -// Filename: dxTextureContext8.I -// Created by: drose (23May05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::has_mipmaps -// Access: Public -// Description: Returns true if the texture was created with mipmaps, -// false otherwise. -//////////////////////////////////////////////////////////////////// -INLINE bool DXTextureContext8:: -has_mipmaps() const { - return _has_mipmaps; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::get_d3d_texture -// Access: Public -// Description: Returns the Direct3D object that represents the -// texture, whatever kind of texture it is. -//////////////////////////////////////////////////////////////////// -INLINE IDirect3DBaseTexture8 *DXTextureContext8:: -get_d3d_texture() const { - return _d3d_texture; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::get_d3d_2d_texture -// Access: Public -// Description: Returns the Direct3D object that represents the -// texture, in the case of a 1-d or 2-d texture. -//////////////////////////////////////////////////////////////////// -INLINE IDirect3DTexture8 *DXTextureContext8:: -get_d3d_2d_texture() const { - return _d3d_2d_texture; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::get_d3d_volume_texture -// Access: Public -// Description: Returns the Direct3D object that represents the -// texture, in the case of a 3-d texture. -//////////////////////////////////////////////////////////////////// -INLINE IDirect3DVolumeTexture8 *DXTextureContext8:: -get_d3d_volume_texture() const { - return _d3d_volume_texture; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::get_d3d_cube_texture -// Access: Public -// Description: Returns the Direct3D object that represents the -// texture, in the case of a cube map texture. -//////////////////////////////////////////////////////////////////// -INLINE IDirect3DCubeTexture8 *DXTextureContext8:: -get_d3d_cube_texture() const { - return _d3d_cube_texture; -} diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx deleted file mode 100644 index 7a299cb4d0..0000000000 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ /dev/null @@ -1,1853 +0,0 @@ -// Filename: dxTextureContext8.cxx -// Created by: georges (02Feb02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "dxTextureContext8.h" -#include "config_dxgsg8.h" -#include "dxGraphicsStateGuardian8.h" -#include "pStatTimer.h" -#include "dxgsg8base.h" -#include "bamCache.h" -#include "graphicsEngine.h" - -#include -#include - -TypeHandle DXTextureContext8::_type_handle; - -static const DWORD g_LowByteMask = 0x000000FF; - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXTextureContext8:: -DXTextureContext8(PreparedGraphicsObjects *pgo, Texture *tex, int view) : - TextureContext(pgo, tex, view) { - - if (dxgsg8_cat.is_spam()) { - dxgsg8_cat.spam() - << "Creating DX texture [" << tex->get_name() << "], minfilter(" << tex->get_minfilter() << "), magfilter(" << tex->get_magfilter() << "), anisodeg(" << tex->get_anisotropic_degree() << ")\n"; - } - - _d3d_texture = NULL; - _d3d_2d_texture = NULL; - _d3d_volume_texture = NULL; - _d3d_cube_texture = NULL; - _has_mipmaps = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -DXTextureContext8:: -~DXTextureContext8() { - delete_texture(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::evict_lru -// Access: Public, Virtual -// Description: 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 DXTextureContext8:: -evict_lru() { - if (get_texture()->get_render_to_texture()) { - // Don't evict the result of render-to-texture. - mark_used_lru(); - return; - } - - dequeue_lru(); - delete_texture(); - update_data_size_bytes(0); - mark_unloaded(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::create_texture -// Access: Public -// Description: Use panda texture's pixelbuffer to create a texture -// for the specified device. This code gets the -// attributes of the texture from the bitmap, creates -// the texture, and then copies the bitmap into the -// texture. The return value is true if the texture is -// successfully created, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DXTextureContext8:: -create_texture(DXScreenData &scrn) { - HRESULT hr; - int num_alpha_bits; // number of alpha bits in texture pixfmt - D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN; - bool needs_luminance = false; - bool compress_texture = false; - - Texture *tex = get_texture(); - nassertr(IS_VALID_PTR(tex), false); - - delete_texture(); - -#ifdef DO_PSTATS - update_data_size_bytes(tex->estimate_texture_memory()); -#endif // DO_PSTATS - - // bpp indicates requested fmt, not texture fmt - DWORD target_bpp = get_bits_per_pixel(tex->get_format(), &num_alpha_bits); - DWORD num_color_channels = tex->get_num_components(); - - //PRINT_REFCNT(dxgsg8, scrn._d3d8); - - DWORD orig_width = (DWORD)tex->get_x_size(); - DWORD orig_height = (DWORD)tex->get_y_size(); - DWORD orig_depth = (DWORD)tex->get_z_size(); - - if ((tex->get_format() == Texture::F_luminance_alpha)|| - (tex->get_format() == Texture::F_luminance_alphamask) || - (tex->get_format() == Texture::F_luminance)) { - needs_luminance = true; - } - - if (num_alpha_bits > 0) { - if (num_color_channels == 3) { - dxgsg8_cat.error() - << "texture " << tex->get_name() - << " has no inherent alpha channel, but alpha format is requested!\n"; - } - } - - _d3d_format = D3DFMT_UNKNOWN; - - // figure out what 'D3DFMT' the Texture is in, so D3DXLoadSurfFromMem knows how to perform copy - - switch (num_color_channels) { - case 1: - if (num_alpha_bits > 0) { - _d3d_format = D3DFMT_A8; - } else if (needs_luminance) { - _d3d_format = D3DFMT_L8; - } - break; - case 2: - nassertr(needs_luminance && (num_alpha_bits > 0), false); - _d3d_format = D3DFMT_A8L8; - break; - case 3: - _d3d_format = D3DFMT_R8G8B8; - break; - case 4: - _d3d_format = D3DFMT_A8R8G8B8; - break; - } - - // check for texture compression - bool texture_wants_compressed = false; - Texture::CompressionMode compression_mode = tex->get_ram_image_compression(); - bool texture_stored_compressed = compression_mode != Texture::CM_off; - - if (texture_stored_compressed) { - texture_wants_compressed = true; - } - else { - if (tex->get_compression() == Texture::CM_off) { - // no compression - } - else { - if (tex->get_compression() == Texture::CM_default) { - // default = use "compressed-textures" config setting - if (compressed_textures) { - texture_wants_compressed = true; - } - } - else { - texture_wants_compressed = true; - } - } - } - - switch (tex->get_texture_type()) { - case Texture::TT_1d_texture: - case Texture::TT_2d_texture: - case Texture::TT_cube_map: - // no compression for render target textures, or very small - // textures - if (tex->get_render_to_texture() == false && - orig_width >= 4 && orig_height >= 4) { - if (texture_wants_compressed){ - compress_texture = true; - } - } - break; - case Texture::TT_3d_texture: - // not supported by all video chips - break; - } - - // make sure we handled all the possible cases - nassertr(_d3d_format != D3DFMT_UNKNOWN, false); - - DWORD target_width = orig_width; - DWORD target_height = orig_height; - DWORD target_depth = orig_depth; - - DWORD filter_caps; - - switch (tex->get_texture_type()) { - case Texture::TT_1d_texture: - case Texture::TT_2d_texture: - filter_caps = scrn._d3dcaps.TextureFilterCaps; - - if (target_width > scrn._d3dcaps.MaxTextureWidth) { - target_width = scrn._d3dcaps.MaxTextureWidth; - } - if (target_height > scrn._d3dcaps.MaxTextureHeight) { - target_height = scrn._d3dcaps.MaxTextureHeight; - } - - if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_POW2) { - if (!ISPOW2(target_width)) { - target_width = down_to_power_2(target_width); - } - if (!ISPOW2(target_height)) { - target_height = down_to_power_2(target_height); - } - } - break; - - case Texture::TT_3d_texture: - if ((scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0) { - dxgsg8_cat.warning() - << "3-d textures are not supported by this graphics driver.\n"; - return false; - } - - filter_caps = scrn._d3dcaps.VolumeTextureFilterCaps; - - if (target_width > scrn._d3dcaps.MaxVolumeExtent) { - target_width = scrn._d3dcaps.MaxVolumeExtent; - } - if (target_height > scrn._d3dcaps.MaxVolumeExtent) { - target_height = scrn._d3dcaps.MaxVolumeExtent; - } - if (target_depth > scrn._d3dcaps.MaxVolumeExtent) { - target_depth = scrn._d3dcaps.MaxVolumeExtent; - } - - if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) { - if (!ISPOW2(target_width)) { - target_width = down_to_power_2(target_width); - } - if (!ISPOW2(target_height)) { - target_height = down_to_power_2(target_height); - } - if (!ISPOW2(target_depth)) { - target_depth = down_to_power_2(target_depth); - } - } - break; - - case Texture::TT_cube_map: - if ((scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) == 0) { - dxgsg8_cat.warning() - << "Cube map textures are not supported by this graphics driver.\n"; - return false; - } - - filter_caps = scrn._d3dcaps.CubeTextureFilterCaps; - - if (target_width > scrn._d3dcaps.MaxTextureWidth) { - target_width = scrn._d3dcaps.MaxTextureWidth; - } - - if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) { - if (!ISPOW2(target_width)) { - target_width = down_to_power_2(target_width); - } - } - - target_height = target_width; - break; - } - - // checks for SQUARE reqmt (nvidia riva128 needs this) - if ((target_width != target_height) && - (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0) { - // assume pow2 textures. sum exponents, divide by 2 rounding down - // to get sq size - int i, width_exp, height_exp; - for (i = target_width, width_exp = 0; i > 1; width_exp++, i >>= 1) { - } - for (i = target_height, height_exp = 0; i > 1; height_exp++, i >>= 1) { - } - target_height = target_width = 1<<((width_exp+height_exp)>>1); - } - - bool shrink_original = false; - - if (orig_width != target_width || orig_height != target_height || - orig_depth != target_depth) { - if (tex->get_texture_type() == Texture::TT_3d_texture) { - dxgsg8_cat.info() - << "Reducing size of " << tex->get_name() - << " from " << orig_width << "x" << orig_height << "x" << orig_depth - << " to " << target_width << "x" << target_height - << "x" << target_depth << "\n"; - } else { - dxgsg8_cat.info() - << "Reducing size of " << tex->get_name() - << " from " << orig_width << "x" << orig_height - << " to " << target_width << "x" << target_height << "\n"; - } - - shrink_original = true; - } - - const char *error_message; - - error_message = "create_texture failed: couldn't find compatible device Texture Pixel Format for input texture"; - - if (dxgsg8_cat.is_spam()) { - dxgsg8_cat.spam() - << "create_texture handling target bitdepth: " << target_bpp - << " alphabits: " << num_alpha_bits << endl; - } - - // I could possibly replace some of this logic with - // D3DXCheckTextureRequirements(), but it wouldn't handle all my - // specialized low-memory cases perfectly - -#define CHECK_FOR_FMT(FMT) \ - if (scrn._supported_tex_formats_mask & FMT##_FLAG) { \ - target_pixel_format = D3DFMT_##FMT; \ - goto found_matching_format; } - - if (texture_stored_compressed && compress_texture) { - // if the texture is already compressed, we need to choose the - // corresponding format, otherwise we might end up - // cross-compressing from e.g. DXT5 to DXT3 - switch (compression_mode){ - case Texture::CM_dxt1: - CHECK_FOR_FMT(DXT1); - break; - case Texture::CM_dxt2: - CHECK_FOR_FMT(DXT2); - break; - case Texture::CM_dxt3: - CHECK_FOR_FMT(DXT3); - break; - case Texture::CM_dxt4: - CHECK_FOR_FMT(DXT4); - break; - case Texture::CM_dxt5: - CHECK_FOR_FMT(DXT5); - break; - } - - // We don't support the compressed format. Fall through. - } - - if (compress_texture) { - if (num_alpha_bits <= 1) { - CHECK_FOR_FMT(DXT1); - } else if (num_alpha_bits <= 4) { - CHECK_FOR_FMT(DXT3); - } else { - CHECK_FOR_FMT(DXT5); - } - } - - // We can't compress for some reason, so ensure the uncompressed - // image is ready to load. - if (texture_stored_compressed) { - tex->get_uncompressed_ram_image(); - compression_mode = tex->get_ram_image_compression(); - texture_stored_compressed = compression_mode != Texture::CM_off; - compress_texture = false; - } - - // handle each target bitdepth separately. might be less confusing - // to reorg by num_color_channels (input type) - switch (target_bpp) { - - // IMPORTANT NOTE: - // target_bpp is REQUESTED bpp, not what exists in the texture - // array (the texture array contains num_color_channels*8bits) - - case 32: - if (!((num_color_channels == 3) || (num_color_channels == 4))) - break; //bail - - CHECK_FOR_FMT(A8R8G8B8); - - if (num_alpha_bits>0) { - nassertr(num_color_channels == 4, false); - - // no 32-bit fmt, look for 16 bit w/alpha (1-15) - - // 32 bit RGBA was requested, but only 16 bit alpha fmts are - // avail. By default, convert to 4-4-4-4 which has 4-bit alpha - // for blurry edges. If we know tex only needs 1 bit alpha - // (i.e. for a mask), use 1555 instead. - - - // ConversionType ConvTo1 = Conv32to16_4444, ConvTo2 = Conv32to16_1555; - // DWORD dwAlphaMask1 = 0xF000, dwAlphaMask2 = 0x8000; - - // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify - // 32->16 conversion. This should be true on most cards. - - if (num_alpha_bits == 1) { - CHECK_FOR_FMT(A1R5G5B5); - } - - // normally prefer 4444 due to better alpha channel resolution - CHECK_FOR_FMT(A4R4G4B4); - CHECK_FOR_FMT(A1R5G5B5); - - // At this point, bail. Don't worry about converting to - // non-alpha formats yet, I think this will be a very rare case. - error_message = "create_texture failed: couldn't find compatible Tex DDPIXELFORMAT! no available 16 or 32-bit alpha formats!"; - } else { - // convert 3 or 4 channel to closest 16bpp color fmt - - if (num_color_channels == 3) { - CHECK_FOR_FMT(R5G6B5); - CHECK_FOR_FMT(X1R5G5B5); - } else { - CHECK_FOR_FMT(R5G6B5); - CHECK_FOR_FMT(X1R5G5B5); - } - } - break; - - case 24: - nassertr(num_color_channels == 3, false); - - CHECK_FOR_FMT(R8G8B8); - - // no 24-bit fmt. look for 32 bit fmt (note: this is - // memory-hogging choice instead I could look for - // memory-conserving 16-bit fmt). - - CHECK_FOR_FMT(X8R8G8B8); - CHECK_FOR_FMT(A8R8G8B8); - - // no 24-bit or 32 fmt. look for 16 bit fmt (higher res 565 1st) - CHECK_FOR_FMT(R5G6B5); - CHECK_FOR_FMT(X1R5G5B5); - CHECK_FOR_FMT(A1R5G5B5); - break; - - case 16: - if (needs_luminance) { - nassertr(num_alpha_bits > 0, false); - nassertr(num_color_channels == 2, false); - - CHECK_FOR_FMT(A8L8); - CHECK_FOR_FMT(A8R8G8B8); - - if (num_alpha_bits == 1) { - CHECK_FOR_FMT(A1R5G5B5); - } - - // normally prefer 4444 due to better alpha channel resolution - CHECK_FOR_FMT(A4R4G4B4); - CHECK_FOR_FMT(A1R5G5B5); - } else { - nassertr((num_color_channels == 3)||(num_color_channels == 4), false); - // look for compatible 16bit fmts, if none then give up - // (don't worry about other bitdepths for 16 bit) - switch(num_alpha_bits) { - case 0: - if (num_color_channels == 3) { - CHECK_FOR_FMT(R5G6B5); - CHECK_FOR_FMT(X1R5G5B5); - } else { - nassertr(num_color_channels == 4, false); - // it could be 4 if user asks us to throw away the alpha channel - CHECK_FOR_FMT(R5G6B5); - CHECK_FOR_FMT(X1R5G5B5); - } - break; - case 1: - // app specifically requests 1-5-5-5 F_rgba5 case, where you - // explicitly want 1-5-5-5 fmt, as opposed to F_rgbm, which - // could use 32bpp ARGB. fail if this particular fmt not - // avail. - nassertr(num_color_channels == 4, false); - CHECK_FOR_FMT(X1R5G5B5); - break; - case 4: - // app specifically requests 4-4-4-4 F_rgba4 case, as opposed - // to F_rgba, which could use 32bpp ARGB - nassertr(num_color_channels == 4, false); - CHECK_FOR_FMT(A4R4G4B4); - break; - default: - nassertr(false, false); // problem in get_bits_per_pixel()? - } - } - case 8: - if (needs_luminance) { - // don't bother handling those other 8bit lum fmts like 4-4, - // since 16 8-8 is usually supported too - nassertr(num_color_channels == 1, false); - - // look for native lum fmt first - CHECK_FOR_FMT(L8); - CHECK_FOR_FMT(L8); - - CHECK_FOR_FMT(R8G8B8); - CHECK_FOR_FMT(X8R8G8B8); - - CHECK_FOR_FMT(R5G6B5); - CHECK_FOR_FMT(X1R5G5B5); - - } else if (num_alpha_bits == 8) { - // look for 16bpp A8L8, else 32-bit ARGB, else 16-4444. - - // skip 8bit alpha only (D3DFMT_A8), because I think only voodoo - // supports it and the voodoo support isn't the kind of blending - // model we need somehow (is it that voodoo assumes color is - // white? isnt that what we do in ConvAlpha8to32 anyway?) - - CHECK_FOR_FMT(A8L8); - CHECK_FOR_FMT(A8R8G8B8); - CHECK_FOR_FMT(A4R4G4B4); - } - break; - - default: - error_message = "create_texture failed: unhandled pixel bitdepth in DX loader"; - } - - // if we've gotten here, haven't found a match - dxgsg8_cat.error() - << error_message << ": " << tex->get_name() << endl - << "NumColorChannels: " << num_color_channels << "; NumAlphaBits: " - << num_alpha_bits << "; targetbpp: " <get_match_framebuffer_format()) { - // Instead of creating a texture with the found format, we will - // need to make one that exactly matches the framebuffer's - // format. Look up what that format is. - IDirect3DSurface8 *render_target; - hr = scrn._d3d_device->GetRenderTarget(&render_target); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "GetRenderTgt failed in create_texture: " << D3DERRORSTRING(hr); - } else { - D3DSURFACE_DESC surface_desc; - hr = render_target->GetDesc(&surface_desc); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "GetDesc failed in create_texture: " << D3DERRORSTRING(hr); - } else { - if (target_pixel_format != surface_desc.Format) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "Chose format " << D3DFormatStr(surface_desc.Format) - << " instead of " << D3DFormatStr(target_pixel_format) - << " for texture to match framebuffer.\n"; - } - target_pixel_format = surface_desc.Format; - } - } - SAFE_RELEASE(render_target); - } - } - - // validate magfilter setting - // degrade filtering if no HW support - - SamplerState::FilterType ft; - - ft = tex->get_magfilter(); - if ((ft != SamplerState::FT_linear) && ft != SamplerState::FT_nearest) { - // mipmap settings make no sense for magfilter - if (ft == SamplerState::FT_nearest_mipmap_nearest) { - ft = SamplerState::FT_nearest; - } else { - ft = SamplerState::FT_linear; - } - } - - if (ft == SamplerState::FT_linear && - (filter_caps & D3DPTFILTERCAPS_MAGFLINEAR) == 0) { - ft = SamplerState::FT_nearest; - } - tex->set_magfilter(ft); - - // figure out if we are mipmapping this texture - ft = tex->get_minfilter(); - _has_mipmaps = false; - - if (!dx_ignore_mipmaps) { // set if no HW mipmap capable - switch(ft) { - case SamplerState::FT_nearest_mipmap_nearest: - case SamplerState::FT_linear_mipmap_nearest: - case SamplerState::FT_nearest_mipmap_linear: // pick nearest in each, interpolate linearly b/w them - case SamplerState::FT_linear_mipmap_linear: - _has_mipmaps = true; - } - - if (dx_mipmap_everything) { // debug toggle, ok to leave in since its just a creation cost - _has_mipmaps = true; - if (dxgsg8_cat.is_spam()) { - if (ft != SamplerState::FT_linear_mipmap_linear) { - dxgsg8_cat.spam() - << "Forcing trilinear mipmapping on DX texture [" - << tex->get_name() << "]\n"; - } - } - ft = SamplerState::FT_linear_mipmap_linear; - tex->set_minfilter(ft); - } - - } else if ((ft == SamplerState::FT_nearest_mipmap_nearest) || // cvt to no-mipmap filter types - (ft == SamplerState::FT_nearest_mipmap_linear)) { - ft = SamplerState::FT_nearest; - - } else if ((ft == SamplerState::FT_linear_mipmap_nearest) || - (ft == SamplerState::FT_linear_mipmap_linear)) { - ft = SamplerState::FT_linear; - } - - nassertr((filter_caps & D3DPTFILTERCAPS_MINFPOINT) != 0, false); - -#define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR) - - // do any other filter type degradations necessary - switch(ft) { - case SamplerState::FT_linear_mipmap_linear: - if ((filter_caps & TRILINEAR_MIPMAP_TEXFILTERCAPS) != TRILINEAR_MIPMAP_TEXFILTERCAPS) { - if (filter_caps & D3DPTFILTERCAPS_MINFLINEAR) { - ft = SamplerState::FT_linear_mipmap_nearest; - } else { - // if you cant do linear in a level, you probably cant do - // linear b/w levels, so just do nearest-all - ft = SamplerState::FT_nearest_mipmap_nearest; - } - } - break; - - case SamplerState::FT_nearest_mipmap_linear: - // if we don't have bilinear, do nearest_nearest - if (!((filter_caps & D3DPTFILTERCAPS_MIPFPOINT) && - (filter_caps & D3DPTFILTERCAPS_MINFLINEAR))) { - ft = SamplerState::FT_nearest_mipmap_nearest; - } - break; - - case SamplerState::FT_linear_mipmap_nearest: - // if we don't have mip linear, do nearest_nearest - if (!(filter_caps & D3DPTFILTERCAPS_MIPFLINEAR)) { - ft = SamplerState::FT_nearest_mipmap_nearest; - } - break; - - case SamplerState::FT_linear: - if (!(filter_caps & D3DPTFILTERCAPS_MINFLINEAR)) { - ft = SamplerState::FT_nearest; - } - break; - } - - tex->set_minfilter(ft); - - uint aniso_degree; - - aniso_degree = 1; - if (scrn._d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) { - aniso_degree = tex->get_anisotropic_degree(); - if ((aniso_degree>scrn._d3dcaps.MaxAnisotropy) || - dx_force_anisotropic_filtering) { - aniso_degree = scrn._d3dcaps.MaxAnisotropy; - } - } - tex->set_anisotropic_degree(aniso_degree); - -#ifdef _DEBUG - dxgsg8_cat.spam() - << "create_texture: setting aniso degree for " << tex->get_name() - << " to: " << aniso_degree << endl; -#endif - - UINT mip_level_count; - - if (_has_mipmaps) { - tex->get_ram_image(); - mip_level_count = tex->get_num_loadable_ram_mipmap_images(); - if (mip_level_count < 2) { - // tell CreateTex to alloc space for all mip levels down to 1x1 - mip_level_count = 0; - - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "create_texture: generating mipmaps for " << tex->get_name() - << endl; - } - } - } else { - mip_level_count = 1; - } - - DWORD usage; - D3DPOOL pool; - - usage = 0; - if (tex->get_render_to_texture ()) { - // REQUIRED - pool = D3DPOOL_DEFAULT; - if (support_render_texture && scrn._dxgsg8 -> get_supports_render_texture ( )) { - usage |= D3DUSAGE_RENDERTARGET; - } - } - else { - pool = D3DPOOL_MANAGED; - } - - switch (tex->get_texture_type()) { - case Texture::TT_1d_texture: - case Texture::TT_2d_texture: - hr = scrn._d3d_device->CreateTexture - (target_width, target_height, mip_level_count, usage, - target_pixel_format, pool, &_d3d_2d_texture); - _d3d_texture = _d3d_2d_texture; - break; - - case Texture::TT_3d_texture: - hr = scrn._d3d_device->CreateVolumeTexture - (target_width, target_height, target_depth, mip_level_count, usage, - target_pixel_format, pool, &_d3d_volume_texture); - _d3d_texture = _d3d_volume_texture; - break; - - case Texture::TT_cube_map: - hr = scrn._d3d_device->CreateCubeTexture - (target_width, mip_level_count, usage, - target_pixel_format, pool, &_d3d_cube_texture); - _d3d_texture = _d3d_cube_texture; - break; - } - - if (FAILED(hr)) { - dxgsg8_cat.error() - << "D3D create_texture failed!" << D3DERRORSTRING(hr); - goto error_exit; - } - - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "create_texture: " << tex->get_name() - << " converting panda equivalent of " << D3DFormatStr(_d3d_format) - << " => " << D3DFormatStr(target_pixel_format) << endl; - } - - hr = fill_d3d_texture_pixels(scrn); - if (FAILED(hr)) { - goto error_exit; - } - - if (tex->get_post_load_store_cache()) { - tex->set_post_load_store_cache(false); - // OK, get the RAM image, and save it in a BamCache record. - if (extract_texture_data()) { - if (tex->has_ram_image()) { - BamCache *cache = BamCache::get_global_ptr(); - PT(BamCacheRecord) record = cache->lookup(tex->get_fullpath(), "txo"); - if (record != (BamCacheRecord *)NULL) { - record->set_data(tex, tex); - cache->store(record); - } - } - } - } - - scrn._dxgsg8->get_engine()->texture_uploaded(tex); - mark_loaded(); - return true; - - error_exit: - - RELEASE(_d3d_texture, dxgsg8, "texture", RELEASE_ONCE); - _d3d_2d_texture = NULL; - _d3d_volume_texture = NULL; - _d3d_cube_texture = NULL; - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::create_simple_texture -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -bool DXTextureContext8:: -create_simple_texture(DXScreenData &scrn) { - nassertr(IS_VALID_PTR(get_texture()), false); - - HRESULT hr; - - delete_texture(); - - _d3d_format = D3DFMT_A8R8G8B8; - D3DFORMAT target_pixel_format = D3DFMT_A8R8G8B8; - DWORD target_bpp = 32; - DWORD num_color_channels = 4; - - DWORD target_width = (DWORD)get_texture()->get_simple_x_size(); - DWORD target_height = (DWORD)get_texture()->get_simple_y_size(); - DWORD mip_level_count = 1; - DWORD usage = 0; - D3DPOOL pool = D3DPOOL_MANAGED; - - int data_size = target_width * target_height * 4; - - hr = scrn._d3d_device->CreateTexture - (target_width, target_height, mip_level_count, usage, - target_pixel_format, pool, &_d3d_2d_texture); - _d3d_texture = _d3d_2d_texture; - if (FAILED(hr)) { - dxgsg8_cat.error() - << "D3D create_simple_texture failed!" << D3DERRORSTRING(hr); - dxgsg8_cat.error() - << " width = " << target_width << " height = " << target_height << " target_pixel_format = " << target_pixel_format << "\n"; - - goto error_exit; - } - - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "create_simple_texture: " << get_texture()->get_name() - << "\n"; - } - - { - CPTA_uchar image = get_texture()->get_simple_ram_image(); - - hr = -1; - // hr = fill_d3d_texture_pixels(scrn); - - IDirect3DSurface8 *surface = NULL; - _d3d_2d_texture->GetSurfaceLevel(0, &surface); - - RECT source_size; - source_size.left = source_size.top = 0; - source_size.right = target_width; - source_size.bottom = target_height; - - DWORD mip_filter = D3DX_FILTER_LINEAR; - - hr = D3DXLoadSurfaceFromMemory - (surface, (PALETTEENTRY*)NULL, (RECT*)NULL, (LPCVOID)image.p(), - target_pixel_format, target_width * 4, (PALETTEENTRY*)NULL, - &source_size, mip_filter, (D3DCOLOR)0x0); - - RELEASE(surface, dxgsg8, "create_simple_texture Surface", RELEASE_ONCE); - } - - if (FAILED(hr)) { - dxgsg8_cat.debug () - << "*** fill_d3d_texture_pixels failed ***: format " - << target_pixel_format - << "\n"; - - goto error_exit; - } - - mark_simple_loaded(); - return true; - - error_exit: - RELEASE(_d3d_texture, dxgsg8, "texture", RELEASE_ONCE); - _d3d_2d_texture = NULL; - _d3d_volume_texture = NULL; - _d3d_cube_texture = NULL; - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::delete_texture -// Access: Public -// Description: Release the surface used to store the texture -//////////////////////////////////////////////////////////////////// -void DXTextureContext8:: -delete_texture() { - if (_d3d_texture == NULL) { - // don't bother printing the msg below, since we already released it. - return; - } - - RELEASE(_d3d_texture, dxgsg8, "texture", RELEASE_ONCE); - _d3d_2d_texture = NULL; - _d3d_volume_texture = NULL; - _d3d_cube_texture = NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::extract_texture_data -// Access: Public -// Description: This method will be called in the draw thread to -// download the texture memory's image into its -// ram_image value. It returns true on success, false -// otherwise. -//////////////////////////////////////////////////////////////////// -bool DXTextureContext8:: -extract_texture_data() { - HRESULT hr; - - Texture *tex = get_texture(); - if (tex->get_texture_type() != Texture::TT_2d_texture) { - dxgsg8_cat.error() - << "Not supported: extract_texture_data for " << tex->get_texture_type() - << "\n"; - return false; - } - nassertr(IS_VALID_PTR(_d3d_2d_texture), false); - - D3DSURFACE_DESC desc; - hr = _d3d_2d_texture->GetLevelDesc(0, &desc); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "Texture::GetLevelDesc() failed!" << D3DERRORSTRING(hr); - return false; - } - - int div = 1; - Texture::Format format = Texture::F_rgba; - Texture::CompressionMode compression = Texture::CM_off; - - switch (desc.Format) { - case D3DFMT_R8G8B8: - format = Texture::F_rgb; - break; - - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - break; - - case D3DFMT_L8: - format = Texture::F_luminance; - break; - - case D3DFMT_A8L8: - format = Texture::F_luminance_alpha; - break; - - case D3DFMT_DXT1: - compression = Texture::CM_dxt1; - div = 4; - break; - case D3DFMT_DXT2: - compression = Texture::CM_dxt2; - div = 4; - break; - case D3DFMT_DXT3: - compression = Texture::CM_dxt3; - div = 4; - break; - case D3DFMT_DXT4: - compression = Texture::CM_dxt4; - div = 4; - break; - case D3DFMT_DXT5: - compression = Texture::CM_dxt5; - div = 4; - break; - - default: - dxgsg8_cat.error() - << "Cannot extract texture data: unhandled surface format " - << desc.Format << "\n"; - return false; - } - - int num_levels = _d3d_2d_texture->GetLevelCount(); - - tex->set_x_size(desc.Width); - tex->set_y_size(desc.Height); - tex->set_z_size(1); - tex->set_component_type(Texture::T_unsigned_byte); - tex->set_format(format); - tex->clear_ram_image(); - - for (int n = 0; n < num_levels; ++n) { - D3DLOCKED_RECT rect; - hr = _d3d_2d_texture->LockRect(n, &rect, NULL, D3DLOCK_READONLY); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "Texture::LockRect() failed!" << D3DERRORSTRING(hr); - return false; - } - - int x_size = tex->get_expected_mipmap_x_size(n); - int y_size = tex->get_expected_mipmap_y_size(n); - PTA_uchar image; - - if (compression == Texture::CM_off) { - // Uncompressed, but we have to respect the pitch. - int pitch = x_size * tex->get_num_components() * tex->get_component_width(); - pitch = min(pitch, (int)rect.Pitch); - int size = pitch * y_size; - image = PTA_uchar::empty_array(size); - if (pitch == rect.Pitch) { - // Easy copy. - memcpy(image.p(), rect.pBits, size); - } else { - // Harder copy: we have to de-interleave DirectX's extra bytes - // on the end of each row. - unsigned char *dest = image.p(); - unsigned char *source = (unsigned char *)rect.pBits; - for (int yi = 0; yi < y_size; ++yi) { - memcpy(dest, source, pitch); - dest += pitch; - source += rect.Pitch; - } - } - - } else { - // Compressed; just copy the data verbatim. - int size = rect.Pitch * (y_size / div); - image = PTA_uchar::empty_array(size); - memcpy(image.p(), rect.pBits, size); - } - - _d3d_2d_texture->UnlockRect(n); - if (n == 0) { - tex->set_ram_image(image, compression); - } else { - tex->set_ram_mipmap_image(n, image); - } - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::d3d_surface_to_texture -// Access: Public, Static -// Description: copies source_rect in pD3DSurf to upper left of -// texture -//////////////////////////////////////////////////////////////////// -HRESULT DXTextureContext8:: -d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, - bool inverted, Texture *result, int view, int z) { - - // still need custom conversion since d3d/d3dx has no way to convert - // arbitrary fmt to ARGB in-memory user buffer - - HRESULT hr; - DWORD num_components = result->get_num_components(); - - nassertr(result->get_component_width() == sizeof(BYTE), E_FAIL); // cant handle anything else now - nassertr(result->get_component_type() == Texture::T_unsigned_byte, E_FAIL); // cant handle anything else now - nassertr((num_components == 3) || (num_components == 4), E_FAIL); // cant handle anything else now - nassertr(IS_VALID_PTR(d3d_surface), E_FAIL); - - BYTE *buf = result->modify_ram_image(); - if (z >= 0) { - nassertr(z < result->get_z_size(), E_FAIL); - buf += z * result->get_expected_ram_page_size(); - } - if (view > 0) { - buf += (view * result->get_z_size()) * result->get_expected_ram_page_size(); - } - - if (IsBadWritePtr(d3d_surface, sizeof(DWORD))) { - dxgsg8_cat.error() - << "d3d_surface_to_texture failed: bad pD3DSurf ptr value (" - << ((void*)d3d_surface) << ")\n"; - exit(1); - } - - DWORD x_window_offset, y_window_offset; - DWORD copy_width, copy_height; - - D3DLOCKED_RECT locked_rect; - D3DSURFACE_DESC surface_desc; - - hr = d3d_surface->GetDesc(&surface_desc); - - x_window_offset = source_rect.left, y_window_offset = source_rect.top; - copy_width = RECT_XSIZE(source_rect); - copy_height = RECT_YSIZE(source_rect); - - // make sure there's enough space in the texture, its size must - // match (especially xsize) or scanlines will be too long - - if (!((copy_width == result->get_x_size()) && (copy_height <= (DWORD)result->get_y_size()))) { - dxgsg8_cat.error() - << "d3d_surface_to_texture, Texture size (" << result->get_x_size() - << ", " << result->get_y_size() - << ") too small to hold display surface (" - << copy_width << ", " << copy_height << ")\n"; - nassertr(false, E_FAIL); - return E_FAIL; - } - - hr = d3d_surface->LockRect(&locked_rect, (CONST RECT*)NULL, (D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE)); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "d3d_surface_to_texture LockRect() failed!" << D3DERRORSTRING(hr); - return hr; - } - - // ones not listed not handled yet - nassertr((surface_desc.Format == D3DFMT_A8R8G8B8) || - (surface_desc.Format == D3DFMT_X8R8G8B8) || - (surface_desc.Format == D3DFMT_R8G8B8) || - (surface_desc.Format == D3DFMT_R5G6B5) || - (surface_desc.Format == D3DFMT_X1R5G5B5) || - (surface_desc.Format == D3DFMT_A1R5G5B5) || - (surface_desc.Format == D3DFMT_A4R4G4B4), E_FAIL); - - //buf contains raw ARGB in Texture byteorder - - int byte_pitch = locked_rect.Pitch; - BYTE *surface_bytes = (BYTE *)locked_rect.pBits; - - if (inverted) { - surface_bytes += byte_pitch * (y_window_offset + copy_height - 1); - byte_pitch = -byte_pitch; - } else { - surface_bytes += byte_pitch * y_window_offset; - } - - // writes out last line in DDSurf first in PixelBuf, so Y line order - // precedes inversely - - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "d3d_surface_to_texture converting " - << D3DFormatStr(surface_desc.Format) - << " DDSurf to " << num_components << "-channel panda Texture\n"; - } - - DWORD *dest_word = (DWORD *)buf; - BYTE *dest_byte = (BYTE *)buf; - - switch(surface_desc.Format) { - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: { - if (num_components == 4) { - DWORD *source_word; - BYTE *dest_line = (BYTE*)dest_word; - - for (DWORD y = 0; y < copy_height; y++) { - source_word = ((DWORD*)surface_bytes) + x_window_offset; - memcpy(dest_line, source_word, byte_pitch); - dest_line += byte_pitch; - surface_bytes += byte_pitch; - } - } else { - // 24bpp texture case (numComponents == 3) - DWORD *source_word; - for (DWORD y = 0; y < copy_height; y++) { - source_word = ((DWORD*)surface_bytes) + x_window_offset; - - for (DWORD x = 0; x < copy_width; x++) { - BYTE r, g, b; - DWORD pixel = *source_word; - - r = (BYTE)((pixel>>16) & g_LowByteMask); - g = (BYTE)((pixel>> 8) & g_LowByteMask); - b = (BYTE)((pixel ) & g_LowByteMask); - - *dest_byte++ = b; - *dest_byte++ = g; - *dest_byte++ = r; - source_word++; - } - surface_bytes += byte_pitch; - } - } - break; - } - - case D3DFMT_R8G8B8: { - BYTE *source_byte; - - if (num_components == 4) { - for (DWORD y = 0; y < copy_height; y++) { - source_byte = surface_bytes + x_window_offset * 3 * sizeof(BYTE); - for (DWORD x = 0; x < copy_width; x++) { - DWORD r, g, b; - - b = *source_byte++; - g = *source_byte++; - r = *source_byte++; - - *dest_word = 0xFF000000 | (r << 16) | (g << 8) | b; - dest_word++; - } - surface_bytes += byte_pitch; - } - } else { - // 24bpp texture case (numComponents == 3) - for (DWORD y = 0; y < copy_height; y++) { - source_byte = surface_bytes + x_window_offset * 3 * sizeof(BYTE); - memcpy(dest_byte, source_byte, byte_pitch); - dest_byte += byte_pitch; - surface_bytes += byte_pitch; - } - } - break; - } - - case D3DFMT_R5G6B5: - case D3DFMT_X1R5G5B5: - case D3DFMT_A1R5G5B5: - case D3DFMT_A4R4G4B4: { - WORD *source_word; - // handle 0555, 1555, 0565, 4444 in same loop - - BYTE redshift, greenshift, blueshift; - DWORD redmask, greenmask, bluemask; - - if (surface_desc.Format == D3DFMT_R5G6B5) { - redshift = (11-3); - redmask = 0xF800; - greenmask = 0x07E0; - greenshift = (5-2); - bluemask = 0x001F; - blueshift = 3; - } else if (surface_desc.Format == D3DFMT_A4R4G4B4) { - redmask = 0x0F00; - redshift = 4; - greenmask = 0x00F0; - greenshift = 0; - bluemask = 0x000F; - blueshift = 4; - } else { // 1555 or x555 - redmask = 0x7C00; - redshift = (10-3); - greenmask = 0x03E0; - greenshift = (5-3); - bluemask = 0x001F; - blueshift = 3; - } - - if (num_components == 4) { - // Note: these 16bpp loops ignore input alpha completely (alpha - // is set to fully opaque in texture!) - - // if we need to capture alpha, probably need to make separate - // loops for diff 16bpp fmts for best speed - - for (DWORD y = 0; y < copy_height; y++) { - source_word = ((WORD*)surface_bytes) + x_window_offset; - for (DWORD x = 0; x < copy_width; x++) { - WORD pixel = *source_word; - BYTE r, g, b; - - b = (pixel & bluemask) << blueshift; - g = (pixel & greenmask) >> greenshift; - r = (pixel & redmask) >> redshift; - - // alpha is just set to 0xFF - - *dest_word = 0xFF000000 | (r << 16) | (g << 8) | b; - source_word++; - dest_word++; - } - surface_bytes += byte_pitch; - } - } else { - // 24bpp texture case (numComponents == 3) - for (DWORD y = 0; y < copy_height; y++) { - source_word = ((WORD*)surface_bytes) + x_window_offset; - for (DWORD x = 0; x < copy_width; x++) { - WORD pixel = *source_word; - BYTE r, g, b; - - b = (pixel & bluemask) << blueshift; - g = (pixel & greenmask) >> greenshift; - r = (pixel & redmask) >> redshift; - - *dest_byte++ = b; - *dest_byte++ = g; - *dest_byte++ = r; - - source_word++; - } - surface_bytes += byte_pitch; - } - } - break; - } - - default: - dxgsg8_cat.error() - << "d3d_surface_to_texture: unsupported D3DFORMAT!\n"; - } - - d3d_surface->UnlockRect(); - return S_OK; -} - -//////////////////////////////////////////////////////////////////// -// Function: calculate_row_byte_length -// Access: Private, hidden -// Description: local helper function, which calculates the -// 'row_byte_length' or 'pitch' needed for calling -// D3DXLoadSurfaceFromMemory. -// Takes compressed formats (DXTn) into account. -//////////////////////////////////////////////////////////////////// -static UINT calculate_row_byte_length (int width, int num_color_channels, D3DFORMAT tex_format) -{ - UINT source_row_byte_length = 0; - - // check for compressed textures and adjust source_row_byte_length and source_format accordingly - switch (tex_format) { - case D3DFMT_DXT1: - // for dxt1 compressed textures, the row_byte_lenght is "the width of one row of cells, in bytes" - // cells are 4 pixels wide, take up 8 bytes, and at least 1 cell has to be there. - source_row_byte_length = max(1,width / 4)*8; - break; - case D3DFMT_DXT2: - case D3DFMT_DXT3: - case D3DFMT_DXT4: - case D3DFMT_DXT5: - // analogue as above, but cells take up 16 bytes - source_row_byte_length = max(1,width / 4)*16; - break; - default: - // no known compression format.. usual calculation - source_row_byte_length = width*num_color_channels; - break; - } - return source_row_byte_length; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::fill_d3d_texture_mipmap_pixels -// Access: Private -// Description: Called from fill_d3d_texture_pixels, this function -// fills a single mipmap with texture data. -// Takes care of all necessery conversions and error -// handling. -//////////////////////////////////////////////////////////////////// -HRESULT DXTextureContext8::fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_format) -{ - // This whole function was refactored out of fill_d3d_texture_pixels to make the code - // more readable and to avoid code duplication. - IDirect3DSurface8 *mip_surface = NULL; - bool using_temp_buffer = false; - HRESULT hr = E_FAIL; - CPTA_uchar image = get_texture()->get_ram_mipmap_image(mip_level); - nassertr(!image.is_null(), E_FAIL); - BYTE *pixels = (BYTE*) image.p(); - DWORD width = (DWORD) get_texture()->get_expected_mipmap_x_size(mip_level); - DWORD height = (DWORD) get_texture()->get_expected_mipmap_y_size(mip_level); - int component_width = get_texture()->get_component_width(); - - pixels += depth_index * get_texture()->get_expected_ram_mipmap_page_size(mip_level); - - if (get_texture()->get_texture_type() == Texture::TT_cube_map) { - nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL); - hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)depth_index, mip_level, &mip_surface); - } else { - nassertr(IS_VALID_PTR(_d3d_2d_texture), E_FAIL); - hr = _d3d_2d_texture->GetSurfaceLevel(mip_level, &mip_surface); - } - - if (FAILED(hr)) { - dxgsg8_cat.error() - << "FillDDTextureMipmapPixels failed for " << get_texture()->get_name() - << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr); - return E_FAIL; - } - - RECT source_size; - source_size.left = source_size.top = 0; - source_size.right = width; - source_size.bottom = height; - - UINT source_row_byte_length = calculate_row_byte_length(width, get_texture()->get_num_components(), source_format); - - DWORD mip_filter; - // need filtering if size changes, (also if bitdepth reduced (need - // dithering)??) - mip_filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER; //dithering looks ugly on i810 for 4444 textures - - // D3DXLoadSurfaceFromMemory will load black luminance and we want - // full white, so convert to explicit luminance-alpha format - if (_d3d_format == D3DFMT_A8) { - // alloc buffer for explicit D3DFMT_A8L8 - USHORT *temp_buffer = new USHORT[width * height]; - if (!IS_VALID_PTR(temp_buffer)) { - dxgsg8_cat.error() - << "FillDDTextureMipmapPixels couldnt alloc mem for temp pixbuf!\n"; - goto exit_FillMipmapSurf; - } - using_temp_buffer = true; - - USHORT *out_pixels = temp_buffer; - BYTE *source_pixels = pixels + component_width - 1; - for (UINT y = 0; y < height; y++) { - for (UINT x = 0; x < width; x++, source_pixels += component_width, out_pixels++) { - // add full white, which is our interpretation of alpha-only - // (similar to default adding full opaque alpha 0xFF to - // RGB-only textures) - *out_pixels = ((*source_pixels) << 8 ) | 0xFF; - } - } - - source_format = D3DFMT_A8L8; - source_row_byte_length = width * sizeof(USHORT); - pixels = (BYTE*)temp_buffer; - } - else if (component_width != 1) { - // Convert from 16-bit per channel (or larger) format down to - // 8-bit per channel. This throws away precision in the - // original image, but dx8 doesn't support high-precision images - // anyway. - - int num_components = get_texture()->get_num_components(); - int num_pixels = width * height * num_components; - BYTE *temp_buffer = new BYTE[num_pixels]; - if (!IS_VALID_PTR(temp_buffer)) { - dxgsg8_cat.error() << "FillDDTextureMipmapPixels couldnt alloc mem for temp pixbuf!\n"; - goto exit_FillMipmapSurf; - } - using_temp_buffer = true; - - BYTE *source_pixels = pixels + component_width - 1; - for (int i = 0; i < num_pixels; i++) { - temp_buffer[i] = *source_pixels; - source_pixels += component_width; - } - pixels = (BYTE*)temp_buffer; - } - - // filtering may be done here if texture if targetsize != origsize -#ifdef DO_PSTATS - GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_row_byte_length * height); -#endif - hr = D3DXLoadSurfaceFromMemory - (mip_surface, (PALETTEENTRY*)NULL, (RECT*)NULL, (LPCVOID)pixels, - source_format, source_row_byte_length, (PALETTEENTRY*)NULL, - &source_size, mip_filter, (D3DCOLOR)0x0); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "FillDDTextureMipmapPixels failed for " << get_texture()->get_name() - << ", mip_level " << mip_level - << ", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr); - } - -exit_FillMipmapSurf: - if (using_temp_buffer) { - SAFE_DELETE_ARRAY(pixels); - } - - RELEASE(mip_surface, dxgsg8, "FillDDTextureMipmapPixels MipSurface texture ptr", RELEASE_ONCE); - return hr; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::fill_d3d_texture_pixels -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -HRESULT DXTextureContext8:: -fill_d3d_texture_pixels(DXScreenData &scrn) { - Texture *tex = get_texture(); - nassertr(IS_VALID_PTR(tex), E_FAIL); - if (tex->get_texture_type() == Texture::TT_3d_texture) { - return fill_d3d_volume_texture_pixels(scrn); - } - - HRESULT hr = E_FAIL; - nassertr(IS_VALID_PTR(tex), E_FAIL); - - CPTA_uchar image; - if (scrn._dxgsg8->get_supports_compressed_texture()) { - image = tex->get_ram_image(); - } else { - image = tex->get_uncompressed_ram_image(); - } - - Texture::CompressionMode image_compression; - if (image.is_null()) { - image_compression = Texture::CM_off; - } else { - image_compression = tex->get_ram_image_compression(); - } - - if (!scrn._dxgsg8->get_supports_compressed_texture_format(image_compression)) { - image = tex->get_uncompressed_ram_image(); - image_compression = Texture::CM_off; - } - if (image.is_null()) { - // The texture doesn't have an image to load. That's ok; it - // might be a texture we've rendered to by frame buffer - // operations or something. - return S_OK; - } - nassertr(IS_VALID_PTR((BYTE*)image.p()), E_FAIL); - nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL); - - PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector); - - DWORD orig_depth = (DWORD) tex->get_z_size(); - D3DFORMAT source_format = _d3d_format; - - // check for compressed textures and adjust source_format accordingly - switch (image_compression) { - case Texture::CM_dxt1: - source_format = D3DFMT_DXT1; - break; - case Texture::CM_dxt2: - source_format = D3DFMT_DXT2; - break; - case Texture::CM_dxt3: - source_format = D3DFMT_DXT3; - break; - case Texture::CM_dxt4: - source_format = D3DFMT_DXT4; - break; - case Texture::CM_dxt5: - source_format = D3DFMT_DXT5; - break; - default: - // no known compression format.. no adjustment - break; - } - - for (unsigned int di = 0; di < orig_depth; di++) { - - // fill top level mipmap - hr = fill_d3d_texture_mipmap_pixels(0, di, source_format); - if (FAILED(hr)) { - return hr; // error message was already output in fill_d3d_texture_mipmap_pixels - } - - if (_has_mipmaps) { - // if we have pre-calculated mipmap levels, use them, otherwise generate on the fly - int miplevel_count = _d3d_2d_texture->GetLevelCount(); // what if it's not a 2d texture? - if (miplevel_count <= tex->get_num_loadable_ram_mipmap_images()) { - dxgsg8_cat.debug() - << "Using pre-calculated mipmap levels for texture " << tex->get_name() << "\n"; - - for (int mip_level = 1; mip_level < miplevel_count; ++mip_level) { - hr = fill_d3d_texture_mipmap_pixels(mip_level, di, source_format); - if (FAILED(hr)) { - return hr; // error message was already output in fill_d3d_texture_mipmap_pixels - } - } - } - else { - // mipmaps need to be generated. - - DWORD mip_filter_flags; - if (!dx_use_triangle_mipgen_filter) { - mip_filter_flags = D3DX_FILTER_BOX; - } else { - mip_filter_flags = D3DX_FILTER_TRIANGLE; - } - - // mip_filter_flags |= D3DX_FILTER_DITHER; - hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0, - mip_filter_flags); - - if (FAILED(hr)) { - dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << tex->get_name() - << ", D3DXFilterTex failed" << D3DERRORSTRING(hr); - } - } - } - } - - return hr; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::fill_d3d_volume_texture_pixels -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -HRESULT DXTextureContext8:: -fill_d3d_volume_texture_pixels(DXScreenData &scrn) { - Texture *tex = get_texture(); - HRESULT hr = E_FAIL; - nassertr(IS_VALID_PTR(tex), E_FAIL); - - CPTA_uchar image; - if (scrn._dxgsg8->get_supports_compressed_texture()) { - image = tex->get_ram_image(); - } else { - image = tex->get_uncompressed_ram_image(); - } - - Texture::CompressionMode image_compression; - if (image.is_null()) { - image_compression = Texture::CM_off; - } else { - image_compression = tex->get_ram_image_compression(); - } - - if (!scrn._dxgsg8->get_supports_compressed_texture_format(image_compression) || - tex->get_x_size() < 4 || tex->get_y_size() < 4) { - // If we don't support this particular compression method, or in - // any case if the texture is too small (DirectX won't accept a - // small compressed texture), then fetch and load the uncompressed - // version instead. - image = tex->get_uncompressed_ram_image(); - image_compression = Texture::CM_off; - } - - if (image.is_null()) { - // The texture doesn't have an image to load. That's ok; it - // might be a texture we've rendered to by frame buffer - // operations or something. - return S_OK; - } - - PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector); - - nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL); - nassertr(tex->get_texture_type() == Texture::TT_3d_texture, E_FAIL); - - DWORD orig_width = (DWORD) tex->get_x_size(); - DWORD orig_height = (DWORD) tex->get_y_size(); - DWORD orig_depth = (DWORD) tex->get_z_size(); - DWORD num_color_channels = tex->get_num_components(); - D3DFORMAT source_format = _d3d_format; - BYTE *image_pixels = (BYTE*)image.p(); - int component_width = tex->get_component_width(); - - nassertr(IS_VALID_PTR(image_pixels), E_FAIL); - - IDirect3DVolume8 *mip_level_0 = NULL; - bool using_temp_buffer = false; - BYTE *pixels = image_pixels; - - nassertr(IS_VALID_PTR(_d3d_volume_texture), E_FAIL); - hr = _d3d_volume_texture->GetVolumeLevel(0, &mip_level_0); - - if (FAILED(hr)) { - dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << tex->get_name() - << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr); - return E_FAIL; - } - - D3DBOX source_size; - source_size.Left = source_size.Top = source_size.Front = 0; - source_size.Right = orig_width; - source_size.Bottom = orig_height; - source_size.Back = orig_depth; - - UINT source_row_byte_length = orig_width * num_color_channels; - UINT source_page_byte_length = orig_height * source_row_byte_length; - - DWORD level_0_filter, mip_filter_flags; - using_temp_buffer = false; - - // need filtering if size changes, (also if bitdepth reduced (need - // dithering)??) - level_0_filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER; //dithering looks ugly on i810 for 4444 textures - - // D3DXLoadSurfaceFromMemory will load black luminance and we want - // full white, so convert to explicit luminance-alpha format - if (_d3d_format == D3DFMT_A8) { - // alloc buffer for explicit D3DFMT_A8L8 - USHORT *temp_buffer = new USHORT[orig_width * orig_height * orig_depth]; - if (!IS_VALID_PTR(temp_buffer)) { - dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n"; - goto exit_FillDDSurf; - } - using_temp_buffer = true; - - USHORT *out_pixels = temp_buffer; - BYTE *source_pixels = pixels + component_width - 1; - for (UINT z = 0; z < orig_depth; z++) { - for (UINT y = 0; y < orig_height; y++) { - for (UINT x = 0; - x < orig_width; - x++, source_pixels += component_width, out_pixels++) { - // add full white, which is our interpretation of alpha-only - // (similar to default adding full opaque alpha 0xFF to - // RGB-only textures) - *out_pixels = ((*source_pixels) << 8 ) | 0xFF; - } - } - } - - source_format = D3DFMT_A8L8; - source_row_byte_length = orig_width * sizeof(USHORT); - source_page_byte_length = orig_height * source_row_byte_length; - pixels = (BYTE*)temp_buffer; - - } else if (component_width != 1) { - // Convert from 16-bit per channel (or larger) format down to - // 8-bit per channel. This throws away precision in the - // original image, but dx8 doesn't support high-precision images - // anyway. - - int num_components = tex->get_num_components(); - int num_pixels = orig_width * orig_height * orig_depth * num_components; - BYTE *temp_buffer = new BYTE[num_pixels]; - if (!IS_VALID_PTR(temp_buffer)) { - dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n"; - goto exit_FillDDSurf; - } - using_temp_buffer = true; - - BYTE *source_pixels = pixels + component_width - 1; - for (int i = 0; i < num_pixels; i++) { - temp_buffer[i] = *source_pixels; - source_pixels += component_width; - } - pixels = (BYTE*)temp_buffer; - } - - - // filtering may be done here if texture if targetsize != origsize -#ifdef DO_PSTATS - GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_page_byte_length * orig_depth); -#endif - hr = D3DXLoadVolumeFromMemory - (mip_level_0, (PALETTEENTRY*)NULL, (D3DBOX*)NULL, (LPCVOID)pixels, - source_format, source_row_byte_length, source_page_byte_length, - (PALETTEENTRY*)NULL, - &source_size, level_0_filter, (D3DCOLOR)0x0); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << tex->get_name() - << ", D3DXLoadVolumeFromMem failed" << D3DERRORSTRING(hr); - goto exit_FillDDSurf; - } - - if (_has_mipmaps) { - if (!dx_use_triangle_mipgen_filter) { - mip_filter_flags = D3DX_FILTER_BOX; - } else { - mip_filter_flags = D3DX_FILTER_TRIANGLE; - } - - // mip_filter_flags| = D3DX_FILTER_DITHER; - - hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0, - mip_filter_flags); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << tex->get_name() - << ", D3DXFilterTex failed" << D3DERRORSTRING(hr); - goto exit_FillDDSurf; - } - } - - exit_FillDDSurf: - if (using_temp_buffer) { - SAFE_DELETE_ARRAY(pixels); - } - RELEASE(mip_level_0, dxgsg8, "FillDDSurf MipLev0 texture ptr", RELEASE_ONCE); - return hr; -} - - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::down_to_power_2 -// Access: Private, Static -// Description: Returns the largest power of 2 less than or equal -// to value. -//////////////////////////////////////////////////////////////////// -int DXTextureContext8:: -down_to_power_2(int value) { - int x = 1; - while ((x << 1) <= value) { - x = (x << 1); - } - return x; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXTextureContext8::get_bits_per_pixel -// Access: Private -// Description: Maps from the Texture's Format symbols to bpp. -// Returns # of alpha bits. Note: Texture's format -// indicates REQUESTED final format, not the stored -// format, which is indicated by pixelbuffer type -//////////////////////////////////////////////////////////////////// -unsigned int DXTextureContext8:: -get_bits_per_pixel(Texture::Format format, int *alphbits) { - *alphbits = 0; // assume no alpha bits - switch(format) { - case Texture::F_alpha: - *alphbits = 8; - case Texture::F_color_index: - case Texture::F_red: - case Texture::F_green: - case Texture::F_blue: - case Texture::F_rgb332: - return 8; - case Texture::F_luminance_alphamask: - *alphbits = 1; - return 16; - case Texture::F_luminance_alpha: - *alphbits = 8; - return 16; - case Texture::F_luminance: - return 8; - case Texture::F_rgba4: - *alphbits = 4; - return 16; - case Texture::F_rgba5: - *alphbits = 1; - return 16; - case Texture::F_depth_stencil: - return 32; - case Texture::F_rgb5: - return 16; - case Texture::F_rgb8: - case Texture::F_rgb: - return 24; - case Texture::F_rgba8: - case Texture::F_rgba: - *alphbits = 8; - return 32; - case Texture::F_rgbm: - *alphbits = 1; - return 32; - case Texture::F_rgb12: - return 36; - case Texture::F_rgba12: - *alphbits = 12; - return 48; - } - return 8; -} diff --git a/panda/src/dxgsg8/dxTextureContext8.h b/panda/src/dxgsg8/dxTextureContext8.h deleted file mode 100644 index 5fc06f8d0a..0000000000 --- a/panda/src/dxgsg8/dxTextureContext8.h +++ /dev/null @@ -1,89 +0,0 @@ -// Filename: dxTextureContext8.h -// Created by: drose (07Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef DXTEXTURECONTEXT8_H -#define DXTEXTURECONTEXT8_H - -#include "dxgsg8base.h" -#include "texture.h" -#include "textureContext.h" - -//////////////////////////////////////////////////////////////////// -// Class : DXTextureContext8 -// Description : -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXTextureContext8 : public TextureContext { -public: - DXTextureContext8(PreparedGraphicsObjects *pgo, Texture *tex, int view); - virtual ~DXTextureContext8(); - - virtual void evict_lru(); - - bool create_texture(DXScreenData &scrn); - bool create_simple_texture(DXScreenData &scrn); - void delete_texture(); - bool extract_texture_data(); - - INLINE bool has_mipmaps() const; - INLINE IDirect3DBaseTexture8 *get_d3d_texture() const; - INLINE IDirect3DTexture8 *get_d3d_2d_texture() const; - INLINE IDirect3DVolumeTexture8 *get_d3d_volume_texture() const; - INLINE IDirect3DCubeTexture8 *get_d3d_cube_texture() const; - - static HRESULT d3d_surface_to_texture(RECT &source_rect, - IDirect3DSurface8 *d3d_surface, - bool inverted, Texture *result, - int view, int z); - -private: - HRESULT fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_format); - HRESULT fill_d3d_texture_pixels(); - HRESULT fill_d3d_texture_pixels(DXScreenData &scrn); - HRESULT fill_d3d_volume_texture_pixels(DXScreenData &scrn); - static int down_to_power_2(int value); - unsigned int get_bits_per_pixel(Texture::Format format, int *alphbits); - -private: - D3DFORMAT _d3d_format; // the 'D3DFORMAT' the Panda TextureBuffer fmt corresponds to - IDirect3DBaseTexture8 *_d3d_texture; - IDirect3DTexture8 *_d3d_2d_texture; - IDirect3DVolumeTexture8 *_d3d_volume_texture; - IDirect3DCubeTexture8 *_d3d_cube_texture; - - bool _has_mipmaps; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TextureContext::init_type(); - register_type(_type_handle, "DXTextureContext8", - TextureContext::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; - - friend class wdxGraphicsBuffer8; -}; - -#include "dxTextureContext8.I" - -#endif - diff --git a/panda/src/dxgsg8/dxVertexBufferContext8.I b/panda/src/dxgsg8/dxVertexBufferContext8.I deleted file mode 100644 index 1f0e299222..0000000000 --- a/panda/src/dxgsg8/dxVertexBufferContext8.I +++ /dev/null @@ -1,14 +0,0 @@ -// Filename: dxVertexBufferContext8.I -// Created by: drose (18Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - diff --git a/panda/src/dxgsg8/dxVertexBufferContext8.cxx b/panda/src/dxgsg8/dxVertexBufferContext8.cxx deleted file mode 100644 index dbabf0de46..0000000000 --- a/panda/src/dxgsg8/dxVertexBufferContext8.cxx +++ /dev/null @@ -1,299 +0,0 @@ -// Filename: dxVertexBufferContext8.cxx -// Created by: drose (18Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "dxVertexBufferContext8.h" -#include "geomVertexArrayData.h" -#include "geomVertexArrayFormat.h" -#include "graphicsStateGuardian.h" -#include "pStatTimer.h" -#include "internalName.h" -#include "config_dxgsg8.h" -#include "dxgsg8base.h" - -TypeHandle DXVertexBufferContext8::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: DXVertexBufferContext8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXVertexBufferContext8:: -DXVertexBufferContext8(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) : - VertexBufferContext(pgo, data), - _vbuffer(NULL) -{ - // Now fill in the FVF code. - const GeomVertexArrayFormat *array_format = data->get_array_format(); - - // We have to start with the vertex data, and work up from there in - // order, since that's the way the FVF is defined. - int n = 0; - int num_columns = array_format->get_num_columns(); - - _fvf = 0; - - if (n < num_columns && - array_format->get_column(n)->get_name() == InternalName::get_vertex()) { - ++n; - - int num_blend_values = 0; - - if (n < num_columns && - array_format->get_column(n)->get_name() == InternalName::get_transform_weight()) { - // We have hardware vertex animation. - num_blend_values = array_format->get_column(n)->get_num_values(); - ++n; - } - - if (n < num_columns && - array_format->get_column(n)->get_name() == InternalName::get_transform_index()) { - // Furthermore, it's indexed vertex animation. - _fvf |= D3DFVF_LASTBETA_UBYTE4; - ++num_blend_values; - ++n; - } - - switch (num_blend_values) { - case 0: - _fvf |= D3DFVF_XYZ; - break; - - case 1: - _fvf |= D3DFVF_XYZB1; - break; - - case 2: - _fvf |= D3DFVF_XYZB2; - break; - - case 3: - _fvf |= D3DFVF_XYZB3; - break; - - case 4: - _fvf |= D3DFVF_XYZB4; - break; - - case 5: - _fvf |= D3DFVF_XYZB5; - break; - } - } - - if (n < num_columns && - array_format->get_column(n)->get_name() == InternalName::get_normal()) { - _fvf |= D3DFVF_NORMAL; - ++n; - } - if (n < num_columns && - array_format->get_column(n)->get_name() == InternalName::get_color()) { - _fvf |= D3DFVF_DIFFUSE; - ++n; - } - - // Now look for all of the texcoord names and enable them in the - // same order they appear in the array. - int texcoord_index = 0; - while (n < num_columns && - array_format->get_column(n)->get_contents() == Geom::C_texcoord) { - const GeomVertexColumn *column = array_format->get_column(n); - switch (column->get_num_values()) { - case 1: - _fvf |= D3DFVF_TEXCOORDSIZE1(texcoord_index); - ++n; - break; - case 2: - _fvf |= D3DFVF_TEXCOORDSIZE2(texcoord_index); - ++n; - break; - case 3: - _fvf |= D3DFVF_TEXCOORDSIZE3(texcoord_index); - ++n; - break; - case 4: - _fvf |= D3DFVF_TEXCOORDSIZE4(texcoord_index); - ++n; - break; - } - ++texcoord_index; - } - - switch (texcoord_index) { - case 0: - break; - case 1: - _fvf |= D3DFVF_TEX1; - break; - case 2: - _fvf |= D3DFVF_TEX2; - break; - case 3: - _fvf |= D3DFVF_TEX3; - break; - case 4: - _fvf |= D3DFVF_TEX4; - break; - case 5: - _fvf |= D3DFVF_TEX5; - break; - case 6: - _fvf |= D3DFVF_TEX6; - break; - case 7: - _fvf |= D3DFVF_TEX7; - break; - case 8: - _fvf |= D3DFVF_TEX8; - break; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXVertexBufferContext8::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DXVertexBufferContext8:: -~DXVertexBufferContext8() { - if (_vbuffer != NULL) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "deleting vertex buffer " << _vbuffer << "\n"; - } - - RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE); - _vbuffer = NULL; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXVertexBufferContext8::evict_lru -// Access: Public, Virtual -// Description: 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 DXVertexBufferContext8:: -evict_lru() { - dequeue_lru(); - - if (_vbuffer != NULL) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "deleting vertex buffer " << _vbuffer << "\n"; - } - - RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE); - _vbuffer = NULL; - } - - update_data_size_bytes(0); - mark_unloaded(); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXVertexBufferContext8::create_vbuffer -// Access: Public -// Description: Creates a new vertex buffer (but does not upload data -// to it). -//////////////////////////////////////////////////////////////////// -void DXVertexBufferContext8:: -create_vbuffer(DXScreenData &scrn, - const GeomVertexArrayDataHandle *reader) { - nassertv(reader->get_object() == get_data()); - Thread *current_thread = reader->get_current_thread(); - - if (_vbuffer != NULL) { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "deleting vertex buffer " << _vbuffer << "\n"; - } - - RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE); - _vbuffer = NULL; - } - - PStatTimer timer(GraphicsStateGuardian::_create_vertex_buffer_pcollector, - current_thread); - - HRESULT hr = scrn._d3d_device->CreateVertexBuffer -// (reader->get_data_size_bytes(), D3DUSAGE_WRITEONLY, -// _fvf, D3DPOOL_MANAGED, &_vbuffer); - (reader->get_data_size_bytes(), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, - _fvf, D3DPOOL_DEFAULT, &_vbuffer); - if (FAILED(hr)) { - dxgsg8_cat.warning() - << "CreateVertexBuffer failed" << D3DERRORSTRING(hr); - _vbuffer = NULL; - } else { - if (dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() - << "created vertex buffer " << _vbuffer << ": " - << reader->get_num_rows() << " vertices " - << *reader->get_array_format() << "\n"; - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: DXVertexBufferContext8::upload_data -// Access: Public -// Description: Copies the latest data from the client store to -// DirectX. -//////////////////////////////////////////////////////////////////// -bool DXVertexBufferContext8:: -upload_data(const GeomVertexArrayDataHandle *reader, bool force) { - nassertr(reader->get_object() == get_data(), false); - nassertr(_vbuffer != NULL, false); - Thread *current_thread = reader->get_current_thread(); - - const unsigned char *data_pointer = reader->get_read_pointer(force); - if (data_pointer == NULL) { - return false; - } - int data_size = reader->get_data_size_bytes(); - - if (dxgsg8_cat.is_spam()) { - dxgsg8_cat.spam() - << "copying " << data_size - << " bytes into vertex buffer " << _vbuffer << "\n"; - } - - PStatTimer timer(GraphicsStateGuardian::_load_vertex_buffer_pcollector, - current_thread); - - BYTE *local_pointer; -// HRESULT hr = _vbuffer->Lock(0, data_size, &local_pointer, 0); - HRESULT hr = _vbuffer->Lock(0, data_size, &local_pointer, D3DLOCK_DISCARD); - if (FAILED(hr)) { - dxgsg8_cat.error() - << "VertexBuffer::Lock failed" << D3DERRORSTRING(hr); - return false; - } - - GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size); - memcpy(local_pointer, data_pointer, data_size); - - _vbuffer->Unlock(); - return true; -} - diff --git a/panda/src/dxgsg8/dxVertexBufferContext8.h b/panda/src/dxgsg8/dxVertexBufferContext8.h deleted file mode 100644 index 44d85ce73d..0000000000 --- a/panda/src/dxgsg8/dxVertexBufferContext8.h +++ /dev/null @@ -1,63 +0,0 @@ -// Filename: dxVertexBufferContext8.h -// Created by: drose (18Mar05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef DXVERTEXBUFFERCONTEXT8_H -#define DXVERTEXBUFFERCONTEXT8_H - -#include "pandabase.h" -#include "dxgsg8base.h" -#include "vertexBufferContext.h" - -//////////////////////////////////////////////////////////////////// -// Class : DXVertexBufferContext8 -// Description : Caches a GeomVertexArrayData in the DirectX device as -// a vertex buffer. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXVertexBufferContext8 : public VertexBufferContext { -public: - DXVertexBufferContext8(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data); - virtual ~DXVertexBufferContext8(); - - virtual void evict_lru(); - - void create_vbuffer(DXScreenData &scrn, - const GeomVertexArrayDataHandle *reader); - bool upload_data(const GeomVertexArrayDataHandle *reader, bool force); - - IDirect3DVertexBuffer8 *_vbuffer; - int _fvf; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - VertexBufferContext::init_type(); - register_type(_type_handle, "DXVertexBufferContext8", - VertexBufferContext::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 "dxVertexBufferContext8.I" - -#endif - - diff --git a/panda/src/dxgsg8/dxgsg8base.h b/panda/src/dxgsg8/dxgsg8base.h deleted file mode 100644 index 49650f89eb..0000000000 --- a/panda/src/dxgsg8/dxgsg8base.h +++ /dev/null @@ -1,208 +0,0 @@ -// Filename: dxgsg8base.h -// Created by: georges (07Oct01) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef DXGSG8BASE_H -#define DXGSG8BASE_H - -#include "pandabase.h" -#include "graphicsWindow.h" -#include "pmap.h" - -#define WIN32_LEAN_AND_MEAN // get rid of mfc win32 hdr stuff -#ifndef STRICT -// enable strict type checking in windows.h, see msdn -#define STRICT -#endif - -#define DIRECT3D_VERSION 0x0800 -#include -#include -#include -#include -#include -#undef WIN32_LEAN_AND_MEAN - -#ifndef D3DERRORSTRING -#ifdef NDEBUG -#define D3DERRORSTRING(HRESULT) " at (" << __FILE__ << ":" << __LINE__ << "), hr=" << DXGetErrorString8(HRESULT) << endl // leave out descriptions to shrink release build -#else -#define D3DERRORSTRING(HRESULT) " at (" << __FILE__ << ":" << __LINE__ << "), hr=" << DXGetErrorString8(HRESULT) << ": " << DXGetErrorDescription8(HRESULT) << endl -#endif -#endif - -// imperfect method to ID NVid? could also scan desc str, but that isnt fullproof either -#define IS_NVIDIA(DDDEVICEID) ((DDDEVICEID.VendorId==0x10DE) || (DDDEVICEID.VendorId==0x12D2)) -#define IS_ATI(DDDEVICEID) (DDDEVICEID.VendorId==0x1002) -#define IS_MATROX(DDDEVICEID) (DDDEVICEID.VendorId==0x102B) - -#define D3D_MAXTEXTURESTAGES 8 - -typedef enum {VertexShader,PixelShader} ShaderType; -typedef DWORD DXShaderHandle; - -#define ISPOW2(X) (((X) & ((X)-1))==0) -#define IS_VALID_PTR(PTR) (!IsBadWritePtr(PTR,sizeof(void*))) - -#define DX_DECLARE_CLEAN(type, var) \ - type var; \ - ZeroMemory(&var, sizeof(type)); \ - var.dwSize = sizeof(type); - -#define SAFE_DELSHADER(TYPE,HANDLE,PDEVICE) \ - if((HANDLE!=NULL)&&IS_VALID_PTR(PDEVICE)) { PDEVICE->Delete##TYPE##Shader(HANDLE); HANDLE=NULL; } - -#define SAFE_DELETE(p) { if(p) { assert(IS_VALID_PTR(p)); delete (p); (p)=NULL; } } -#define SAFE_DELETE_ARRAY(p) { if(p) { assert(IS_VALID_PTR(p)); delete [] (p); (p)=NULL; } } - -// for stuff outside a panda class -#define SAFE_RELEASE(p) { if(p) { assert(IS_VALID_PTR(p)); (p)->Release(); (p)=NULL; } } -#define SAFE_FREELIB(hDLL) { if(hDLL!=NULL) { FreeLibrary(hDLL);hDLL = NULL; } } - -// this is bDoDownToZero argument to RELEASE() -#define RELEASE_DOWN_TO_ZERO true -#define RELEASE_ONCE false - - -// uncomment to add refcnt debug output -#define DEBUG_RELEASES - -#ifdef DEBUG_RELEASES -#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) { \ - ULONG refcnt; \ - if(IS_VALID_PTR(OBJECT)) { \ - refcnt = (OBJECT)->Release(); \ - MODULE##_cat.debug() << DBGSTR << " released, refcnt = " << refcnt << " at " << __FILE__ << ":" << __LINE__ << endl; \ - if((bDoDownToZero) && (refcnt>0)) { \ - MODULE##_cat.warning() << DBGSTR << " released but still has a non-zero refcnt(" << refcnt << "), multi-releasing it down to zero!\n"; \ - do { \ - refcnt = (OBJECT)->Release(); \ - } while(refcnt>0); \ - } \ - (OBJECT) = NULL; \ - } else { \ - MODULE##_cat.debug() << DBGSTR << " not released, ptr == NULL" << endl; \ - }} - -#define PRINT_REFCNT(MODULE,p) { ULONG refcnt; (p)->AddRef(); refcnt=(p)->Release(); \ - MODULE##_cat.debug() << #p << " has refcnt = " << refcnt << " at " << __FILE__ << ":" << __LINE__ << endl; } - -#else -#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) { \ - ULONG refcnt; \ - if(IS_VALID_PTR(OBJECT)) { \ - refcnt=(OBJECT)->Release(); \ - if((bDoDownToZero) && (refcnt>0)) { \ - MODULE##_cat.warning() << DBGSTR << " released but still has a non-zero refcnt(" << refcnt << "), multi-releasing it down to zero!\n"; \ - do { \ - refcnt = (OBJECT)->Release(); \ - } while(refcnt>0); \ - } \ - (OBJECT) = NULL; \ - }} - -#define PRINT_REFCNT(MODULE,p) -#endif - -#ifdef DO_PSTATS -#define DO_PSTATS_STUFF(XX) XX; -#else -#define DO_PSTATS_STUFF(XX) -#endif - -#define PANDA_MAXNUMVERTS 0xFFFF // Note Device may support more than this if it supports D3DFMT_INDEX32 indexbufs. - -#define FLG(NN) (1< g_D3DFORMATmap; -extern void Init_D3DFORMAT_map(); -extern const char *D3DFormatStr(D3DFORMAT fmt); - -#endif - diff --git a/panda/src/dxgsg8/p3dxgsg8_composite1.cxx b/panda/src/dxgsg8/p3dxgsg8_composite1.cxx deleted file mode 100644 index 8e3cc0e6f9..0000000000 --- a/panda/src/dxgsg8/p3dxgsg8_composite1.cxx +++ /dev/null @@ -1,10 +0,0 @@ -#include "dxgsg8base.h" -#include "config_dxgsg8.cxx" -#include "dxTextureContext8.cxx" -#include "dxVertexBufferContext8.cxx" -#include "dxIndexBufferContext8.cxx" -#include "dxGeomMunger8.cxx" -#include "wdxGraphicsPipe8.cxx" -#include "wdxGraphicsWindow8.cxx" -#include "wdxGraphicsBuffer8.cxx" -#include "dxGraphicsDevice8.cxx" diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.I b/panda/src/dxgsg8/wdxGraphicsBuffer8.I deleted file mode 100644 index a2a4185d0c..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsBuffer8.I +++ /dev/null @@ -1,27 +0,0 @@ -// Filename: wdxGraphicsBuffer8.I -// Created by: zhao (29Sep12) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::get_supports_render_texture -// Access: Published, Virtual -// Description: Returns true if this particular GraphicsOutput can -// render directly into a texture, or false if it must -// always copy-to-texture at the end of each frame to -// achieve this effect. -//////////////////////////////////////////////////////////////////// -INLINE bool wdxGraphicsBuffer8:: -get_supports_render_texture() const { - // DX8 buffers can always bind-to-texture. - return true; -} diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx b/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx deleted file mode 100644 index 9b0c28b7b1..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx +++ /dev/null @@ -1,575 +0,0 @@ -// Filename: wdxGraphicsBuffer8.cxx -// Created by: drose (08Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "wdxGraphicsPipe8.h" -#include "wdxGraphicsBuffer8.h" -#include "pStatTimer.h" - - -// ISSUES: - // render to texure format - // can be specified via the DXGraphicsStateGuardian8 member - // _render_to_texture_d3d_format default = D3DFMT_X8R8G8B8 - - // should check texture creation with CheckDepthStencilMatch - // support copy from texture to ram? - // check D3DCAPS2_DYNAMICTEXTURES - -#define FL << "\n" << __FILE__ << " " << __LINE__ << "\n" - -TypeHandle wdxGraphicsBuffer8::_type_handle; - - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -wdxGraphicsBuffer8:: -wdxGraphicsBuffer8(GraphicsEngine *engine, GraphicsPipe *pipe, - const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsStateGuardian *gsg, - GraphicsOutput *host): - GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) -{ - // initialize all class members - _cube_map_index = -1; - _saved_color_buffer = NULL; - _saved_depth_buffer = NULL; - _color_backing_store = NULL; - _depth_backing_store = NULL; - - // is this correct ??? - // Since the pbuffer never gets flipped, we get screenshots from the - // same buffer we draw into. - _screenshot_buffer_type = _draw_buffer_type; - - _this = 0; - - if (_gsg) { - // save to GSG list to handle device lost issues - DXGraphicsStateGuardian8 *dxgsg; - - dxgsg = DCAST (DXGraphicsStateGuardian8, _gsg); - _this = new (wdxGraphicsBuffer8 *); - *_this = this; - dxgsg -> _graphics_buffer_list.push_back(_this); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -wdxGraphicsBuffer8:: -~wdxGraphicsBuffer8() { - this -> close_buffer ( ); - - if (_gsg) { - // remove from GSG list - DXGraphicsStateGuardian8 *dxgsg; - - dxgsg = DCAST (DXGraphicsStateGuardian8, _gsg); - if (_this) { - dxgsg -> _graphics_buffer_list.remove(_this); - } - _this = 0; - _gsg.clear(); - _gsg = 0; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::begin_frame -// Access: Public, Virtual -// Description: This function will be called within the draw thread -// before beginning rendering for a given frame. It -// should do whatever setup is required, and return true -// if the frame should be rendered, or false if it -// should be skipped. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsBuffer8:: -begin_frame(FrameMode mode, Thread *current_thread) { - - begin_frame_spam(mode); - if (_gsg == (GraphicsStateGuardian *)NULL) { - return false; - } - if (_dxgsg -> _d3d_device == 0) { - return false; - } - - if (mode == FM_render) { - if (!save_bitplanes()) { - return false; - } - if (!rebuild_bitplanes()) { - restore_bitplanes(); - return false; - } - clear_cube_map_selection(); - } - - _gsg->set_current_properties(&get_fb_properties()); - return _gsg->begin_frame(current_thread); -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::end_frame -// Access: Public, Virtual -// Description: This function will be called within the draw thread -// after rendering is completed for a given frame. It -// should do whatever finalization is required. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsBuffer8:: -end_frame(FrameMode mode, Thread *current_thread) { - - end_frame_spam(mode); - nassertv(_gsg != (GraphicsStateGuardian *)NULL); - - if (mode == FM_render) { - copy_to_textures(); - } - - _gsg->end_frame(current_thread); - - if (mode == FM_render) { - trigger_flip(); - clear_cube_map_selection(); - restore_bitplanes(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::save_bitplanes -// Access: Public -// Description: After rendering, d3d_device will need to be restored -// to its initial state. This function saves the state. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsBuffer8:: -save_bitplanes() { - HRESULT hr; - - hr = _dxgsg -> _d3d_device -> GetRenderTarget (&_saved_color_buffer); - if (!SUCCEEDED (hr)) { - dxgsg8_cat.error ( ) << "GetRenderTarget " << D3DERRORSTRING(hr) FL; - return false; - } - hr = _dxgsg -> _d3d_device -> GetDepthStencilSurface (&_saved_depth_buffer); - if (!SUCCEEDED (hr)) { - dxgsg8_cat.error ( ) << "GetDepthStencilSurface " << D3DERRORSTRING(hr) FL; - return false; - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::restore_bitplanes -// Access: Public -// Description: After rendering, d3d_device will need to be restored -// to its initial state. This function restores the state. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsBuffer8:: -restore_bitplanes() { - DXGraphicsStateGuardian8 *dxgsg; - DCAST_INTO_V(dxgsg, _gsg); - - HRESULT hr; - - hr = dxgsg -> _d3d_device -> - SetRenderTarget (_saved_color_buffer, _saved_depth_buffer); - - if (!SUCCEEDED (hr)) { - dxgsg8_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL; - } - - _saved_color_buffer->Release(); - _saved_depth_buffer->Release(); - _saved_color_buffer = NULL; - _saved_depth_buffer = NULL; -} - - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::rebuild_bitplanes -// Access: Public -// Description: If necessary, reallocates (or allocates) the -// bitplanes for the buffer. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsBuffer8:: -rebuild_bitplanes() { - - HRESULT hr; - Texture *color_tex = 0; - Texture *depth_tex = 0; - DXTextureContext8 *color_ctx = 0; - DXTextureContext8 *depth_ctx = 0; - IDirect3DTexture8 *color_d3d_tex = 0; - IDirect3DTexture8 *depth_d3d_tex = 0; - IDirect3DCubeTexture8 *color_cube = 0; - IDirect3DCubeTexture8 *depth_cube = 0; - IDirect3DSurface8 *color_surf = 0; - IDirect3DSurface8 *depth_surf = 0; - - // Decide how big the bitplanes should be. - - if ((_host != 0)&&(_creation_flags & GraphicsPipe::BF_size_track_host)) { - if (_host->get_size() != _size) { - set_size_and_recalc(_host->get_x_size(), - _host->get_y_size()); - } - } - int bitplane_x = get_x_size(); - int bitplane_y = get_y_size(); - if (Texture::get_textures_power_2() != ATS_none) { - bitplane_x = Texture::up_to_power_2(bitplane_x); - bitplane_y = Texture::up_to_power_2(bitplane_y); - } - - // Find the color and depth textures. Either may be present, - // or neither. - // - // NOTE: Currently, depth-stencil textures are not implemented, - // but since it's coming soon, we're structuring for it. - - int color_tex_index = -1; - int depth_tex_index = -1; - for (int i=0; iget_format() != Texture::F_depth_stencil)&& - (get_texture(i)->get_format() != Texture::F_depth_component)&& - (color_tex_index < 0)) { - color_tex_index = i; - } - } - } - - - if (color_tex_index < 0) { - // Maintain the backing color surface. - if ((_color_backing_store)&& - ((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) { - _color_backing_store->Release(); - _color_backing_store = NULL; - } - if (!_color_backing_store) { - hr = _dxgsg -> _d3d_device -> - CreateImageSurface(bitplane_x, bitplane_y, _saved_color_desc.Format, &_color_backing_store); - if (!SUCCEEDED(hr)) { - dxgsg8_cat.error ( ) << "CreateImageSurface " << D3DERRORSTRING(hr) FL; - } - } - color_surf = _color_backing_store; - } else { - // Maintain the color texture. - if (_color_backing_store) { - _color_backing_store->Release(); - _color_backing_store = NULL; - } - color_tex = get_texture(color_tex_index); - color_tex->set_x_size(bitplane_x); - color_tex->set_y_size(bitplane_y); - color_tex->set_format(Texture::F_rgba); - color_ctx = - DCAST(DXTextureContext8, - color_tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg)); - if (color_ctx) { - if (!color_ctx->create_texture(*_dxgsg->_screen)) { - dxgsg8_cat.error() - << "Unable to re-create texture " << *color_ctx->get_texture() << endl; - return false; - } - if (color_tex->get_texture_type() == Texture::TT_2d_texture) { - color_d3d_tex = color_ctx->_d3d_2d_texture; - nassertr(color_d3d_tex != 0, false); - hr = color_d3d_tex -> GetSurfaceLevel(0, &color_surf); - if (!SUCCEEDED(hr)) { - dxgsg8_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL; - } - } else { - color_cube = color_ctx->_d3d_cube_texture; - nassertr(color_cube != 0, false); - if (_cube_map_index >= 0 && _cube_map_index < 6) { - hr = color_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &color_surf); - if (!SUCCEEDED(hr)) { - dxgsg8_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL; - } - } - } - } - } - - if (depth_tex_index < 0) { - // Maintain the backing depth surface. - if ((_depth_backing_store)&& - ((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) { - _depth_backing_store->Release(); - _depth_backing_store = NULL; - } - if (!_depth_backing_store) { - hr = _dxgsg -> _d3d_device -> - CreateDepthStencilSurface (bitplane_x, bitplane_y, _saved_depth_desc.Format, - _saved_depth_desc.MultiSampleType, &_depth_backing_store); - if (!SUCCEEDED(hr)) { - dxgsg8_cat.error ( ) << "CreateDepthStencilSurface " << D3DERRORSTRING(hr) FL; - } - } - depth_surf = _depth_backing_store; - } else { - // Maintain the depth texture. - if (_depth_backing_store) { - _depth_backing_store->Release(); - _depth_backing_store = NULL; - } - depth_tex = get_texture(depth_tex_index); - depth_tex->set_x_size(bitplane_x); - depth_tex->set_y_size(bitplane_y); - depth_tex->set_format(Texture::F_depth_stencil); - depth_ctx = - DCAST(DXTextureContext8, - depth_tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg)); - if (depth_ctx) { - if (!depth_ctx->create_texture(*_dxgsg->_screen)) { - dxgsg8_cat.error() - << "Unable to re-create texture " << *depth_ctx->get_texture() << endl; - return false; - } - - if (depth_tex->get_texture_type() == Texture::TT_2d_texture) { - depth_d3d_tex = depth_ctx->_d3d_2d_texture; - nassertr(depth_d3d_tex != 0, false); - hr = depth_d3d_tex -> GetSurfaceLevel(0, &depth_surf); - if (!SUCCEEDED(hr)) { - dxgsg8_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL; - } - } else { - depth_cube = depth_ctx->_d3d_cube_texture; - nassertr(depth_cube != 0, false); - hr = depth_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &depth_surf); - if (!SUCCEEDED(hr)) { - dxgsg8_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL; - } - } - } - } - - _backing_sizex = bitplane_x; - _backing_sizey = bitplane_y; - - // Load up the bitplanes. - - if (color_surf && depth_surf) { - hr = _dxgsg -> _d3d_device -> SetRenderTarget (color_surf, depth_surf); - if (!SUCCEEDED (hr)) { - dxgsg8_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL; - } - } - - // Decrement the reference counts on these surfaces. The refcounts - // were incremented earlier when we called GetSurfaceLevel. - - if ((color_surf != 0)&&(color_surf != _color_backing_store)) { - color_surf->Release(); - } - if ((depth_surf != 0)&&(depth_surf != _depth_backing_store)) { - depth_surf->Release(); - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::select_target_tex_page -// Access: Public, Virtual -// Description: Called internally when the window is in -// render-to-a-texture mode and we are in the process of -// rendering the six faces of a cube map. This should -// do whatever needs to be done to switch the buffer to -// the indicated face. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsBuffer8:: -select_target_tex_page(int page) { - _cube_map_index = page; - - HRESULT hr; - Texture *color_tex = 0; - DXTextureContext8 *color_ctx = 0; - IDirect3DCubeTexture8 *color_cube = 0; - IDirect3DSurface8 *color_surf = 0; - int color_tex_index = -1; - - for (int i=0; iget_format() != Texture::F_depth_stencil)&& - (get_texture(i)->get_format() != Texture::F_depth_component)&& - (color_tex_index < 0)) { - color_tex_index = i; - } - } - } - - color_tex = get_texture(color_tex_index); - if (color_tex) { - color_ctx = - DCAST(DXTextureContext8, - color_tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg)); - if (!color_ctx->create_texture(*_dxgsg->_screen)) { - dxgsg8_cat.error() - << "Unable to re-create texture " << *color_ctx->get_texture() << endl; - return; - } - - color_cube = color_ctx->_d3d_cube_texture; - - if (color_cube && _cube_map_index >= 0 && _cube_map_index < 6) { - hr = color_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &color_surf); - if (!SUCCEEDED(hr)) { - dxgsg8_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL; - } - - hr = _dxgsg -> _d3d_device -> SetRenderTarget (color_surf, 0); - if (!SUCCEEDED (hr)) { - dxgsg8_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL; - } - else { - color_surf->Release(); - } - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::process_events -// Access: Public, Virtual -// Description: Do whatever processing is necessary to ensure that -// the window responds to user events. Also, honor any -// requests recently made via request_properties() -// -// This function is called only within the window -// thread. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsBuffer8:: -process_events() { - GraphicsBuffer::process_events(); - - MSG msg; - - // Handle all the messages on the queue in a row. Some of these - // might be for another window, but they will get dispatched - // appropriately. - while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { - process_1_event(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::close_buffer -// Access: Protected, Virtual -// Description: Closes the buffer right now. Called from the window -// thread. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsBuffer8:: -close_buffer() { - - if (_gsg != (GraphicsStateGuardian *)NULL) { - _gsg.clear(); - } - - if (_color_backing_store) { - _color_backing_store->Release(); - _color_backing_store = NULL; - } - if (_depth_backing_store) { - _depth_backing_store->Release(); - _depth_backing_store = NULL; - } - - _cube_map_index = -1; - _is_valid = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::open_buffer -// Access: Protected, Virtual -// Description: Opens the window right now. Called from the window -// thread. Returns true if the window is successfully -// opened, or false if there was a problem. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsBuffer8:: -open_buffer() { - - // GSG creation/initialization. - if (_gsg == 0) { - // The code below doesn't support creating a GSG on the fly. - // Just error out for now. - //_dxgsg = new DXGraphicsStateGuardian8(_engine, _pipe); - //_gsg = _dxgsg; - return false; - } - - DCAST_INTO_R(_dxgsg, _gsg, false); - - if (!save_bitplanes()) { - return false; - } - - HRESULT hr; - hr = _saved_color_buffer -> GetDesc (&_saved_color_desc); - if (!SUCCEEDED (hr)) { - dxgsg8_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL; - return false; - } - hr = _saved_depth_buffer -> GetDesc (&_saved_depth_desc); - if (!SUCCEEDED (hr)) { - dxgsg8_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL; - return false; - } - _fb_properties = _dxgsg-> - calc_fb_properties(_saved_color_desc.Format, - _saved_depth_desc.Format, - _saved_depth_desc.MultiSampleType); - _fb_properties.set_force_hardware(1); // Wild guess. - - if (!rebuild_bitplanes()) { - restore_bitplanes(); - return false; - } - - restore_bitplanes(); - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::process_1_event -// Access: Private, Static -// Description: Handles one event from the message queue. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsBuffer8:: -process_1_event() { - MSG msg; - - if (!GetMessage(&msg, NULL, 0, 0)) { - // WM_QUIT received. We need a cleaner way to deal with this. - // DestroyAllWindows(false); - exit(msg.wParam); // this will invoke AtExitFn - } - - // Translate virtual key messages - TranslateMessage(&msg); - // Call window_proc - DispatchMessage(&msg); -} diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.h b/panda/src/dxgsg8/wdxGraphicsBuffer8.h deleted file mode 100644 index fe3c5a95de..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsBuffer8.h +++ /dev/null @@ -1,99 +0,0 @@ -// Filename: wdxGraphicsBuffer8.h -// Created by: drose (08Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef wdxGraphicsBuffer8_H -#define wdxGraphicsBuffer8_H - -#include "pandabase.h" -#include "graphicsBuffer.h" -#include "dxgsg8base.h" - - -//////////////////////////////////////////////////////////////////// -// Class : wdxGraphicsBuffer8 -// Description : An offscreen render buffer. In OpenGL under Windows, -// this simply renders into a window that is never made -// visible. There's a Windows interface for rendering -// into a DIB, but this puts restrictions on the kind of -// pixelformat we can use, and thus makes it difficult -// to support one GSG rendering into an offscreen buffer -// and also into a window. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX wdxGraphicsBuffer8 : public GraphicsBuffer { -public: - wdxGraphicsBuffer8(GraphicsEngine *engine, GraphicsPipe *pipe, - const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsStateGuardian *gsg, - GraphicsOutput *host); - virtual ~wdxGraphicsBuffer8(); - - virtual INLINE bool get_supports_render_texture() const; - - virtual bool begin_frame(FrameMode mode, Thread *current_thread); - virtual void end_frame(FrameMode mode, Thread *current_thread); - - virtual void select_target_tex_page(int page); - - virtual void process_events(); - -protected: - virtual void close_buffer(); - virtual bool open_buffer(); - -private: - bool save_bitplanes(); - bool rebuild_bitplanes(); - void restore_bitplanes(); - static void process_1_event(); - - int _cube_map_index; - DXGraphicsStateGuardian8 *_dxgsg; - IDirect3DSurface8 *_saved_color_buffer; - IDirect3DSurface8 *_saved_depth_buffer; - D3DSURFACE_DESC _saved_color_desc; - D3DSURFACE_DESC _saved_depth_desc; - IDirect3DSurface8 *_color_backing_store; - IDirect3DSurface8 *_depth_backing_store; - int _backing_sizex; - int _backing_sizey; - - wdxGraphicsBuffer8 **_this; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - GraphicsBuffer::init_type(); - register_type(_type_handle, "wdxGraphicsBuffer8", - GraphicsBuffer::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; - - friend class DXGraphicsStateGuardian8; - friend class DXTextureContext8; -}; - -#include "wdxGraphicsBuffer8.I" - -#endif diff --git a/panda/src/dxgsg8/wdxGraphicsPipe8.I b/panda/src/dxgsg8/wdxGraphicsPipe8.I deleted file mode 100644 index f9c26197b8..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsPipe8.I +++ /dev/null @@ -1,13 +0,0 @@ -// Filename: wdxGraphicsPipe8.I -// Created by: drose (20Dec02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg8/wdxGraphicsPipe8.cxx b/panda/src/dxgsg8/wdxGraphicsPipe8.cxx deleted file mode 100644 index 6412bf1572..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsPipe8.cxx +++ /dev/null @@ -1,931 +0,0 @@ -// Filename: wdxGraphicsPipe8.cxx -// Created by: drose (20Dec02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "wdxGraphicsPipe8.h" -#include "dxGraphicsDevice8.h" -#include "wdxGraphicsWindow8.h" -#include "wdxGraphicsBuffer8.h" -#include "config_dxgsg8.h" - -TypeHandle wdxGraphicsPipe8::_type_handle; - -#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 - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsPipe8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -wdxGraphicsPipe8:: -wdxGraphicsPipe8() { - _hDDrawDLL = NULL; - _hD3D8_DLL = NULL; - __d3d8 = NULL; - _is_valid = init(); -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsPipe8::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -wdxGraphicsPipe8:: -~wdxGraphicsPipe8() { - RELEASE(__d3d8, wdxdisplay8, "ID3D8", RELEASE_DOWN_TO_ZERO); - SAFE_FREELIB(_hD3D8_DLL); - SAFE_FREELIB(_hDDrawDLL); -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsPipe8::get_interface_name -// Access: Published, Virtual -// Description: Returns the name of the rendering interface -// associated with this GraphicsPipe. This is used to -// present to the user to allow him/her to choose -// between several possible GraphicsPipes available on a -// particular platform, so the name should be meaningful -// and unique for a given platform. -//////////////////////////////////////////////////////////////////// -string wdxGraphicsPipe8:: -get_interface_name() const { - return "DirectX8"; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsPipe8::pipe_constructor -// Access: Public, Static -// Description: This function is passed to the GraphicsPipeSelection -// object to allow the user to make a default -// wdxGraphicsPipe8. -//////////////////////////////////////////////////////////////////// -PT(GraphicsPipe) wdxGraphicsPipe8:: -pipe_constructor() { - return new wdxGraphicsPipe8; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsPipe8::make_output -// Access: Protected, Virtual -// Description: Creates a new window on the pipe, if possible. -//////////////////////////////////////////////////////////////////// -PT(GraphicsOutput) wdxGraphicsPipe8:: -make_output(const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsEngine *engine, - GraphicsStateGuardian *gsg, - GraphicsOutput *host, - int retry, - bool &precertify) { - - if (!_is_valid) { - return NULL; - } - - DXGraphicsStateGuardian8 *wdxgsg = 0; - if (gsg != 0) { - DCAST_INTO_R(wdxgsg, gsg, NULL); - } - - // First thing to try: a visible window. - - if (retry == 0) { - if (((flags&BF_require_parasite)!=0)|| - ((flags&BF_refuse_window)!=0)|| - ((flags&BF_resizeable)!=0)|| - ((flags&BF_size_track_host)!=0)|| - ((flags&BF_rtt_cumulative)!=0)|| - ((flags&BF_can_bind_color)!=0)|| - ((flags&BF_can_bind_every)!=0)) { - return NULL; - } - // Early failure - if we are sure that this buffer WONT - // meet specs, we can bail out early. - if ((flags & BF_fb_props_optional) == 0) { - if ((fb_prop.get_aux_rgba() > 0)|| - (fb_prop.get_aux_rgba() > 0)|| - (fb_prop.get_aux_float() > 0)) { - return NULL; - } - } - return new wdxGraphicsWindow8(engine, this, name, fb_prop, win_prop, - flags, gsg, host); - } - - // Second thing to try: a wdxGraphicsBuffer8 - - if (retry == 1) { - if ((!support_render_texture)|| - ((flags&BF_require_parasite)!=0)|| - ((flags&BF_require_window)!=0)|| - ((flags&BF_resizeable)!=0)|| - ((flags&BF_size_track_host)!=0)|| - ((flags&BF_rtt_cumulative)!=0)|| - ((flags&BF_can_bind_every)!=0)) { - return NULL; - } - // Early failure - if we are sure that this buffer WONT - // meet specs, we can bail out early. - if ((flags & BF_fb_props_optional) == 0) { - if ((fb_prop.get_aux_rgba() > 0)|| - (fb_prop.get_aux_rgba() > 0)|| - (fb_prop.get_aux_float() > 0)|| - (fb_prop.get_indexed_color() > 0)|| - (fb_prop.get_back_buffers() > 0)|| - (fb_prop.get_accum_bits() > 0)|| - (fb_prop.get_multisamples() > 0)) { - return NULL; - } - } - // Early success - if we are sure that this buffer WILL - // meet specs, we can precertify it. - // This looks rather overly optimistic -- ie, buggy. - if ((gsg != 0)&& - (gsg->is_valid())&& - (!gsg->needs_reset())&& - (DCAST(DXGraphicsStateGuardian8, gsg)->get_supports_render_texture())) { - precertify = true; - } - return new wdxGraphicsBuffer8(engine, this, name, fb_prop, win_prop, - flags, gsg, host); - } - - // Nothing else left to try. - return NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsPipe8::init -// Access: Private -// Description: Performs some initialization steps to load up -// function pointers from the relevant DLL's, and -// determine the number and type of available graphics -// adapters, etc. Returns true on success, false on -// failure. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsPipe8:: -init() { - if (!MyLoadLib(_hDDrawDLL, "ddraw.dll")) { - goto error; - } - - if (!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawCreateEx, "DirectDrawCreateEx")) { - goto error; - } - - if (!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawEnumerateExA, "DirectDrawEnumerateExA")) { - goto error; - } - - if (!MyLoadLib(_hD3D8_DLL, "d3d8.dll")) { - goto error; - } - - if (!MyGetProcAddr(_hD3D8_DLL, (FARPROC*)&_Direct3DCreate8, "Direct3DCreate8")) { - goto error; - } - - // Create a Direct3D object. - - // these were taken from the 8.0 and 8.1 d3d8.h SDK headers -#define D3D_SDK_VERSION_8_0 120 -#define D3D_SDK_VERSION_8_1 220 - - // are we using 8.0 or 8.1? - WIN32_FIND_DATA TempFindData; - HANDLE hFind; - char tmppath[_MAX_PATH + 128]; - GetSystemDirectory(tmppath, MAX_PATH); - strcat(tmppath, "\\dpnhpast.dll"); - hFind = FindFirstFile (tmppath, &TempFindData); - if (hFind != INVALID_HANDLE_VALUE) { - FindClose(hFind); - __is_dx8_1 = true; - __d3d8 = (*_Direct3DCreate8)(D3D_SDK_VERSION_8_1); - } else { - __is_dx8_1 = false; - __d3d8 = (*_Direct3DCreate8)(D3D_SDK_VERSION_8_0); - } - - if (__d3d8 == NULL) { - wdxdisplay8_cat.error() << "Direct3DCreate8(8." << (__is_dx8_1 ? "1" : "0") << ") failed!, error = " << GetLastError() << endl; - //release_gsg(); - goto error; - } - - Init_D3DFORMAT_map(); - - return find_all_card_memavails(); - - error: - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsPipe8::find_all_card_memavails -// Access: Private -// Description: Uses DX7 calls to determine how much video memory is -// available for each video adapter in the system. -// Returns true on success, false on failure. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsPipe8:: -find_all_card_memavails() { - HRESULT hr; - - hr = (*_DirectDrawEnumerateExA)(dx7_driver_enum_callback, this, - DDENUM_ATTACHEDSECONDARYDEVICES | DDENUM_NONDISPLAYDEVICES); - if (FAILED(hr)) { - wdxdisplay8_cat.fatal() - << "DirectDrawEnumerateEx failed" << D3DERRORSTRING(hr); - return false; - } - - if (_card_ids.empty()) { - wdxdisplay8_cat.error() - << "DirectDrawEnumerateEx enum'ed no devices!\n"; - return false; - } - - GUID ZeroGUID; - ZeroMemory(&ZeroGUID, sizeof(GUID)); - - if (_card_ids.size() > 1) { - nassertr(IsEqualGUID(ZeroGUID, _card_ids[0].DX7_DeviceGUID), false); - // delete enum of primary display (always the first), since it is - // duplicated by explicit entry - _card_ids.erase(_card_ids.begin()); - } - - for (UINT i = 0; i < _card_ids.size(); i++) { - LPDIRECTDRAW7 pDD; - BYTE ddd_space[sizeof(DDDEVICEIDENTIFIER2)+4]; //bug in DX7 requires 4 extra bytes for GetDeviceID - DDDEVICEIDENTIFIER2 *pDX7DeviceID = (DDDEVICEIDENTIFIER2 *)&ddd_space[0]; - GUID *pGUID = &(_card_ids[i].DX7_DeviceGUID); - - if (IsEqualGUID(*pGUID, ZeroGUID)) { - pGUID = NULL; - } - - // Create the Direct Draw Object - hr = (*_DirectDrawCreateEx)(pGUID, (void **)&pDD, IID_IDirectDraw7, NULL); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "DirectDrawCreateEx failed for device (" << i - << ")" << D3DERRORSTRING(hr); - continue; - } - - ZeroMemory(ddd_space, sizeof(DDDEVICEIDENTIFIER2)); - - hr = pDD->GetDeviceIdentifier(pDX7DeviceID, 0x0); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "GetDeviceID failed for device (" << i << ")" << D3DERRORSTRING(hr); - continue; - } - - _card_ids[i].DeviceID = pDX7DeviceID->dwDeviceId; - _card_ids[i].VendorID = pDX7DeviceID->dwVendorId; - - // Get Current VidMem avail. Note this is only an estimate, when - // we switch to fullscreen mode from desktop, more vidmem will be - // available (typically 1.2 meg). I don't want to switch to - // fullscreen more than once due to the annoying monitor flicker, - // so try to figure out optimal mode using this estimate - DDSCAPS2 ddsGAVMCaps; - DWORD dwVidMemTotal, dwVidMemFree; - dwVidMemTotal = dwVidMemFree = 0; - { - // print out total INCLUDING AGP just for information purposes - // and future use. The real value I'm interested in for - // purposes of measuring possible valid screen sizes shouldnt - // include AGP. - ZeroMemory(&ddsGAVMCaps, sizeof(DDSCAPS2)); - ddsGAVMCaps.dwCaps = DDSCAPS_VIDEOMEMORY; - - hr = pDD->GetAvailableVidMem(&ddsGAVMCaps, &dwVidMemTotal, &dwVidMemFree); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "GetAvailableVidMem failed for device #" << i - << D3DERRORSTRING(hr); - //goto skip_device; - //exit(1); // probably want to exit, since it may be my fault - } - } - - wdxdisplay8_cat.info() - << "GetAvailableVidMem (including AGP) returns Total: " - << dwVidMemTotal <<", Free: " << dwVidMemFree - << " for device #" << i << endl; - - ZeroMemory(&ddsGAVMCaps, sizeof(DDSCAPS2)); - - // just want to measure localvidmem, not AGP texmem - ddsGAVMCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM; - - hr = pDD->GetAvailableVidMem(&ddsGAVMCaps, &dwVidMemTotal, &dwVidMemFree); - if (FAILED(hr)) { - wdxdisplay8_cat.error() << "GetAvailableVidMem failed for device #" << i<< D3DERRORSTRING(hr); - // sometimes GetAvailableVidMem fails with hr = DDERR_NODIRECTDRAWHW for some unknown reason (bad drivers?) - // see bugs: 15327, 18122, others. is it because D3D8 object has already been created? - if (hr == DDERR_NODIRECTDRAWHW) - continue; - exit(1); // probably want to exit, since it may be my fault - } - - wdxdisplay8_cat.info() - << "GetAvailableVidMem (no AGP) returns Total: " << dwVidMemTotal - << ", Free: " << dwVidMemFree << " for device #" << i<< endl; - - pDD->Release(); // release DD obj, since this is all we needed it for - - if (!dx_do_vidmemsize_check) { - // still calling the DD stuff to get deviceID, etc. is this necessary? - _card_ids[i]._max_available_video_memory = UNKNOWN_VIDMEM_SIZE; - _card_ids[i]._is_low_memory_card = false; - continue; - } - - if (dwVidMemTotal == 0) { // unreliable driver - dwVidMemTotal = UNKNOWN_VIDMEM_SIZE; - } else { - if (!ISPOW2(dwVidMemTotal)) { - // assume they wont return a proper max value, so - // round up to next pow of 2 - UINT count = 0; - while ((dwVidMemTotal >> count) != 0x0) { - count++; - } - dwVidMemTotal = (1 << count); - } - } - - // after Set_display_mode, GetAvailVidMem totalmem seems to go down - // by 1.2 meg (contradicting above comment and what I think would - // be correct behavior (shouldnt FS mode release the desktop - // vidmem?), so this is the true value - _card_ids[i]._max_available_video_memory = dwVidMemTotal; - - // I can never get this stuff to work reliably, so I'm just - // rounding up to nearest pow2. Could try to get - // HardwareInformation.Memory_size MB number from registry like - // video control panel, but its not clear how to find the proper - // registry location for a given card - - // assume buggy drivers (this means you, FireGL2) may return zero - // (or small amts) for dwVidMemTotal, so ignore value if its < CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD - bool bLowVidMemFlag = - ((dwVidMemTotal > CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) && - (dwVidMemTotal< LOWVIDMEMTHRESHOLD)); - - _card_ids[i]._is_low_memory_card = bLowVidMemFlag; - wdxdisplay8_cat.info() - << "SetLowVidMem flag to " << bLowVidMemFlag - << " based on adjusted VidMemTotal: " << dwVidMemTotal << endl; - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsPipe8::dx7_driver_enum_callback -// Access: Private, Static -// Description: -//////////////////////////////////////////////////////////////////// -BOOL WINAPI wdxGraphicsPipe8:: -dx7_driver_enum_callback(GUID *pGUID, TCHAR *strDesc, TCHAR *strName, - VOID *argptr, HMONITOR hm) { - wdxGraphicsPipe8 *self = (wdxGraphicsPipe8 *)argptr; - - CardID card_id; - ZeroMemory(&card_id, sizeof(CardID)); - - if (hm == NULL) { - card_id._monitor = MonitorFromWindow(GetDesktopWindow(), - MONITOR_DEFAULTTOPRIMARY); - } else { - card_id._monitor = hm; - } - - if (pGUID != NULL) { - memcpy(&card_id.DX7_DeviceGUID, pGUID, sizeof(GUID)); - } - - card_id._max_available_video_memory = UNKNOWN_VIDMEM_SIZE; - - self->_card_ids.push_back(card_id); - - return DDENUMRET_OK; -} - -////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::find_best_depth_format -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsPipe8:: -find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &Test_display_mode, - D3DFORMAT *pBestFmt, bool bWantStencil, - bool bForce16bpp, bool bVerboseMode) const { - if (dxgsg8_cat.is_debug()) { - bVerboseMode = true; - } - - // list formats to try in order of preference. - -#define NUM_TEST_ZFMTS 6 -#define FIRST_NON_STENCIL_ZFMT 3 - static D3DFORMAT FormatPrefList[NUM_TEST_ZFMTS] = { - D3DFMT_D24S8, D3DFMT_D24X4S4, D3DFMT_D15S1, // with stencil - D3DFMT_D32, D3DFMT_D24X8, D3DFMT_D16 // without stencil - }; - - // do not use Display._display_mode since that is probably not set yet, use Test_display_mode instead - - *pBestFmt = D3DFMT_UNKNOWN; - HRESULT hr; - - // nvidia likes zbuf depth to match rendertarget depth - bool bOnlySelect16bpp = (bForce16bpp || - (IS_NVIDIA(Display._dx_device_id) && IS_16BPP_DISPLAY_FORMAT(Test_display_mode.Format))); - - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "FindBestDepthFmt: bSelectOnly16bpp: " << bOnlySelect16bpp << endl; - } - - int first_format = (bWantStencil ? 0 : FIRST_NON_STENCIL_ZFMT); - for (int i = first_format; i < NUM_TEST_ZFMTS; i++) { - D3DFORMAT TestDepthFmt = FormatPrefList[i]; - - if (bOnlySelect16bpp && !IS_16BPP_ZBUFFER(TestDepthFmt)) { - continue; - } - - hr = Display._d3d8->CheckDeviceFormat(Display._card_id, - D3DDEVTYPE_HAL, - Test_display_mode.Format, - D3DUSAGE_DEPTHSTENCIL, - D3DRTYPE_SURFACE, TestDepthFmt); - - if (FAILED(hr)) { - if (hr == D3DERR_NOTAVAILABLE) { - if (bVerboseMode) - wdxdisplay8_cat.info() - << "FindBestDepthFmt: ChkDevFmt returns NotAvail for " - << D3DFormatStr(TestDepthFmt) << endl; - continue; - } - - wdxdisplay8_cat.error() - << "unexpected CheckDeviceFormat failure" << D3DERRORSTRING(hr) - << endl; - exit(1); - } - - hr = Display._d3d8->CheckDepthStencilMatch(Display._card_id, - D3DDEVTYPE_HAL, - Test_display_mode.Format, // adapter format - Test_display_mode.Format, // backbuffer fmt (should be the same in my apps) - TestDepthFmt); - if (SUCCEEDED(hr)) { - *pBestFmt = TestDepthFmt; - break; - } else { - if (hr == D3DERR_NOTAVAILABLE) { - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "FindBestDepthFmt: ChkDepMatch returns NotAvail for " - << D3DFormatStr(Test_display_mode.Format) << ", " - << D3DFormatStr(TestDepthFmt) << endl; - } - } else { - wdxdisplay8_cat.error() - << "unexpected CheckDepthStencilMatch failure for " - << D3DFormatStr(Test_display_mode.Format) << ", " - << D3DFormatStr(TestDepthFmt) << endl; - } - } - } - - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "FindBestDepthFmt returns fmt " << D3DFormatStr(*pBestFmt) << endl; - } - - return (*pBestFmt != D3DFMT_UNKNOWN); -} - - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::special_check_fullscreen_resolution -// Access: Private -// Description: overrides of the general estimator for known working -// cases -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsPipe8:: -special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size, UINT y_size) { - DWORD VendorId = scrn._dx_device_id.VendorId; - DWORD DeviceId = scrn._dx_device_id.DeviceId; - - switch (VendorId) { - case 0x8086: // Intel - if ((x_size == 640) && (y_size == 480)) { - return true; - } - if ((x_size == 800) && (y_size == 600)) { - return true; - } - if ((x_size == 1024) && (y_size == 768)) { - return true; - } - break; - } - - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::search_for_valid_displaymode -// Access: Private -// Description: All ptr args are output parameters. If no valid mode -// found, returns *pSuggestedPixFmt = D3DFMT_UNKNOWN; -//////////////////////////////////////////////////////////////////// -void wdxGraphicsPipe8:: -search_for_valid_displaymode(DXScreenData &scrn, - UINT RequestedX_Size, UINT RequestedY_Size, - bool bWantZBuffer, bool bWantStencil, - UINT *p_supported_screen_depths_mask, - bool *pCouldntFindAnyValidZBuf, - D3DFORMAT *pSuggestedPixFmt, - bool bForce16bppZBuffer, - bool bVerboseMode) { - - nassertv(IS_VALID_PTR(scrn._d3d8)); - HRESULT hr; - - *pSuggestedPixFmt = D3DFMT_UNKNOWN; - *p_supported_screen_depths_mask = 0x0; - *pCouldntFindAnyValidZBuf = false; - - int cNumModes = scrn._d3d8->GetAdapterModeCount(scrn._card_id); - D3DDISPLAYMODE BestDispMode; - ZeroMemory(&BestDispMode, sizeof(BestDispMode)); - - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "searching for valid display modes at res: (" - << RequestedX_Size << ", " << RequestedY_Size - << "), TotalModes: " << cNumModes << endl; - } - - // ignore memory based checks for min res 640x480. some cards just - // don't give accurate memavails. (should I do the check anyway for - // 640x480 32bpp?) - bool bDoMemBasedChecks = - ((!((RequestedX_Size == 640)&&(RequestedY_Size == 480))) && - (scrn._max_available_video_memory != UNKNOWN_VIDMEM_SIZE) && - (!special_check_fullscreen_resolution(scrn, RequestedX_Size, RequestedY_Size))); - - if (bVerboseMode || wdxdisplay8_cat.is_spam()) { - wdxdisplay8_cat.info() - << "DoMemBasedChecks = " << bDoMemBasedChecks << endl; - } - - for (int i = 0; i < cNumModes; i++) { - D3DDISPLAYMODE dispmode; - hr = scrn._d3d8->EnumAdapterModes(scrn._card_id, i, &dispmode); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "EnumAdapter_display_mode failed for device #" - << scrn._card_id << D3DERRORSTRING(hr); - continue; - } - - if ((dispmode.Width != RequestedX_Size) || - (dispmode.Height != RequestedY_Size)) { - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "Mode dimension " << dispmode.Width << "x" << dispmode.Height - << "; format " << D3DFormatStr(dispmode.Format) - << ": onto next mode\n"; - } - continue; - } - - // disable refresh rate checking since SLI video cards may use - // refresh rates less than 60 - if (0) { - if ((dispmode.RefreshRate<60) && (dispmode.RefreshRate>1)) { - // don't want refresh rates under 60Hz, but 0 or 1 might indicate - // a default refresh rate, which is usually > = 60 - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "skipping mode[" << i << "], bad refresh rate: " - << dispmode.RefreshRate << endl; - } - continue; - } - } - - // Note no attempt is made to verify if format will work at - // requested size, so even if this call succeeds, could still get - // an out-of-video-mem error - - hr = scrn._d3d8->CheckDeviceFormat(scrn._card_id, D3DDEVTYPE_HAL, dispmode.Format, - D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, - dispmode.Format); - if (FAILED(hr)) { - if (hr == D3DERR_NOTAVAILABLE) { - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "skipping mode[" << i - << "], CheckDevFmt returns NotAvail for fmt: " - << D3DFormatStr(dispmode.Format) << endl; - } - continue; - } else { - wdxdisplay8_cat.error() - << "CheckDeviceFormat failed for device #" - << scrn._card_id << D3DERRORSTRING(hr); - continue; - } - } - - bool bIs16bppRenderTgt = IS_16BPP_DISPLAY_FORMAT(dispmode.Format); - PN_stdfloat RendTgtMinMemReqmt = 0.0f; - - // if we have a valid memavail value, try to determine if we have - // enough space - if (bDoMemBasedChecks) { - // assume user is testing fullscreen, not windowed, so use the - // dwTotal value see if 3 scrnbufs (front/back/z)at 16bpp at - // x_size*y_size will fit with a few extra megs for texmem - - // 8MB Rage Pro says it has 6.8 megs Total free and will run at - // 1024x768, so formula makes it so that is OK - -#define REQD_TEXMEM 1800000 - - PN_stdfloat bytes_per_pixel = (bIs16bppRenderTgt ? 2 : 4); - - // *2 for double buffer - - RendTgtMinMemReqmt = - ((PN_stdfloat)RequestedX_Size) * ((PN_stdfloat)RequestedY_Size) * - bytes_per_pixel * 2 + REQD_TEXMEM; - - if (bVerboseMode || wdxdisplay8_cat.is_spam()) - wdxdisplay8_cat.info() - << "Testing Mode (" < scrn._max_available_video_memory) { - if (bVerboseMode || wdxdisplay8_cat.is_debug()) - wdxdisplay8_cat.info() - << "not enough VidMem for render tgt, skipping display fmt " - << D3DFormatStr(dispmode.Format) << " (" - << (int)RendTgtMinMemReqmt << " > " - << scrn._max_available_video_memory << ")\n"; - continue; - } - } - - if (bWantZBuffer) { - D3DFORMAT zformat; - if (!find_best_depth_format(scrn, dispmode, &zformat, - bWantStencil, bForce16bppZBuffer)) { - *pCouldntFindAnyValidZBuf = true; - continue; - } - - PN_stdfloat MinMemReqmt = 0.0f; - - if (bDoMemBasedChecks) { - // test memory again, this time including zbuf size - PN_stdfloat zbytes_per_pixel = (IS_16BPP_ZBUFFER(zformat) ? 2 : 4); - PN_stdfloat MinMemReqmt = RendTgtMinMemReqmt + ((PN_stdfloat)RequestedX_Size)*((PN_stdfloat)RequestedY_Size)*zbytes_per_pixel; - - if (bVerboseMode || wdxdisplay8_cat.is_spam()) - wdxdisplay8_cat.info() - << "Testing Mode w/Z (" << RequestedX_Size << "x" - << RequestedY_Size << ", " << D3DFormatStr(dispmode.Format) - << ")\nReqdVidMem: " << (int)MinMemReqmt << " AvailVidMem: " - << scrn._max_available_video_memory << endl; - - if (MinMemReqmt > scrn._max_available_video_memory) { - if (bVerboseMode || wdxdisplay8_cat.is_debug()) - wdxdisplay8_cat.info() - << "not enough VidMem for RendTgt+zbuf, skipping display fmt " - << D3DFormatStr(dispmode.Format) << " (" << (int)MinMemReqmt - << " > " << scrn._max_available_video_memory << ")\n"; - continue; - } - } - -// Optimizing for 16-bit depth does not work in all cases so turn it off. - if (false) { - if ((!bDoMemBasedChecks) || (MinMemReqmt_Scrn, scrn, sizeof(device->_Scrn)); - device->_d3d_device = device->_Scrn._d3d_device; - - _device = device; - wdxdisplay8_cat.info() << "walla: device" << device << "\n"; - - return device.p(); -} - -pmap g_D3DFORMATmap; - -void Init_D3DFORMAT_map() { - if (g_D3DFORMATmap.size() != 0) - return; - -#define INSERT_ELEM(XX) g_D3DFORMATmap[XX##_FLAG] = D3DFMT_##XX; - - INSERT_ELEM(R8G8B8); - INSERT_ELEM(A8R8G8B8); - INSERT_ELEM(X8R8G8B8); - INSERT_ELEM(R5G6B5); - INSERT_ELEM(X1R5G5B5); - INSERT_ELEM(A1R5G5B5); - INSERT_ELEM(A4R4G4B4); - INSERT_ELEM(R3G3B2); - INSERT_ELEM(A8); - INSERT_ELEM(A8R3G3B2); - INSERT_ELEM(X4R4G4B4); - INSERT_ELEM(A2B10G10R10); - INSERT_ELEM(G16R16); - INSERT_ELEM(A8P8); - INSERT_ELEM(P8); - INSERT_ELEM(L8); - INSERT_ELEM(A8L8); - INSERT_ELEM(A4L4); - INSERT_ELEM(V8U8); - INSERT_ELEM(L6V5U5); - INSERT_ELEM(X8L8V8U8); - INSERT_ELEM(Q8W8V8U8); - INSERT_ELEM(V16U16); - INSERT_ELEM(W11V11U10); - INSERT_ELEM(A2W10V10U10); - INSERT_ELEM(UYVY); - INSERT_ELEM(YUY2); - INSERT_ELEM(DXT1); - INSERT_ELEM(DXT2); - INSERT_ELEM(DXT3); - INSERT_ELEM(DXT4); - INSERT_ELEM(DXT5); -} - - - -const char *D3DFormatStr(D3DFORMAT fmt) { - -#define CASESTR(XX) case XX: return #XX; - switch(fmt) { - CASESTR(D3DFMT_UNKNOWN); - CASESTR(D3DFMT_R8G8B8); - CASESTR(D3DFMT_A8R8G8B8); - CASESTR(D3DFMT_X8R8G8B8); - CASESTR(D3DFMT_R5G6B5); - CASESTR(D3DFMT_X1R5G5B5); - CASESTR(D3DFMT_A1R5G5B5); - CASESTR(D3DFMT_A4R4G4B4); - CASESTR(D3DFMT_R3G3B2); - CASESTR(D3DFMT_A8); - CASESTR(D3DFMT_A8R3G3B2); - CASESTR(D3DFMT_X4R4G4B4); - CASESTR(D3DFMT_A2B10G10R10); - CASESTR(D3DFMT_G16R16); - CASESTR(D3DFMT_A8P8); - CASESTR(D3DFMT_P8); - CASESTR(D3DFMT_L8); - CASESTR(D3DFMT_A8L8); - CASESTR(D3DFMT_A4L4); - CASESTR(D3DFMT_V8U8); - CASESTR(D3DFMT_L6V5U5); - CASESTR(D3DFMT_X8L8V8U8); - CASESTR(D3DFMT_Q8W8V8U8); - CASESTR(D3DFMT_V16U16); - CASESTR(D3DFMT_W11V11U10); - CASESTR(D3DFMT_A2W10V10U10); - CASESTR(D3DFMT_UYVY); - CASESTR(D3DFMT_YUY2); - CASESTR(D3DFMT_DXT1); - CASESTR(D3DFMT_DXT2); - CASESTR(D3DFMT_DXT3); - CASESTR(D3DFMT_DXT4); - CASESTR(D3DFMT_DXT5); - CASESTR(D3DFMT_D16_LOCKABLE); - CASESTR(D3DFMT_D32); - CASESTR(D3DFMT_D15S1); - CASESTR(D3DFMT_D24S8); - CASESTR(D3DFMT_D16); - CASESTR(D3DFMT_D24X8); - CASESTR(D3DFMT_D24X4S4); - CASESTR(D3DFMT_VERTEXDATA); - CASESTR(D3DFMT_INDEX16); - CASESTR(D3DFMT_INDEX32); - } - - return "Invalid D3DFORMAT"; -} - diff --git a/panda/src/dxgsg8/wdxGraphicsPipe8.h b/panda/src/dxgsg8/wdxGraphicsPipe8.h deleted file mode 100644 index 91606306f6..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsPipe8.h +++ /dev/null @@ -1,122 +0,0 @@ -// Filename: wdxGraphicsPipe8.h -// Created by: drose (20Dec02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef WDXGRAPHICSPIPE8_H -#define WDXGRAPHICSPIPE8_H - -#include "pandabase.h" -#include "winGraphicsPipe.h" -#include "pvector.h" -#include "dxgsg8base.h" -#include - -//////////////////////////////////////////////////////////////////// -// Class : wdxGraphicsPipe8 -// Description : This graphics pipe represents the interface for -// creating DirectX8 graphics windows. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX wdxGraphicsPipe8 : public WinGraphicsPipe { -public: - wdxGraphicsPipe8(); - virtual ~wdxGraphicsPipe8(); - - virtual string get_interface_name() const; - static PT(GraphicsPipe) pipe_constructor(); - - virtual PT(GraphicsDevice) make_device(void *scrn); - - bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &Test_display_mode, - D3DFORMAT *pBestFmt, bool bWantStencil, - bool bForce16bpp, bool bVerboseMode = false) const; - - void search_for_valid_displaymode(DXScreenData &scrn, - UINT RequestedX_Size, UINT RequestedY_Size, - bool bWantZBuffer, bool bWantStencil, - UINT *p_supported_screen_depths_mask, - bool *pCouldntFindAnyValidZBuf, - D3DFORMAT *pSuggestedPixFmt, - bool bForce16bppZBuffer, - bool bVerboseMode = false); - - bool special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size,UINT y_size); - -protected: - virtual PT(GraphicsOutput) make_output(const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsEngine *engine, - GraphicsStateGuardian *gsg, - GraphicsOutput *host, - int retry, - bool &precertify); - -private: - bool init(); - bool find_all_card_memavails(); - - static BOOL WINAPI - dx7_driver_enum_callback(GUID *pGUID, TCHAR *strDesc, TCHAR *strName, - VOID *argptr, HMONITOR hm); - -private: - HINSTANCE _hDDrawDLL; - HINSTANCE _hD3D8_DLL; - LPDIRECT3D8 __d3d8; - - - typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion); - typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter); - - LPDIRECTDRAWCREATEEX _DirectDrawCreateEx; - LPDIRECTDRAWENUMERATEEX _DirectDrawEnumerateExA; - Direct3DCreate8_ProcPtr _Direct3DCreate8; - - // CardID is used in DX7 lowmem card-classification pass so DX8 can - // establish correspondence b/w DX7 mem info & DX8 device - struct CardID { - HMONITOR _monitor; - DWORD _max_available_video_memory; - bool _is_low_memory_card; - GUID DX7_DeviceGUID; - DWORD VendorID, DeviceID; - }; - - typedef pvector CardIDs; - CardIDs _card_ids; - bool __is_dx8_1; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - WinGraphicsPipe::init_type(); - register_type(_type_handle, "wdxGraphicsPipe8", - WinGraphicsPipe::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; - - friend class wdxGraphicsWindow8; -}; - -#include "wdxGraphicsPipe8.I" - -#endif diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.I b/panda/src/dxgsg8/wdxGraphicsWindow8.I deleted file mode 100644 index fc44aa533a..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.I +++ /dev/null @@ -1,13 +0,0 @@ -// Filename: wdxGraphicsWindow8.I -// Created by: drose (20Dec02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx deleted file mode 100644 index 077274e36d..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx +++ /dev/null @@ -1,1241 +0,0 @@ -// Filename: wdxGraphicsWindow8.cxx -// Created by: mike (09Jan00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "wdxGraphicsPipe8.h" -#include "wdxGraphicsWindow8.h" -#include "config_dxgsg8.h" -#include "config_display.h" -#include "keyboardButton.h" -#include "mouseButton.h" -#include "throw_event.h" -#include "pStatTimer.h" -#include "pmap.h" -#include -#include -#include -#include -#include - -TypeHandle wdxGraphicsWindow8::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -wdxGraphicsWindow8:: -wdxGraphicsWindow8(GraphicsEngine *engine, GraphicsPipe *pipe, - const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsStateGuardian *gsg, - GraphicsOutput *host): - WinGraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) -{ - // don't actually create the window in the constructor. reason: - // multi-threading requires panda C++ window object to exist in - // separate thread from actual API window - - _dxgsg = DCAST(DXGraphicsStateGuardian8, gsg); - _depth_buffer_bpp = 0; - _awaiting_restore = false; - ZeroMemory(&_wcontext, sizeof(_wcontext)); -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -wdxGraphicsWindow8:: -~wdxGraphicsWindow8() { -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::begin_frame -// Access: Public, Virtual -// Description: This function will be called within the draw thread -// before beginning rendering for a given frame. It -// should do whatever setup is required, and return true -// if the frame should be rendered, or false if it -// should be skipped. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -begin_frame(FrameMode mode, Thread *current_thread) { - begin_frame_spam(mode); - if (_gsg == (GraphicsStateGuardian *)NULL) { - return false; - } - - if (_awaiting_restore) { - // The fullscreen window was recently restored; we can't continue - // until the GSG says we can. - if (!_dxgsg->check_cooperative_level()) { - // Keep waiting. - return false; - } - _awaiting_restore = false; - init_resized_window(); - } - - make_current(); - - if (mode == FM_render) { - clear_cube_map_selection(); - } - - _gsg->set_current_properties(&get_fb_properties()); - bool return_val = _gsg->begin_frame(current_thread); - _dxgsg->set_render_target(); - return return_val; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::end_frame -// Access: Public, Virtual -// Description: This function will be called within the draw thread -// after rendering is completed for a given frame. It -// should do whatever finalization is required. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -end_frame(FrameMode mode, Thread *current_thread) { - - end_frame_spam(mode); - nassertv(_gsg != (GraphicsStateGuardian *)NULL); - - if (mode == FM_render) { - copy_to_textures(); - } - - _gsg->end_frame(current_thread); - - if (mode == FM_render) { - trigger_flip(); - clear_cube_map_selection(); - } -} -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::make_current -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -make_current() { - PStatTimer timer(_make_current_pcollector); - - _dxgsg->set_context(&_wcontext); - - // Now that we have made the context current to a window, we can - // reset the GSG state if this is the first time it has been used. - // (We can't just call reset() when we construct the GSG, because - // reset() requires having a current context.) - _dxgsg->reset_if_new(); -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::end_flip -// Access: Public, Virtual -// Description: This function will be called within the draw thread -// after begin_flip() has been called on all windows, to -// finish the exchange of the front and back buffers. -// -// This should cause the window to wait for the flip, if -// necessary. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -end_flip() { - if (_dxgsg != (DXGraphicsStateGuardian8 *)NULL && is_active()) { - _dxgsg->show_frame(); - } - GraphicsWindow::end_flip(); -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::verify_window_sizes -// Access: Public, Virtual -// Description: Determines which of the indicated window sizes are -// supported by available hardware (e.g. in fullscreen -// mode). -// -// On entry, dimen is an array containing contiguous x, y -// pairs specifying possible display sizes; it is -// numsizes*2 words long. The function will zero out -// any invalid x, y size pairs. The return value is the -// number of valid sizes that were found. -//////////////////////////////////////////////////////////////////// -int wdxGraphicsWindow8:: -verify_window_sizes(int numsizes, int *dimen) { - // unfortunately this only works AFTER you make the window - // initially, so its really mostly useful for resizes only - nassertr(IS_VALID_PTR(_dxgsg), 0); - - int num_valid_modes = 0; - - wdxGraphicsPipe8 *dxpipe; - DCAST_INTO_R(dxpipe, _pipe, 0); - - // not requesting same refresh rate since changing res might not - // support same refresh rate at new size - - int *pCurDim = dimen; - - for (int i = 0; i < numsizes; i++, pCurDim += 2) { - int x_size = pCurDim[0]; - int y_size = pCurDim[1]; - - bool bIsGoodMode = false; - bool CouldntFindAnyValidZBuf; - D3DFORMAT newPixFmt = D3DFMT_UNKNOWN; - - if (dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) { - // bypass the test below for certain cards we know have valid modes - bIsGoodMode = true; - - } else { - if (_wcontext._is_low_memory_card) { - bIsGoodMode = ((x_size == 640) && (y_size == 480)); - } else { - dxpipe->search_for_valid_displaymode - (_wcontext, x_size, y_size, _wcontext._presentation_params.EnableAutoDepthStencil != false, - IS_STENCIL_FORMAT(_wcontext._presentation_params.AutoDepthStencilFormat), - &_wcontext._supported_screen_depths_mask, - &CouldntFindAnyValidZBuf, &newPixFmt, dx_force_16bpp_zbuffer); - bIsGoodMode = (newPixFmt != D3DFMT_UNKNOWN); - } - } - - if (bIsGoodMode) { - num_valid_modes++; - } else { - // tell caller the mode is invalid - pCurDim[0] = 0; - pCurDim[1] = 0; - } - - if (wdxdisplay8_cat.is_spam()) { - wdxdisplay8_cat.spam() - << "Fullscrn Mode (" << x_size << ", " << y_size << ")\t" - << (bIsGoodMode ? "V" : "Inv") << "alid\n"; - } - } - - return num_valid_modes; -} - -////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow::close_window -// Access: Public -// Description: Some cleanup is necessary for directx closeup of window. -// Handle close window events for this particular -// window. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -close_window() { - if (wdxdisplay8_cat.is_debug()) { - wdxdisplay8_cat.debug() - << "wdxGraphicsWindow8::close_window() " << this << "\n"; - } - - if (_gsg != (GraphicsStateGuardian*)NULL) { - _gsg.clear(); - } - - _dxgsg->release_swap_chain(&_wcontext); - WinGraphicsWindow::close_window(); -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::open_window -// Access: Protected, Virtual -// Description: Opens the window right now. Called from the window -// thread. Returns true if the window is successfully -// opened, or false if there was a problem. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -open_window() { - PT(DXGraphicsDevice8) dxdev; - WindowProperties props; - - // For now, let's make this configurable. If this is true, then you - // can't open multiple different windows with the same GSG, but you - // may have more luck opening different windows with different - // GSG's. - static ConfigVariableBool always_discard_device("always-discard-device", true); - bool discard_device = always_discard_device; - - // GSG creation/initialization. - if (_gsg == 0) { - _dxgsg = new DXGraphicsStateGuardian8(_engine, _pipe); - _gsg = _dxgsg; - } else { - DCAST_INTO_R(_dxgsg, _gsg, false); - } - - if (!choose_device()) { - return false; - } - - // Ensure the window properties get set to the actual size of the - // window. - { - WindowProperties resized_props; - resized_props.set_size(_wcontext._display_mode.Width, - _wcontext._display_mode.Height); - _properties.add_properties(resized_props); - } - - wdxdisplay8_cat.debug() << "_wcontext._window is " << _wcontext._window << "\n"; - if (!WinGraphicsWindow::open_window()) { - return false; - } - _wcontext._window = _hWnd; - - wdxdisplay8_cat.debug() << "_wcontext._window is " << _wcontext._window << "\n"; - - // Here check if a device already exists. If so, then this open_window - // call may be an extension to create multiple windows on same device - // In that case just create an additional swapchain for this window - - while (true) { - if (_dxgsg->get_pipe()->get_device() == NULL || discard_device) { - wdxdisplay8_cat.debug() << "device is null or fullscreen\n"; - - // If device exists, free it - if (_dxgsg->get_pipe()->get_device()) { - _dxgsg->dx_cleanup(); - } - - wdxdisplay8_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n"; - if (!create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer)) { - wdxdisplay8_cat.error() << "Unable to create window with specified parameters.\n"; - close_window(); - return false; - } - _dxgsg->get_pipe()->make_device((void*)(&_wcontext)); - _dxgsg->copy_pres_reset(&_wcontext); - _dxgsg->create_swap_chain(&_wcontext); - break; - - } else { - // fill in the DXScreenData from dxdevice here and change the - // reference to _window. - wdxdisplay8_cat.debug() << "device is not null\n"; - - dxdev = (DXGraphicsDevice8*)(_dxgsg->get_pipe()->get_device()); - props = get_properties(); - memcpy(&_wcontext, &dxdev->_Scrn, sizeof(DXScreenData)); - - _wcontext._presentation_params.Windowed = !is_fullscreen(); - _wcontext._presentation_params.hDeviceWindow = _wcontext._window = _hWnd; - _wcontext._presentation_params.BackBufferWidth = _wcontext._display_mode.Width = props.get_x_size(); - _wcontext._presentation_params.BackBufferHeight = _wcontext._display_mode.Height = props.get_y_size(); - - wdxdisplay8_cat.debug() << "device width " << _wcontext._presentation_params.BackBufferWidth << "\n"; - if (!_dxgsg->create_swap_chain(&_wcontext)) { - discard_device = true; - continue; // try again - } - init_resized_window(); - break; - } - } - wdxdisplay8_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n"; - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::reset_window -// Access: Public, Virtual -// Description: Resets the window framebuffer right now. Called -// from graphicsEngine. It releases the current swap -// chain / creates a new one. If this is the initial -// window and swapchain is false, then it calls reset_ -// main_device to Reset the device. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -reset_window(bool swapchain) { - if (swapchain) { - if (_wcontext._swap_chain) { - _dxgsg->create_swap_chain(&_wcontext); - wdxdisplay8_cat.debug() << "created swapchain " << _wcontext._swap_chain << "\n"; - } - } - else { - if (_wcontext._swap_chain) { - _dxgsg->release_swap_chain(&_wcontext); - wdxdisplay8_cat.debug() << "released swapchain " << _wcontext._swap_chain << "\n"; - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::fullscreen_restored -// Access: Protected, Virtual -// Description: This is a hook for derived classes to do something -// special, if necessary, when a fullscreen window has -// been restored after being minimized. The given -// WindowProperties struct will be applied to this -// window's properties after this function returns. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -fullscreen_restored(WindowProperties &properties) { - // In DX8, unlike DX7, for some reason we can't immediately start - // rendering as soon as the window is restored, even though - // BeginScene() says we can. Instead, we have to wait until - // TestCooperativeLevel() lets us in. We need to set a flag so we - // can handle this special case in begin_frame(). - if (_dxgsg != NULL) { - _awaiting_restore = true; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::handle_reshape -// Access: Protected, Virtual -// Description: Called in the window thread when the window size or -// location is changed, this updates the properties -// structure accordingly. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -handle_reshape() { - GdiFlush(); - WinGraphicsWindow::handle_reshape(); - - if (_dxgsg != NULL && _dxgsg->_d3d_device != NULL) { - // create the new resized rendertargets - WindowProperties props = get_properties(); - int x_size = props.get_x_size(); - int y_size = props.get_y_size(); - - if (_wcontext._presentation_params.BackBufferWidth != x_size || - _wcontext._presentation_params.BackBufferHeight != y_size) { - bool resize_succeeded = reset_device_resize_window(x_size, y_size); - - if (wdxdisplay8_cat.is_debug()) { - if (!resize_succeeded) { - wdxdisplay8_cat.debug() - << "windowed_resize to size: (" << x_size << ", " << y_size - << ") failed due to out-of-memory\n"; - } else { - int x_origin = props.get_x_origin(); - int y_origin = props.get_y_origin(); - wdxdisplay8_cat.debug() - << "windowed_resize to origin: (" << x_origin << ", " - << y_origin << "), size: (" << x_size - << ", " << y_size << ")\n"; - } - } - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::do_fullscreen_resize -// Access: Protected, Virtual -// Description: Called in the window thread to resize a fullscreen -// window. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -do_fullscreen_resize(int x_size, int y_size) { - if (!WinGraphicsWindow::do_fullscreen_resize(x_size, y_size)) { - return false; - } - - bool bCouldntFindValidZBuf; - D3DFORMAT pixFmt; - bool bNeedZBuffer = (_wcontext._presentation_params.EnableAutoDepthStencil != false); - bool bNeedStencilBuffer = IS_STENCIL_FORMAT(_wcontext._presentation_params.AutoDepthStencilFormat); - - wdxGraphicsPipe8 *dxpipe; - DCAST_INTO_R(dxpipe, _pipe, false); - - bool bIsGoodMode = false; - bool bResizeSucceeded = false; - - if (!dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) { - // bypass the lowvidmem test below for certain "lowmem" cards we know have valid modes - - if (_wcontext._is_low_memory_card && (!((x_size == 640) && (y_size == 480)))) { - wdxdisplay8_cat.error() << "resize() failed: will not try to resize low vidmem device #" << _wcontext._card_id << " to non-640x480!\n"; - return bResizeSucceeded; - } - } - - // must ALWAYS use search_for_valid_displaymode even if we know - // a-priori that res is valid so we can get a valid pixfmt - dxpipe->search_for_valid_displaymode(_wcontext, x_size, y_size, - bNeedZBuffer, bNeedStencilBuffer, - &_wcontext._supported_screen_depths_mask, - &bCouldntFindValidZBuf, - &pixFmt, dx_force_16bpp_zbuffer); - bIsGoodMode = (pixFmt != D3DFMT_UNKNOWN); - - if (!bIsGoodMode) { - wdxdisplay8_cat.error() << "resize() failed: " - << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes") - << " at " << x_size << "x" << y_size << " for device #" << _wcontext._card_id << endl; - return bResizeSucceeded; - } - - // reset_device_resize_window handles both windowed & fullscrn, - // so need to set new displaymode manually here - _wcontext._display_mode.Width = x_size; - _wcontext._display_mode.Height = y_size; - _wcontext._display_mode.Format = pixFmt; - _wcontext._display_mode.RefreshRate = D3DPRESENT_RATE_DEFAULT; - - _wcontext._presentation_params.BackBufferFormat = pixFmt; // make reset_device_resize use presparams or displaymode?? - - bResizeSucceeded = reset_device_resize_window(x_size, y_size); - - if (!bResizeSucceeded) { - wdxdisplay8_cat.error() << "resize() failed with OUT-OF-MEMORY error!\n"; - - if ((!IS_16BPP_DISPLAY_FORMAT(_wcontext._presentation_params.BackBufferFormat)) && - (_wcontext._supported_screen_depths_mask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) { - // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers - _wcontext._display_mode.Format = ((_wcontext._supported_screen_depths_mask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5); - dx_force_16bpp_zbuffer = true; - if (wdxdisplay8_cat.info()) - wdxdisplay8_cat.info() << "CreateDevice failed with out-of-vidmem, retrying w/16bpp buffers on device #" << _wcontext._card_id << endl; - - bResizeSucceeded = reset_device_resize_window(x_size, y_size); // create the new resized rendertargets - } - } - - return bResizeSucceeded; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::create_screen_buffers_and_device -// Access: Private -// Description: Called whenever the window is resized, this recreates -// the necessary buffers for rendering. -// -// Sets _depth_buffer_bpp appropriately. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer) { - wdxGraphicsPipe8 *dxpipe; - DCAST_INTO_R(dxpipe, _pipe, false); - - DWORD dwRenderWidth = display._display_mode.Width; - DWORD dwRenderHeight = display._display_mode.Height; - DWORD dwBehaviorFlags = 0x0; - LPDIRECT3D8 _d3d8 = display._d3d8; - D3DCAPS8 *pD3DCaps = &display._d3dcaps; - D3DPRESENT_PARAMETERS* presentation_params = &display._presentation_params; - RECT view_rect; - HRESULT hr; - - wdxdisplay8_cat.debug() << "Display Width " << dwRenderWidth << " and PresParam Width " << _wcontext._presentation_params.BackBufferWidth << "\n"; - - bool bWantStencil = (_fb_properties.get_stencil_bits() > 0); - - PRINT_REFCNT(wdxdisplay8, _d3d8); - - nassertr(_d3d8 != NULL, false); - nassertr(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION, false); - - presentation_params->BackBufferFormat = display._display_mode.Format; // don't need dest alpha, so just use adapter format - cerr << "attempting " << D3DFormatStr(presentation_params->BackBufferFormat) << "\n"; - - bool do_sync = sync_video; - - if (do_sync && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) { - wdxdisplay8_cat.info() - << "HW doesnt support syncing to vertical refresh, ignoring sync-video\n"; - do_sync = false; - } - - // verify the rendertarget fmt one last time - if (FAILED(_d3d8->CheckDeviceFormat(display._card_id, D3DDEVTYPE_HAL, display._display_mode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_SURFACE, presentation_params->BackBufferFormat))) { - wdxdisplay8_cat.error() << "device #" << display._card_id << " CheckDeviceFmt failed for surface fmt " << D3DFormatStr(presentation_params->BackBufferFormat) << endl; - goto Fallback_to_16bpp_buffers; - } - - if (FAILED(_d3d8->CheckDeviceType(display._card_id, D3DDEVTYPE_HAL, display._display_mode.Format, presentation_params->BackBufferFormat, - is_fullscreen()))) { - wdxdisplay8_cat.error() << "device #" << display._card_id << " CheckDeviceType failed for surface fmt " << D3DFormatStr(presentation_params->BackBufferFormat) << endl; - goto Fallback_to_16bpp_buffers; - } - - if (display._presentation_params.EnableAutoDepthStencil) { - if (!dxpipe->find_best_depth_format(display, display._display_mode, - &display._presentation_params.AutoDepthStencilFormat, - bWantStencil, false)) { - wdxdisplay8_cat.error() - << "find_best_depth_format failed in CreateScreenBuffers for device #" - << display._card_id << endl; - goto Fallback_to_16bpp_buffers; - } - _depth_buffer_bpp = D3DFMT_to_DepthBits(display._presentation_params.AutoDepthStencilFormat); - } else { - _depth_buffer_bpp = 0; - } - - presentation_params->Windowed = !is_fullscreen(); - - if (dx_multisample_antialiasing_level>1) { - // need to check both rendertarget and zbuffer fmts - hr = _d3d8->CheckDeviceMultiSampleType(display._card_id, D3DDEVTYPE_HAL, display._display_mode.Format, - is_fullscreen(), D3DMULTISAMPLE_TYPE(dx_multisample_antialiasing_level.get_value())); - if (FAILED(hr)) { - wdxdisplay8_cat.fatal() << "device #" << display._card_id << " doesnt support multisample level " << dx_multisample_antialiasing_level << "surface fmt " << D3DFormatStr(display._display_mode.Format) << endl; - return false; - } - - if (display._presentation_params.EnableAutoDepthStencil) { - hr = _d3d8->CheckDeviceMultiSampleType(display._card_id, D3DDEVTYPE_HAL, display._presentation_params.AutoDepthStencilFormat, - is_fullscreen(), D3DMULTISAMPLE_TYPE(dx_multisample_antialiasing_level.get_value())); - if (FAILED(hr)) { - wdxdisplay8_cat.fatal() << "device #" << display._card_id << " doesnt support multisample level " << dx_multisample_antialiasing_level << "surface fmt " << D3DFormatStr(display._presentation_params.AutoDepthStencilFormat) << endl; - return false; - } - } - - presentation_params->MultiSampleType = D3DMULTISAMPLE_TYPE(dx_multisample_antialiasing_level.get_value()); - - if (wdxdisplay8_cat.is_info()) - wdxdisplay8_cat.info() << "device #" << display._card_id << " using multisample antialiasing level " << dx_multisample_antialiasing_level << endl; - } - - presentation_params->BackBufferCount = 1; - presentation_params->Flags = 0x0; - presentation_params->hDeviceWindow = display._window; - presentation_params->BackBufferWidth = display._display_mode.Width; - presentation_params->BackBufferHeight = display._display_mode.Height; - - if (_wcontext._is_tnl_device) { - dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; - // note: we could create a pure device in this case if I - // eliminated the GetRenderState calls in dxgsg - - // also, no software vertex processing available since I specify - // D3DCREATE_HARDWARE_VERTEXPROCESSING and not - // D3DCREATE_MIXED_VERTEXPROCESSING - } else { - dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; - } - - if (dx_preserve_fpu_state) - dwBehaviorFlags |= D3DCREATE_FPU_PRESERVE; - - // if window is not foreground in exclusive mode, ddraw thinks you - // are 'not active', so it changes your WM_ACTIVATEAPP from true to - // false, causing us to go into a 'wait-for WM_ACTIVATEAPP true' - // loop, and the event never comes so we hang in fullscreen wait. - // also doing this for windowed mode since it was requested. - if (!SetForegroundWindow(display._window)) { - wdxdisplay8_cat.warning() << "SetForegroundWindow() failed!\n"; - } - - if (is_fullscreen()) { - // CREATE FULLSCREEN BUFFERS - - presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; // we don't care about preserving contents of old frame - presentation_params->FullScreen_PresentationInterval = (do_sync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE); - presentation_params->FullScreen_RefreshRateInHz = display._display_mode.RefreshRate; - - ClearToBlack(display._window, get_properties()); - - hr = _d3d8->CreateDevice(display._card_id, D3DDEVTYPE_HAL, _hWnd, - dwBehaviorFlags, presentation_params, &display._d3d_device); - - if (FAILED(hr)) { - wdxdisplay8_cat.fatal() << "D3D CreateDevice failed for device #" << display._card_id << ", " << D3DERRORSTRING(hr); - - if (hr == D3DERR_OUTOFVIDEOMEMORY) - goto Fallback_to_16bpp_buffers; - else - return false; - } - - SetRect(&view_rect, 0, 0, dwRenderWidth, dwRenderHeight); - - } else { - // CREATE WINDOWED BUFFERS - - D3DDISPLAYMODE dispmode; - hr = display._d3d8->GetAdapterDisplayMode(display._card_id, &dispmode); - - if (FAILED(hr)) { - wdxdisplay8_cat.fatal() - << "GetAdapterDisplayMode failed" << D3DERRORSTRING(hr); - return false; - } - - if (dispmode.Format == D3DFMT_P8) { - wdxdisplay8_cat.fatal() - << "Can't run windowed in an 8-bit or less display mode" << endl; - return false; - } - - presentation_params->FullScreen_PresentationInterval = 0; - - if (dx_multisample_antialiasing_level<2) { - if (do_sync) { - // It turns out that COPY_VSYNC has real performance problems - // on many nVidia cards--it syncs at some random interval, - // possibly skipping over several video syncs. Screw it, - // we'll effectively disable sync-video with windowed mode - // using DirectX8. - //presentation_params->SwapEffect = D3DSWAPEFFECT_COPY_VSYNC; - presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; - } else { - presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; - } - } else { - presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; - } - - //nassertv((dwRenderWidth == presentation_params->BackBufferWidth)&&(dwRenderHeight == presentation_params->BackBufferHeight)); - - hr = _d3d8->CreateDevice(display._card_id, D3DDEVTYPE_HAL, _hWnd, - dwBehaviorFlags, presentation_params, &display._d3d_device); - - if (FAILED(hr)) { - wdxdisplay8_cat.warning() << "presentation_params->BackBufferWidth : " << presentation_params->BackBufferWidth << endl; - wdxdisplay8_cat.warning() << "presentation_params->BackBufferHeight : " << presentation_params->BackBufferHeight << endl; - wdxdisplay8_cat.warning() << "presentation_params->BackBufferFormat : " << presentation_params->BackBufferFormat << endl; - wdxdisplay8_cat.warning() << "presentation_params->BackBufferCount : " << presentation_params->BackBufferCount << endl; - wdxdisplay8_cat.warning() << "D3D CreateDevice failed for device #" << display._card_id << D3DERRORSTRING(hr); - goto Fallback_to_16bpp_buffers; - } - } // end create windowed buffers - - // ======================================================== - - PRINT_REFCNT(wdxdisplay8, _wcontext._d3d_device); - - if (presentation_params->EnableAutoDepthStencil) { - int depth_bits; - int stencil_bits; - - depth_bits = 1; - stencil_bits = 0; - switch (presentation_params->AutoDepthStencilFormat) - { - case D3DFMT_D16_LOCKABLE: - depth_bits = 16; - break; - case D3DFMT_D32: - depth_bits = 32; - break; - case D3DFMT_D15S1: - depth_bits = 15; - stencil_bits = 1; - break; - case D3DFMT_D24S8: - depth_bits = 24; - stencil_bits = 8; - break; - case D3DFMT_D24X8: - depth_bits = 24; - break; - case D3DFMT_D24X4S4: - depth_bits = 24; - stencil_bits = 4; - break; - case D3DFMT_D16: - depth_bits = 16; - break; - default: - wdxdisplay8_cat.error() << "unknown depth stencil format " << presentation_params->AutoDepthStencilFormat; - break; - } - - _fb_properties.set_stencil_bits(stencil_bits); - _fb_properties.set_depth_bits(depth_bits); - } else { - _fb_properties.set_depth_bits(0); - _fb_properties.set_stencil_bits(0); - } - - init_resized_window(); - - return true; - - Fallback_to_16bpp_buffers: - if ((!IS_16BPP_DISPLAY_FORMAT(presentation_params->BackBufferFormat)) && - (display._supported_screen_depths_mask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) { - // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers - - display._display_mode.Format = ((display._supported_screen_depths_mask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5); - - if (wdxdisplay8_cat.info()) { - wdxdisplay8_cat.info() - << "CreateDevice failed with out-of-vidmem or invalid BackBufferFormat, retrying w/16bpp buffers on device #" - << display._card_id << endl; - } - return create_screen_buffers_and_device(display, true); - //return; - - } else if (!((dwRenderWidth == 640)&&(dwRenderHeight == 480))) { - if (wdxdisplay8_cat.info()) - wdxdisplay8_cat.info() << "CreateDevice failed w/out-of-vidmem, retrying at 640x480 w/16bpp buffers on device #" << display._card_id << endl; - // try final fallback to 640x480x16 - display._display_mode.Width = 640; - display._display_mode.Height = 480; - return create_screen_buffers_and_device(display, true); - //return; - - } else { - wdxdisplay8_cat.fatal() - << "Can't create any screen buffers, bailing out.\n"; - return false; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::choose_device -// Access: Private -// Description: Looks at the list of available graphics adapters and -// chooses a suitable one for the window. -// -// Returns true if successful, false on failure. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -choose_device() { - HRESULT hr; - - wdxGraphicsPipe8 *dxpipe; - DCAST_INTO_R(dxpipe, _pipe, false); - - int num_adapters = dxpipe->__d3d8->GetAdapterCount(); - DXDeviceInfoVec device_infos; - - for (int i = 0; i < num_adapters; i++) { - D3DADAPTER_IDENTIFIER8 adapter_info; - ZeroMemory(&adapter_info, sizeof(D3DADAPTER_IDENTIFIER8)); - hr = dxpipe->__d3d8->GetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, &adapter_info); - if (FAILED(hr)) { - wdxdisplay8_cat.fatal() - << "D3D GetAdapterID(" << i << ") failed: " - << D3DERRORSTRING(hr) << endl; - continue; - } - - LARGE_INTEGER *DrvVer = &adapter_info.DriverVersion; - - wdxdisplay8_cat.info() - << "D3D8." << (dxpipe->__is_dx8_1 ?"1":"0") << " Adapter[" << i << "]: " << adapter_info.Description - << ", Driver: " << adapter_info.Driver << ", DriverVersion: (" - << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "." - << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart) - << ")\nVendorID: 0x" << (void*) adapter_info.VendorId - << " DeviceID: 0x" << (void*) adapter_info.DeviceId - << " SubsysID: 0x" << (void*) adapter_info.SubSysId - << " Revision: 0x" << (void*) adapter_info.Revision << endl; - - HMONITOR _monitor = dxpipe->__d3d8->GetAdapterMonitor(i); - if (_monitor == NULL) { - wdxdisplay8_cat.info() - << "D3D8 Adapter[" << i << "]: seems to be disabled, skipping it\n"; - continue; - } - - DXDeviceInfo devinfo; - ZeroMemory(&devinfo, sizeof(devinfo)); - memcpy(&devinfo.guidDeviceIdentifier, &adapter_info.DeviceIdentifier, - sizeof(GUID)); - strncpy(devinfo.szDescription, adapter_info.Description, - MAX_DEVICE_IDENTIFIER_STRING); - strncpy(devinfo.szDriver, adapter_info.Driver, - MAX_DEVICE_IDENTIFIER_STRING); - devinfo.VendorID = adapter_info.VendorId; - devinfo.DeviceID = adapter_info.DeviceId; - devinfo._monitor = _monitor; - devinfo.cardID = i; - - device_infos.push_back(devinfo); - } - - if (device_infos.empty()) { - wdxdisplay8_cat.error() - << "No available D3D8 devices found.\n"; - return false; - } - - // Since some adapters may have been disabled, we should re-obtain - // the number of available adapters. - num_adapters = (int)device_infos.size(); - - // Now choose a suitable adapter. - - int adapter_num = D3DADAPTER_DEFAULT; - - // Eventually, we should have some interface for specifying a device - // index interactively, instead of only via Configrc. - if (dx_preferred_device_id != -1) { - if (dx_preferred_device_id < 0 || dx_preferred_device_id >= num_adapters) { - wdxdisplay8_cat.error() - << "invalid 'dx-preferred-device-id', valid values are 0-" - << num_adapters - 1 << ", using default adapter instead.\n"; - } else { - adapter_num = dx_preferred_device_id; - } - } - - UINT good_device_count = 0; - for(UINT devnum = 0;devnum__d3d8; - - nassertr(_dxgsg != NULL, false); - _wcontext._d3d8 = _d3d8; - _wcontext._is_dx8_1 = dxpipe->__is_dx8_1; - _wcontext._card_id = device_info->cardID; // could this change by end? - - bool bWantStencil = (_fb_properties.get_stencil_bits() > 0); - - hr = _d3d8->GetAdapterIdentifier(device_info->cardID, D3DENUM_NO_WHQL_LEVEL, - &_wcontext._dx_device_id); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "D3D GetAdapterID failed" << D3DERRORSTRING(hr); - return false; - } - - D3DCAPS8 _d3dcaps; - hr = _d3d8->GetDeviceCaps(device_info->cardID, D3DDEVTYPE_HAL, &_d3dcaps); - if (FAILED(hr)) { - if ((hr == D3DERR_INVALIDDEVICE)||(hr == D3DERR_NOTAVAILABLE)) { - wdxdisplay8_cat.error() - << "No DirectX 8 D3D-capable 3D hardware detected for device # " - << device_info->cardID << " (" << device_info->szDescription - << ")!\n"; - } else { - wdxdisplay8_cat.error() - << "GetDeviceCaps failed: " << D3DERRORSTRING(hr) << endl; - } - return false; - } - - //search_for_valid_displaymode needs these to be set - memcpy(&_wcontext._d3dcaps, &_d3dcaps, sizeof(D3DCAPS8)); - _wcontext._card_id = device_info->cardID; - - _wcontext._max_available_video_memory = UNKNOWN_VIDMEM_SIZE; - _wcontext._is_low_memory_card = false; - - // bugbug: wouldnt we like to do GetAVailVidMem so we can do - // upper-limit memory computation for dx8 cards too? otherwise - // verify_window_sizes cant do much - if (_d3dcaps.MaxStreams == 0) { - if (wdxdisplay8_cat.is_debug()) { - wdxdisplay8_cat.debug() - << "checking vidmem size\n"; - } - - UINT IDnum; - - // simple linear search to match DX7 card info w/DX8 card ID - for (IDnum = 0; IDnum < dxpipe->_card_ids.size(); IDnum++) { - if ((device_info->VendorID == dxpipe->_card_ids[IDnum].VendorID) && - (device_info->DeviceID == dxpipe->_card_ids[IDnum].DeviceID) && - (device_info->_monitor == dxpipe->_card_ids[IDnum]._monitor)) - break; - } - - if (IDnum < dxpipe->_card_ids.size()) { - _wcontext._max_available_video_memory = dxpipe->_card_ids[IDnum]._max_available_video_memory; - _wcontext._is_low_memory_card = dxpipe->_card_ids[IDnum]._is_low_memory_card; - } else { - wdxdisplay8_cat.error() - << "Error: couldnt find a CardID match in DX7 info, assuming card is not a lowmem card\n"; - } - } - - if ((bWantStencil) && (_d3dcaps.StencilCaps == 0x0)) { - wdxdisplay8_cat.fatal() - << "Stencil ability requested, but device #" << device_info->cardID - << " (" << _wcontext._dx_device_id.Description - << "), has no stencil capability!\n"; - return false; - } - - // just because TNL is true, it doesnt mean vtx shaders are - // supported in HW (see GF2) for this case, you probably want MIXED - // processing to use HW for fixed-fn vertex processing and SW for - // vtx shaders - _wcontext._is_tnl_device = - ((_d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0); - _wcontext._can_use_hw_vertex_shaders = - (_d3dcaps.VertexShaderVersion >= D3DVS_VERSION(1, 0)); - _wcontext._can_use_pixel_shaders = - (_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(1, 0)); - - bool bNeedZBuffer = - ((!(_d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) && - (_fb_properties.get_depth_bits() > 0)); - - _wcontext._presentation_params.EnableAutoDepthStencil = bNeedZBuffer; - - D3DFORMAT pixFmt = D3DFMT_UNKNOWN; - - if (is_fullscreen()) { - bool bCouldntFindValidZBuf; - dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight, - bNeedZBuffer, bWantStencil, - &_wcontext._supported_screen_depths_mask, - &bCouldntFindValidZBuf, - &pixFmt, dx_force_16bpp_zbuffer); - - // note I'm not saving refresh rate, will just use adapter - // default at given res for now - - if (pixFmt == D3DFMT_UNKNOWN) { - wdxdisplay8_cat.error() - << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes") - << " at " << dwRenderWidth << "x" << dwRenderHeight << " for device #" << _wcontext._card_id << endl; - - // run it again in verbose mode to get more dbg info to log - dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight, - bNeedZBuffer, bWantStencil, - &_wcontext._supported_screen_depths_mask, - &bCouldntFindValidZBuf, - &pixFmt, dx_force_16bpp_zbuffer, true); - - // if still D3DFMT_UNKNOWN return false - if (pixFmt == D3DFMT_UNKNOWN) - return false; - } - } else { - // Windowed Mode - - D3DDISPLAYMODE dispmode; - hr = _d3d8->GetAdapterDisplayMode(device_info->cardID, &dispmode); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "GetAdapterDisplayMode(" << device_info->cardID - << ") failed" << D3DERRORSTRING(hr); - return false; - } - pixFmt = dispmode.Format; - } - - _wcontext._display_mode.Width = dwRenderWidth; - _wcontext._display_mode.Height = dwRenderHeight; - _wcontext._display_mode.Format = pixFmt; - _wcontext._display_mode.RefreshRate = D3DPRESENT_RATE_DEFAULT; - _wcontext._monitor = device_info->_monitor; - - if (dwRenderWidth != properties.get_x_size() || - dwRenderHeight != properties.get_y_size()) { - // This is probably not the best place to put this; I'm just - // putting it here for now because the code above might have - // changed the size of the window unexpectedly. This code gets - // called when make_gsg() is called, which means it is called in - // the draw thread, but this method should really be called from - // the window thread. In DirectX those may always be the same - // threads anyway, so we may be all right. Still, it's a little - // strange that the window may change size after it has already - // been opened, at the time we create the GSG for it; it would be - // better if we could find a way to do this resolution-selection - // logic earlier, say at the time the window is created. - system_changed_size(dwRenderWidth, dwRenderHeight); - WindowProperties resized_props; - resized_props.set_size(dwRenderWidth, dwRenderHeight); - _properties.add_properties(resized_props); - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::reset_device_resize_window -// Access: Private -// Description: Called after a window (either fullscreen or windowed) -// has been resized, this recreates the D3D structures -// to match the new size. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -reset_device_resize_window(UINT new_xsize, UINT new_ysize) { - nassertr((new_xsize > 0) && (new_ysize > 0), false); - bool retval = true; - - DXScreenData *screen = NULL; - D3DPRESENT_PARAMETERS d3dpp; - memcpy(&d3dpp, &_wcontext._presentation_params, sizeof(D3DPRESENT_PARAMETERS)); - _wcontext._presentation_params.BackBufferWidth = new_xsize; - _wcontext._presentation_params.BackBufferHeight = new_ysize; - make_current(); - HRESULT hr = _dxgsg->reset_d3d_device(&_wcontext._presentation_params, &screen); - - if (FAILED(hr)) { - retval = false; - wdxdisplay8_cat.error() - << "reset_device_resize_window Reset() failed" << D3DERRORSTRING(hr); - if (hr == D3DERR_OUTOFVIDEOMEMORY) { - memcpy(&_wcontext._presentation_params, &d3dpp, sizeof(D3DPRESENT_PARAMETERS)); - hr = _dxgsg->reset_d3d_device(&_wcontext._presentation_params, &screen); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "reset_device_resize_window Reset() failed OutOfVidmem, then failed again doing Reset w/original params:" << D3DERRORSTRING(hr); - throw_event("panda3d-render-error"); - return false; - - } else { - if (wdxdisplay8_cat.is_info()) { - wdxdisplay8_cat.info() - << "reset of original size (" << _wcontext._presentation_params.BackBufferWidth - << ", " << _wcontext._presentation_params.BackBufferHeight << ") succeeded\n"; - } - } - } else { - wdxdisplay8_cat.fatal() - << "Can't reset device, bailing out.\n"; - throw_event("panda3d-render-error"); - return false; - } - } - // before you init_resized_window you need to copy certain changes to _wcontext - if (screen) { - _wcontext._swap_chain = screen->_swap_chain; - } - wdxdisplay8_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n"; - _gsg->mark_new(); - init_resized_window(); - return retval; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::init_resized_window -// Access: Private -// Description: Reinitializes the window after it has been resized, -// or after it is first created. -// -// Assumes CreateDevice or Device->Reset() has just been -// called, and the new size is specified in -// _wcontext._presentation_params. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -init_resized_window() { - HRESULT hr; - - DWORD newWidth = _wcontext._presentation_params.BackBufferWidth; - DWORD newHeight = _wcontext._presentation_params.BackBufferHeight; - - nassertv((newWidth != 0) && (newHeight != 0)); - nassertv(_wcontext._window != NULL); - - if (_wcontext._presentation_params.Windowed) { - POINT ul, lr; - RECT client_rect; - - // need to figure out x, y origin offset of window client area on screen - // (we already know the client area size) - - GetClientRect(_wcontext._window, &client_rect); - ul.x = client_rect.left; - ul.y = client_rect.top; - lr.x = client_rect.right; - lr.y = client_rect.bottom; - ClientToScreen(_wcontext._window, &ul); - ClientToScreen(_wcontext._window, &lr); - client_rect.left = ul.x; - client_rect.top = ul.y; - client_rect.right = lr.x; - client_rect.bottom = lr.y; - } - - // clear window to black ASAP - nassertv(_wcontext._window != NULL); - ClearToBlack(_wcontext._window, get_properties()); - - // clear textures and VB's out of video&AGP mem, so cache is reset - hr = _wcontext._d3d_device->ResourceManagerDiscardBytes(0); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "ResourceManagerDiscardBytes failed for device #" - << _wcontext._card_id << D3DERRORSTRING(hr); - } - - make_current(); -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::D3DFMT_to_DepthBits -// Access: Private, Static -// Description: Returns the number of depth bits represented by the -// indicated D3DFORMAT value. -//////////////////////////////////////////////////////////////////// -int wdxGraphicsWindow8:: -D3DFMT_to_DepthBits(D3DFORMAT fmt) { - switch(fmt) { - case D3DFMT_D16: - return 16; - - case D3DFMT_D24X8: - case D3DFMT_D24X4S4: - case D3DFMT_D24S8: - return 24; - - case D3DFMT_D32: - return 32; - - case D3DFMT_D15S1: - return 15; - - default: - wdxdisplay8_cat.debug() - << "D3DFMT_DepthBits: unhandled D3DFMT!\n"; - return 0; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::is_badvidmem_card -// Access: Private, Static -// Description: Returns true if the indicated video adapter card is -// known to report an inaccurate figure for available -// video memory. -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID) { - // don't trust Intel cards since they often use regular memory as vidmem - if (pDevID->VendorId == 0x00008086) { - return true; - } - - return false; -} diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.h b/panda/src/dxgsg8/wdxGraphicsWindow8.h deleted file mode 100644 index a9d080dd61..0000000000 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.h +++ /dev/null @@ -1,108 +0,0 @@ -// Filename: wdxGraphicsWindow8.h -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef WDXGRAPHICSWINDOW8_H -#define WDXGRAPHICSWINDOW8_H - -#include "pandabase.h" -#include "winGraphicsWindow.h" -#include "dxGraphicsStateGuardian8.h" -#include "dxInput8.h" -#include "wdxGraphicsPipe8.h" - -class wdxGraphicsPipe8; - -//////////////////////////////////////////////////////////////////// -// Class : wdxGraphicsWindow8 -// Description : A single graphics window for rendering DirectX under -// Microsoft Windows. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX wdxGraphicsWindow8 : public WinGraphicsWindow { -public: - wdxGraphicsWindow8(GraphicsEngine *engine, GraphicsPipe *pipe, - const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsStateGuardian *gsg, - GraphicsOutput *host); - virtual ~wdxGraphicsWindow8(); - - virtual bool begin_frame(FrameMode mode, Thread *current_thread); - virtual void end_frame(FrameMode mode, Thread *current_thread); - virtual void end_flip(); - - virtual int verify_window_sizes(int numsizes, int *dimen); - -protected: - virtual void close_window(); - virtual bool open_window(); - virtual void reset_window(bool swapchain); - - virtual void fullscreen_restored(WindowProperties &properties); - virtual void handle_reshape(); - virtual bool do_fullscreen_resize(int x_size, int y_size); - -private: - struct DXDeviceInfo { - UINT cardID; - char szDriver[MAX_DEVICE_IDENTIFIER_STRING]; - char szDescription[MAX_DEVICE_IDENTIFIER_STRING]; - GUID guidDeviceIdentifier; - DWORD VendorID, DeviceID; - HMONITOR _monitor; - }; - typedef pvector DXDeviceInfoVec; - - bool create_screen_buffers_and_device(DXScreenData &display, - bool force_16bpp_zbuffer); - - bool choose_device(); - bool search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info); - - bool reset_device_resize_window(UINT new_xsize, UINT new_ysize); - void init_resized_window(); - void make_current(); - static int D3DFMT_to_DepthBits(D3DFORMAT fmt); - static bool is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID); - - DXGraphicsStateGuardian8 *_dxgsg; - DXScreenData _wcontext; - - int _depth_buffer_bpp; - bool _awaiting_restore; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - WinGraphicsWindow::init_type(); - register_type(_type_handle, "wdxGraphicsWindow8", - WinGraphicsWindow::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; - friend class wdxGraphicsPipe8; -}; - - -#include "wdxGraphicsWindow8.I" - -#endif diff --git a/panda/src/framework/Sources.pp b/panda/src/framework/Sources.pp index d19d1fd3d5..ff9614ddd1 100644 --- a/panda/src/framework/Sources.pp +++ b/panda/src/framework/Sources.pp @@ -15,8 +15,6 @@ #define LOCAL_LIBS pandagl $[LOCAL_LIBS] #elif $[HAVE_DX9] #define LOCAL_LIBS pandadx9 $[LOCAL_LIBS] - #elif $[HAVE_DX8] - #define LOCAL_LIBS pandadx8 $[LOCAL_LIBS] #elif $[HAVE_TINYDISPLAY] #define LOCAL_LIBS p3tinydisplay $[LOCAL_LIBS] #endif diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index 9225931e8b..fc064a664e 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -37,7 +37,7 @@ LoaderOptions PandaFramework::_loader_options; //////////////////////////////////////////////////////////////////// // Function: PandaFramework::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// PandaFramework:: PandaFramework() : @@ -63,7 +63,7 @@ PandaFramework() : //////////////////////////////////////////////////////////////////// // Function: PandaFramework::Destructor // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// PandaFramework:: ~PandaFramework() { @@ -98,9 +98,6 @@ open_framework(int &argc, char **&argv) { #elif defined(HAVE_DX9) extern EXPCL_PANDADX9 void init_libpandadx9(); init_libpandadx9(); - #elif defined(HAVE_DX8) - extern EXPCL_PANDADX8 void init_libpandadx8(); - init_libpandadx8(); #elif defined(HAVE_TINYDISPLAY) extern EXPCL_TINYDISPLAY void init_libtinydisplay(); init_libtinydisplay(); @@ -158,7 +155,7 @@ open_framework(int &argc, char **&argv) { PT(GenericAsyncTask) task = new GenericAsyncTask("play_frame", task_play_frame, this); task->set_sort(55); _task_mgr.add(task); - + } else if (!record_session.empty()) { // If the config file so indicates, create a recorder and start it // recording. @@ -168,7 +165,7 @@ open_framework(int &argc, char **&argv) { PT(GenericAsyncTask) task = new GenericAsyncTask("record_frame", task_record_frame, this); task->set_sort(45); _task_mgr.add(task); - } + } _event_handler.add_hook("window-event", event_window_event, this); } @@ -263,7 +260,7 @@ get_mouse(GraphicsOutput *window) { GraphicsWindow *win = DCAST(GraphicsWindow, window); MouseAndKeyboard *mouse_node = new MouseAndKeyboard(win, 0, "mouse"); mouse = data_root.attach_new_node(mouse_node); - + RecorderController *recorder = get_recorder(); if (recorder != (RecorderController *)NULL) { // If we're in recording or playback mode, associate a recorder. @@ -272,7 +269,7 @@ get_mouse(GraphicsOutput *window) { recorder->add_recorder("mouse", mouse_recorder); } } - + _mouses[window] = mouse; return mouse; @@ -415,7 +412,7 @@ open_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) { if (window_type == "offscreen") { flags = GraphicsPipe::BF_refuse_window; } - + return open_window(props, flags, pipe, gsg); } @@ -449,7 +446,7 @@ open_window(const WindowProperties &props, int flags, wf->set_perpixel(get_perpixel()); wf->set_background_type(get_background_type()); - GraphicsOutput *win = wf->open_window(props, flags, get_graphics_engine(), + GraphicsOutput *win = wf->open_window(props, flags, get_graphics_engine(), pipe, gsg); _engine->open_windows(); if (win != (GraphicsOutput *)NULL && !win->is_valid()) { @@ -523,7 +520,7 @@ close_window(int n) { if (win != (GraphicsOutput *)NULL) { _engine->remove_window(win); } - + wf->close_window(); _windows.erase(_windows.begin() + n); } @@ -544,7 +541,7 @@ close_all_windows() { if (win != (GraphicsOutput *)NULL) { _engine->remove_window(win); } - + wf->close_window(); } @@ -602,7 +599,7 @@ void PandaFramework:: report_frame_rate(ostream &out) const { double now = ClockObject::get_global_clock()->get_frame_time(); double delta = now - _start_time; - + int frame_count = ClockObject::get_global_clock()->get_frame_count(); int num_frames = frame_count - _frame_count; if (num_frames > 0) { @@ -959,7 +956,7 @@ clear_text() { // window). //////////////////////////////////////////////////////////////////// void PandaFramework:: -event_esc(const Event *event, void *data) { +event_esc(const Event *event, void *data) { if (event->get_num_parameters() == 1) { EventParameter param = event->get_parameter(0); WindowFramework *wf; @@ -1227,7 +1224,7 @@ event_A(const Event *, void *data) { void PandaFramework:: event_h(const Event *, void *data) { PandaFramework *self = (PandaFramework *)data; - + if (self->has_highlight()) { self->clear_highlight(); } else { @@ -1290,7 +1287,7 @@ event_arrow_left(const Event *, void *data) { nassertv(index >= 0); int sibling = index - 1; - if (sibling >= 0 && + if (sibling >= 0 && parent.node()->get_child(sibling) == self->_highlight_wireframe.node()) { // Skip over the special highlight node. sibling--; @@ -1323,12 +1320,12 @@ event_arrow_right(const Event *, void *data) { int num_children = parent.node()->get_num_children(); int sibling = index + 1; - if (sibling < num_children && + if (sibling < num_children && parent.node()->get_child(sibling) == self->_highlight_wireframe.node()) { // Skip over the special highlight node. sibling++; } - + if (sibling < num_children) { self->set_highlight(NodePath(parent, parent.node()->get_child(sibling))); } @@ -1416,11 +1413,11 @@ event_comma(const Event *event, void *) { case WindowFramework::BT_other: case WindowFramework::BT_none: break; - + case WindowFramework::BT_white: wf->set_background_type(WindowFramework::BT_default); break; - + default: wf->set_background_type((WindowFramework::BackgroundType)(wf->get_background_type() + 1)); } @@ -1450,8 +1447,8 @@ event_question(const Event *event, void *data) { // Build up a string to display. ostringstream help; KeyDefinitions::const_iterator ki; - for (ki = self->_key_definitions.begin(); - ki != self->_key_definitions.end(); + for (ki = self->_key_definitions.begin(); + ki != self->_key_definitions.end(); ++ki) { const KeyDefinition &keydef = (*ki); help << keydef._event_name << "\t" << keydef._description << "\n"; @@ -1513,7 +1510,7 @@ event_window_event(const Event *event, void *data) { self->close_window(window_index); window_index = self->find_window(win); } - + // Free up the mouse for that window. self->remove_mouse(win); diff --git a/panda/src/windisplay/Sources.pp b/panda/src/windisplay/Sources.pp index 2496806250..cd450ca1b9 100644 --- a/panda/src/windisplay/Sources.pp +++ b/panda/src/windisplay/Sources.pp @@ -6,14 +6,14 @@ #define BUILDING_DLL BUILDING_PANDAWIN -#define USE_PACKAGES dx8 dx9 +#define USE_PACKAGES dx9 #begin lib_target #define TARGET p3windisplay #define LOCAL_LIBS \ p3display p3putil - #define COMBINED_SOURCES $[TARGET]_composite1.cxx winDetectDx9.cxx winDetectDx8.cxx + #define COMBINED_SOURCES $[TARGET]_composite1.cxx winDetectDx9.cxx #define SOURCES \ config_windisplay.h \ @@ -30,7 +30,7 @@ #define INCLUDED_SOURCES \ config_windisplay.cxx winGraphicsPipe.cxx \ winGraphicsWindow.cxx \ - winDetectDx9.cxx winDetectDx8.cxx + winDetectDx9.cxx #define WIN_SYS_LIBS Imm32.lib winmm.lib kernel32.lib oldnames.lib user32.lib gdi32.lib diff --git a/panda/src/windisplay/winDetectDx.h b/panda/src/windisplay/winDetectDx.h index 58827aa570..f04d468090 100644 --- a/panda/src/windisplay/winDetectDx.h +++ b/panda/src/windisplay/winDetectDx.h @@ -38,10 +38,7 @@ static DISPLAY_FORMAT display_format_array [ ] = { D3DFMT_R5G6B5, 16, FALSE, D3DFMT_X1R5G5B5, 16, FALSE, -#if DX8 -#else D3DFMT_A2R10G10B10, 32, TRUE, -#endif // terminator D3DFMT_UNKNOWN, 0, FALSE, @@ -226,7 +223,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para get_adapter_display_mode_state = true; } else { - get_adapter_display_mode_state = false; + get_adapter_display_mode_state = false; } flags = 0; @@ -234,10 +231,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para // print adapter info d3d_adapter_identifier.Driver; d3d_adapter_identifier.Description; - #if DX8 - #else d3d_adapter_identifier.DeviceName; - #endif d3d_adapter_identifier.DriverVersion; d3d_adapter_identifier.VendorId; d3d_adapter_identifier.DeviceId; @@ -245,12 +239,12 @@ static int get_display_information (DisplaySearchParameters &display_search_para d3d_adapter_identifier.Revision; d3d_adapter_identifier.DeviceIdentifier; d3d_adapter_identifier.WHQLLevel; - + if (debug) { printf ("Driver: %s\n", d3d_adapter_identifier.Driver); printf ("Description: %s\n", d3d_adapter_identifier.Description); } - + char system_directory [MAX_PATH]; char dll_file_path [MAX_PATH]; @@ -338,9 +332,6 @@ static int get_display_information (DisplaySearchParameters &display_search_para if (direct_3d -> GetDeviceCaps (adapter, device_type, &d3d_caps) == D3D_OK) { -#if DX8 - // shaders not supported in DX8 -#else int vertex_shader_version_major; int vertex_shader_version_minor; int pixel_shader_version_major; @@ -374,7 +365,6 @@ static int get_display_information (DisplaySearchParameters &display_search_para shader_model = GraphicsStateGuardian::SM_40; break; } -#endif if (debug) { printf ("shader_model = %d \n", shader_model); @@ -394,35 +384,26 @@ static int get_display_information (DisplaySearchParameters &display_search_para format_index = 0; maximum_display_modes = 0; - while (display_format_array [format_index].d3d_format != D3DFMT_UNKNOWN) { + while (display_format_array [format_index].d3d_format != D3DFMT_UNKNOWN) { d3d_format = display_format_array [format_index].d3d_format; -#if DX8 - display_mode_count = direct_3d -> GetAdapterModeCount (adapter); -#else display_mode_count = direct_3d -> GetAdapterModeCount (adapter, d3d_format); -#endif if (display_mode_count > 0) { UINT mode_index; D3DDISPLAYMODE d3d_display_mode; for (mode_index = 0; mode_index < display_mode_count; mode_index++) { -#if DX8 - if (direct_3d -> EnumAdapterModes (adapter, mode_index, &d3d_display_mode) == D3D_OK) -#else - if (direct_3d -> EnumAdapterModes (adapter, d3d_format, mode_index, &d3d_display_mode) == D3D_OK) -#endif - { + if (direct_3d -> EnumAdapterModes (adapter, d3d_format, mode_index, &d3d_display_mode) == D3D_OK) { if (d3d_display_mode.Width >= minimum_width && d3d_display_mode.Height >= minimum_height && - d3d_display_mode.Width <= maximum_width && d3d_display_mode.Height <= maximum_height) { + d3d_display_mode.Width <= maximum_width && d3d_display_mode.Height <= maximum_height) { if (display_format_array [format_index].bits_per_pixel >= minimum_bits_per_pixel && - display_format_array [format_index].bits_per_pixel <= maximum_bits_per_pixel) { + display_format_array [format_index].bits_per_pixel <= maximum_bits_per_pixel) { if (d3d_format == d3d_display_mode.Format) { - maximum_display_modes++; + maximum_display_modes++; } } } - } + } } } @@ -436,26 +417,17 @@ static int get_display_information (DisplaySearchParameters &display_search_para display_mode_array = new DisplayMode [maximum_display_modes]; format_index = 0; - while (display_format_array [format_index].d3d_format != D3DFMT_UNKNOWN) { + while (display_format_array [format_index].d3d_format != D3DFMT_UNKNOWN) { d3d_format = display_format_array [format_index].d3d_format; -#if DX8 - display_mode_count = direct_3d -> GetAdapterModeCount (adapter); -#else display_mode_count = direct_3d -> GetAdapterModeCount (adapter, d3d_format); -#endif if (display_mode_count > 0) { UINT mode_index; D3DDISPLAYMODE d3d_display_mode; for (mode_index = 0; mode_index < display_mode_count; mode_index++) { -#if DX8 - if (direct_3d -> EnumAdapterModes (adapter, mode_index, &d3d_display_mode) == D3D_OK) -#else - if (direct_3d -> EnumAdapterModes (adapter, d3d_format, mode_index, &d3d_display_mode) == D3D_OK) -#endif - { + if (direct_3d -> EnumAdapterModes (adapter, d3d_format, mode_index, &d3d_display_mode) == D3D_OK) { if (d3d_display_mode.Width >= minimum_width && d3d_display_mode.Height >= minimum_height && - d3d_display_mode.Width <= maximum_width && d3d_display_mode.Height <= maximum_height) { + d3d_display_mode.Width <= maximum_width && d3d_display_mode.Height <= maximum_height) { if (display_format_array [format_index].bits_per_pixel >= minimum_bits_per_pixel && display_format_array [format_index].bits_per_pixel <= maximum_bits_per_pixel) { if (debug) { @@ -515,7 +487,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para direct_3d_device = 0; memset (&present_parameters, 0, sizeof (D3DPRESENT_PARAMETERS)); - present_parameters.BackBufferWidth = width; + present_parameters.BackBufferWidth = width; present_parameters.BackBufferHeight = height; present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8; present_parameters.BackBufferCount = 1; @@ -528,11 +500,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8; present_parameters.FullScreen_RefreshRateInHz; - -#if DX8 -#else present_parameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; -#endif if (d3d_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING; @@ -546,32 +514,18 @@ static int get_display_information (DisplaySearchParameters &display_search_para HRESULT result; result = direct_3d -> CreateDevice (adapter, device_type, window_handle, behavior_flags, &present_parameters, &direct_3d_device); - if (result == D3D_OK) { + if (result == D3D_OK) { - // allocate 512x512 32-bit textures (1MB size) until we run out or hit the limit + // allocate 512x512 32-bit textures (1MB size) until we run out or hit the limit #define MAXIMUM_TEXTURES (2048 - 1) - + int total_textures; - HRESULT texture_result; - #if DX8 - IDirect3DTexture8 *texture_array [MAXIMUM_TEXTURES]; - #else + HRESULT texture_result; IDirect3DTexture9 *texture_array [MAXIMUM_TEXTURES]; - #endif - + total_textures = 0; while (total_textures < MAXIMUM_TEXTURES) { - #if DX8 - texture_result = direct_3d_device -> CreateTexture ( - 512, - 512, - 1, - D3DUSAGE_RENDERTARGET, - D3DFMT_A8R8G8B8, - D3DPOOL_DEFAULT, - &texture_array [total_textures]); - #else texture_result = direct_3d_device -> CreateTexture ( 512, 512, @@ -581,28 +535,27 @@ static int get_display_information (DisplaySearchParameters &display_search_para D3DPOOL_DEFAULT, &texture_array [total_textures], NULL); - #endif - if (texture_result == D3D_OK) { + if (texture_result == D3D_OK) { total_textures++; } else { if (texture_result == D3DERR_OUTOFVIDEOMEMORY) { if (debug) { printf ("D3DERR_OUTOFVIDEOMEMORY \n"); - } - } + } + } break; - } + } } // free all allocated textures - int index; + int index; for (index = 0; index < total_textures; index++) { - texture_array [index] -> Release ( ); + texture_array [index] -> Release ( ); } video_memory = (total_textures * 1024 * 1024); - + if (debug) { printf ("video_memory = %d \n", video_memory); } @@ -612,9 +565,9 @@ static int get_display_information (DisplaySearchParameters &display_search_para printf ("texture_memory = %d \n", texture_memory); } - direct_3d_device -> Release ( ); + direct_3d_device -> Release ( ); - state = DisplayInformation::DS_success; + state = DisplayInformation::DS_success; success = true; } else @@ -623,7 +576,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para printf ("CreateDevice failed.\n"); } - state = DisplayInformation::DS_create_device_error; + state = DisplayInformation::DS_create_device_error; success = true; } @@ -641,7 +594,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para } } else { - state = DisplayInformation::DS_direct_3d_create_error; + state = DisplayInformation::DS_direct_3d_create_error; } FreeLibrary (d3d_dll); diff --git a/panda/src/windisplay/winDetectDx8.cxx b/panda/src/windisplay/winDetectDx8.cxx deleted file mode 100644 index ceca2e7840..0000000000 --- a/panda/src/windisplay/winDetectDx8.cxx +++ /dev/null @@ -1,48 +0,0 @@ -// Filename: winDetectDx8.cxx -// Created by: aignacio (18Jan07) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "pandabase.h" - -#ifdef HAVE_DX8 - -#define WIN32_LEAN_AND_MEAN -#include -#include "graphicsStateGuardian.h" -#include "graphicsPipe.h" -#include "displaySearchParameters.h" - - -#define DX8 1 -#define Direct3DCreate Direct3DCreate8 - -typedef LPDIRECT3D8 (WINAPI *DIRECT3DCREATE8)(UINT SDKVersion); -typedef LPDIRECT3D8 DIRECT_3D; -typedef D3DCAPS8 D3DCAPS; -typedef D3DADAPTER_IDENTIFIER8 D3DADAPTER_IDENTIFIER; -typedef LPDIRECT3DDEVICE8 DIRECT_3D_DEVICE; -typedef DIRECT3DCREATE8 DIRECT_3D_CREATE; - -static char *d3d_dll_name = "d3d8.dll"; -static char *direct_3d_create_function_name = "Direct3DCreate8"; - - -// include common source code -#include "winDetectDx.h" - - -int dx8_display_information (DisplaySearchParameters &display_search_parameters, DisplayInformation *display_information) { - return get_display_information (display_search_parameters, display_information); -} - -#endif diff --git a/panda/src/windisplay/winDetectDx9.cxx b/panda/src/windisplay/winDetectDx9.cxx index c1556ee289..3689451cce 100644 --- a/panda/src/windisplay/winDetectDx9.cxx +++ b/panda/src/windisplay/winDetectDx9.cxx @@ -22,7 +22,6 @@ #include "graphicsPipe.h" #include "displaySearchParameters.h" -#define DX8 0 #define Direct3DCreate Direct3DCreate9 typedef LPDIRECT3D9 (WINAPI *DIRECT3DCREATE9)(UINT SDKVersion); diff --git a/panda/src/windisplay/winGraphicsPipe.cxx b/panda/src/windisplay/winGraphicsPipe.cxx index 46864162f7..90a17ab557 100644 --- a/panda/src/windisplay/winGraphicsPipe.cxx +++ b/panda/src/windisplay/winGraphicsPipe.cxx @@ -758,7 +758,7 @@ count_number_of_cpus(DisplayInformation *display_information) { if (buffer != NULL) { PANDA_FREE_ARRAY(buffer); } - + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)PANDA_MALLOC_ARRAY(buffer_length); nassertv(buffer != NULL); } else { @@ -777,7 +777,7 @@ count_number_of_cpus(DisplayInformation *display_information) { while (ptr < end) { if (ptr->Relationship == RelationProcessorCore) { num_cpu_cores++; - + // A hyperthreaded core supplies more than one logical processor. num_logical_cpus += count_bits_in_word((PN_uint64)(ptr->ProcessorMask)); } @@ -798,14 +798,14 @@ count_number_of_cpus(DisplayInformation *display_information) { //////////////////////////////////////////////////////////////////// // Function: WinGraphicsPipe::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// WinGraphicsPipe:: WinGraphicsPipe() { bool state; char string [512]; - + state = false; _supported_types = OT_window | OT_fullscreen_window; @@ -815,7 +815,7 @@ WinGraphicsPipe() { _hUser32 = (HINSTANCE)LoadLibrary("user32.dll"); if (_hUser32 != NULL) { - _pfnTrackMouseEvent = + _pfnTrackMouseEvent = (PFN_TRACKMOUSEEVENT)GetProcAddress(_hUser32, "TrackMouseEvent"); } @@ -830,17 +830,6 @@ WinGraphicsPipe() { } #endif -#ifdef HAVE_DX8 - if (request_dxdisplay_information){ - DisplaySearchParameters display_search_parameters_dx8; - int dx8_display_information (DisplaySearchParameters &display_search_parameters_dx8, DisplayInformation *display_information); - - if (state == false && dx8_display_information (display_search_parameters_dx8, _display_information)) { - state = true; - } - } -#endif - if (auto_cpu_data) { lookup_cpu_data(); } @@ -852,32 +841,32 @@ WinGraphicsPipe() { sprintf (string, "OS version: %d.%d.%d.%d \n", version_info.dwMajorVersion, version_info.dwMinorVersion, version_info.dwPlatformId, version_info.dwBuildNumber); windisplay_cat.info() << string; windisplay_cat.info() << " " << version_info.szCSDVersion << "\n"; - + _display_information -> _os_version_major = version_info.dwMajorVersion; _display_information -> _os_version_minor = version_info.dwMinorVersion; - _display_information -> _os_version_build = version_info.dwBuildNumber; + _display_information -> _os_version_build = version_info.dwBuildNumber; _display_information -> _os_platform_id = version_info.dwPlatformId; } // Screen size _display_width = GetSystemMetrics(SM_CXSCREEN); _display_height = GetSystemMetrics(SM_CYSCREEN); - + HMODULE power_dll; power_dll = LoadLibrary ("PowrProf.dll"); - if (power_dll) { + if (power_dll) { CallNtPowerInformationFunction = (CallNtPowerInformationType) GetProcAddress (power_dll, "CallNtPowerInformation"); - if (CallNtPowerInformationFunction) { - + if (CallNtPowerInformationFunction) { + _display_information -> _update_cpu_frequency_function = update_cpu_frequency_function; update_cpu_frequency_function(0, _display_information); - sprintf (string, "max Mhz %I64d, current Mhz %I64d \n", _display_information -> _maximum_cpu_frequency, _display_information -> _current_cpu_frequency); + sprintf (string, "max Mhz %I64d, current Mhz %I64d \n", _display_information -> _maximum_cpu_frequency, _display_information -> _current_cpu_frequency); - windisplay_cat.info() << string; + windisplay_cat.info() << string; } } - + if (state) { } diff --git a/pandatool/src/scripts/builder.cshrc b/pandatool/src/scripts/builder.cshrc index 06f29f9918..e79489ad78 100644 --- a/pandatool/src/scripts/builder.cshrc +++ b/pandatool/src/scripts/builder.cshrc @@ -38,7 +38,6 @@ alias setbrowseinfo1 setenv CL_MAKE_BROWSE_INFO 1 alias setbrowseinfo0 setenv CL_MAKE_BROWSE_INFO 0 setenv HAVE_GL yes -setenv HAVE_DX8 yes setenv HAVE_DX9 yes setenv USE_NSPR t From 9c3553b3fc8bf1dbe0a0d09dac5913ec0d693431 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 30 Dec 2014 11:39:40 +0100 Subject: [PATCH 06/83] Add r8i, rg8i, rgb8i, rgba8i to switches it's missing from --- panda/src/gobj/texture.cxx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index b67fb9eae8..53f32dd336 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1713,6 +1713,19 @@ write(ostream &out, int indent_level) const { case F_rgb32: out << "rgb32"; break; + + case F_r8i: + out << "r8i"; + break; + case F_rg8i: + out << "rg8i"; + break; + case F_rgb8i: + out << "rgb8i"; + break; + case F_rgba8i: + out << "rgba8i"; + break; } if (cdata->_compression != CM_default) { @@ -2110,6 +2123,14 @@ format_format(Format format) { return "rg32"; case F_rgb32: return "rgb32"; + case F_r8i: + return "r8i"; + case F_rg8i: + return "rg8i"; + case F_rgb8i: + return "rgb8i"; + case F_rgba8i: + return "rgba8i"; } return "**invalid**"; } @@ -5121,6 +5142,7 @@ do_set_format(CData *cdata, Texture::Format format) { case F_sluminance: case F_r32i: case F_r32: + case F_r8i: cdata->_num_components = 1; break; @@ -5129,6 +5151,7 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rg16: case F_sluminance_alpha: case F_rg32: + case F_rg8i: cdata->_num_components = 2; break; @@ -5140,6 +5163,7 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rgb16: case F_srgb: case F_rgb32: + case F_rgb8i: cdata->_num_components = 3; break; @@ -5152,6 +5176,7 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rgba16: case F_rgba32: case F_srgb_alpha: + case F_rgba8i: cdata->_num_components = 4; break; } From 202008c4703f984cd4119310290bbaef97ef85be Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 2 Jan 2015 14:55:06 +0100 Subject: [PATCH 07/83] Support digraphs and alternate operator names in CPPParser --- dtool/src/cppparser/cppPreprocessor.cxx | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 474063e4a7..0911921510 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -824,6 +824,8 @@ internal_get_next_token() { } if (next_c == '<') return CPPToken(LSHIFT, first_line, first_col, first_file); if (next_c == '=') return CPPToken(LECOMPARE, first_line, first_col, first_file); + if (next_c == ':') return CPPToken('[', first_line, first_col, first_file); + if (next_c == '%') return CPPToken('{', first_line, first_col, first_file); break; case '>': @@ -867,6 +869,7 @@ internal_get_next_token() { case ':': if (next_c == ':') return CPPToken(SCOPE, first_line, first_col, first_file); + if (next_c == '>') return CPPToken(']', first_line, first_col, first_file); break; case '*': @@ -879,6 +882,7 @@ internal_get_next_token() { case '%': if (next_c == '=') return CPPToken(MODEQUAL, first_line, first_col, first_file); + if (next_c == '>') return CPPToken('}', first_line, first_col, first_file); break; } @@ -1411,7 +1415,7 @@ handle_include_directive(const string &args, int first_line, found_file = true; source = CPPFile::S_local; } - + // Search the same directory as the includer. if (!angle_quotes && !found_file) { Filename match(get_file()._filename.get_dirname(), filename); @@ -1439,7 +1443,7 @@ handle_include_directive(const string &args, int first_line, } } } - + if (!found_file) { warning("Cannot find " + filename.get_fullpath(), first_line, first_col, first_file); @@ -2058,6 +2062,19 @@ check_keyword(const string &name) { if (name == "volatile") return KW_VOLATILE; if (name == "while") return KW_WHILE; + // These are alternative ways to refer to built-in operators. + if (name == "and") return ANDAND; + if (name == "and_eq") return ANDEQUAL; + if (name == "bitand") return '&'; + if (name == "bitor") return '|'; + if (name == "compl") return '~'; + if (name == "not") return '!'; + if (name == "not_eq") return NECOMPARE; + if (name == "or") return OROR; + if (name == "or_eq") return OREQUAL; + if (name == "xor") return '^'; + if (name == "xor_eq") return XOREQUAL; + if (!cpp_longlong_keyword.empty() && name == cpp_longlong_keyword) { return KW_LONGLONG; } From 368e1ca644c999336975ada6d1ab3af40c13f757 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 2 Jan 2015 14:57:33 +0100 Subject: [PATCH 08/83] Support noexcept and rvalue references in C++ parser --- dtool/src/cppparser/cppBison.yxx | 111 +++++++++++------- dtool/src/cppparser/cppFunctionType.cxx | 3 + dtool/src/cppparser/cppFunctionType.h | 1 + dtool/src/cppparser/cppInstanceIdentifier.cxx | 10 +- dtool/src/cppparser/cppInstanceIdentifier.h | 1 + dtool/src/cppparser/cppPreprocessor.cxx | 1 + dtool/src/cppparser/cppReferenceType.cxx | 22 +++- dtool/src/cppparser/cppReferenceType.h | 13 +- 8 files changed, 110 insertions(+), 52 deletions(-) diff --git a/dtool/src/cppparser/cppBison.yxx b/dtool/src/cppparser/cppBison.yxx index 238c4f578b..80d78fe184 100644 --- a/dtool/src/cppparser/cppBison.yxx +++ b/dtool/src/cppparser/cppBison.yxx @@ -1,6 +1,6 @@ // Filename: cppBison.y // Created by: drose (16Jan99) -// +// //////////////////////////////////////////////////////////////////// %{ @@ -38,7 +38,7 @@ CPPScope *current_scope = NULL; CPPScope *global_scope = NULL; CPPPreprocessor *current_lexer = NULL; -static CPPStructType *current_struct = NULL; +static CPPStructType *current_struct = NULL; static CPPEnumType *current_enum = NULL; static int current_storage_class = 0; static CPPType *current_type = NULL; @@ -98,7 +98,7 @@ parse_cpp(CPPParser *cp) { current_scope = old_scope; global_scope = old_global_scope; current_lexer = old_lexer; - + } CPPExpression * @@ -140,7 +140,7 @@ parse_type(CPPPreprocessor *pp, CPPScope *new_current_scope, yyparse(); CPPType *result = current_type; - + current_scope = old_scope; global_scope = old_global_scope; current_lexer = old_lexer; @@ -223,8 +223,8 @@ pop_struct() { %token UNARY_REF %token POINTSAT %token SCOPE -%token PLUSPLUS -%token MINUSMINUS +%token PLUSPLUS +%token MINUSMINUS %token TIMESEQUAL %token DIVIDEEQUAL %token MODEQUAL @@ -242,14 +242,14 @@ pop_struct() { %token KW_CATCH %token KW_CHAR %token KW_WCHAR_T -%token KW_CLASS -%token KW_CONST +%token KW_CLASS +%token KW_CONST %token KW_DELETE %token KW_DOUBLE %token KW_DYNAMIC_CAST %token KW_ELSE -%token KW_END_PUBLISH -%token KW_ENUM +%token KW_END_PUBLISH +%token KW_ENUM %token KW_EXTENSION %token KW_EXTERN %token KW_EXPLICIT @@ -269,6 +269,7 @@ pop_struct() { %token KW_MUTABLE %token KW_NAMESPACE %token KW_NEW +%token KW_NOEXCEPT %token KW_OPERATOR %token KW_PRIVATE %token KW_PROTECTED @@ -280,14 +281,14 @@ pop_struct() { %token KW_SIZEOF %token KW_STATIC %token KW_STATIC_CAST -%token KW_STRUCT +%token KW_STRUCT %token KW_TEMPLATE %token KW_THROW %token KW_TRUE %token KW_TRY -%token KW_TYPEDEF +%token KW_TYPEDEF %token KW_TYPENAME -%token KW_UNION +%token KW_UNION %token KW_UNSIGNED %token KW_USING %token KW_VIRTUAL @@ -417,7 +418,7 @@ constructor_init: extern_c: storage_class '{' { - push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | + push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | ($1 & CPPInstance::SC_c_binding)); } cpp '}' @@ -434,7 +435,7 @@ declaration: | using_declaration | friend_declaration | KW_TYPEDEF typedef_declaration - | KW_BEGIN_PUBLISH + | KW_BEGIN_PUBLISH { if (publish_nest_level != 0) { yyerror("Unclosed __begin_publish", publish_loc); @@ -447,7 +448,7 @@ declaration: publish_nest_level++; current_scope->set_current_vis(V_published); } - | KW_END_PUBLISH + | KW_END_PUBLISH { if (publish_nest_level != 1) { yyerror("Unmatched __end_publish", @1); @@ -765,7 +766,7 @@ typedef_const_instance_identifiers: function_prototype: /* Functions with implicit return types, and constructors */ - IDENTIFIER '(' + IDENTIFIER '(' { push_scope($1->get_scope(current_scope, global_scope)); } @@ -821,13 +822,13 @@ function_prototype: if ($2->is_scoped()) { yyerror("Invalid destructor name: ~" + $2->get_fully_scoped_name(), @2); } else { - CPPIdentifier *ident = + CPPIdentifier *ident = new CPPIdentifier("~" + $2->get_simple_name(), @2.file); delete $2; CPPType *type; type = new CPPSimpleType(CPPSimpleType::T_void); - + CPPInstanceIdentifier *ii = new CPPInstanceIdentifier(ident); ii->add_func_modifier($5, $7); @@ -932,7 +933,7 @@ function_prototype: avoid shift/reduce conflicts. */ | IDENTIFIER { - CPPDeclaration *decl = + CPPDeclaration *decl = $1->find_symbol(current_scope, global_scope, current_lexer); if (decl != (CPPDeclaration *)NULL) { $$ = decl->as_instance(); @@ -950,6 +951,10 @@ function_post: | KW_CONST { $$ = (int)CPPFunctionType::F_const_method; +} + | function_post KW_NOEXCEPT +{ + $$ = (int)CPPFunctionType::F_noexcept; } | function_post KW_THROW '(' ')' { @@ -1239,6 +1244,11 @@ instance_identifier: { $$ = $2; $$->add_modifier(IIT_reference); +} + | ANDAND instance_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_rvalue_reference); } | SCOPING '*' instance_identifier %prec UNARY { @@ -1436,6 +1446,11 @@ not_paren_formal_parameter_identifier: { $$ = $2; $$->add_modifier(IIT_reference); +} + | ANDAND not_paren_formal_parameter_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_rvalue_reference); } | SCOPING '*' not_paren_formal_parameter_identifier %prec UNARY { @@ -1476,6 +1491,11 @@ formal_parameter_identifier: { $$ = $2; $$->add_modifier(IIT_reference); +} + | ANDAND formal_parameter_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_rvalue_reference); } | SCOPING '*' formal_parameter_identifier %prec UNARY { @@ -1519,6 +1539,11 @@ empty_instance_identifier: { $$ = $2; $$->add_modifier(IIT_reference); +} + | ANDAND empty_instance_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_rvalue_reference); } | SCOPING '*' empty_instance_identifier %prec UNARY { @@ -1574,7 +1599,7 @@ type: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1590,7 +1615,7 @@ type: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1638,7 +1663,7 @@ type_decl: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1654,7 +1679,7 @@ type_decl: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1686,7 +1711,7 @@ predefined_type: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1702,7 +1727,7 @@ predefined_type: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1733,9 +1758,9 @@ full_type: anonymous_struct: struct_keyword '{' { - CPPVisibility starting_vis = + CPPVisibility starting_vis = ($1 == CPPExtensionType::T_class) ? V_private : V_public; - + CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("anon"), starting_vis); CPPStructType *st = new CPPStructType($1, NULL, current_scope, @@ -1757,7 +1782,7 @@ anonymous_struct: named_struct: struct_keyword name { - CPPVisibility starting_vis = + CPPVisibility starting_vis = ($1 == CPPExtensionType::T_class) ? V_private : V_public; CPPScope *scope = $2->get_scope(current_scope, global_scope, current_lexer); @@ -1771,7 +1796,7 @@ named_struct: new_scope, @1.file); new_scope->set_struct_type(st); current_scope->define_extension_type(st); - + push_scope(new_scope); push_struct(st); } @@ -1916,7 +1941,7 @@ namespace_declaration: CPPScope *scope = $2->find_scope(current_scope, global_scope, current_lexer); if (scope == NULL) { // This must be a new namespace declaration. - CPPScope *parent_scope = + CPPScope *parent_scope = $2->get_scope(current_scope, global_scope, current_lexer); if (parent_scope == NULL) { parent_scope = current_scope; @@ -2104,13 +2129,13 @@ element: | ELLIPSIS | OROR | ANDAND | EQCOMPARE | NECOMPARE | LECOMPARE | GECOMPARE | LSHIFT | RSHIFT | POINTSAT_STAR | DOT_STAR | POINTSAT - | SCOPE | PLUSPLUS | MINUSMINUS + | SCOPE | PLUSPLUS | MINUSMINUS | TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL | OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL | KW_BOOL | KW_CATCH | KW_CHAR | KW_WCHAR_T | KW_CLASS | KW_CONST | KW_DELETE | KW_DOUBLE | KW_DYNAMIC_CAST | KW_ELSE | KW_ENUM | KW_EXTERN | KW_EXPLICIT | KW_FALSE - | KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO + | KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO | KW_IF | KW_INLINE | KW_INT | KW_LONG | KW_MUTABLE | KW_NEW | KW_PRIVATE | KW_PROTECTED | KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_RETURN @@ -2329,65 +2354,65 @@ const_expr: } | KW_INT '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_CHAR '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_WCHAR_T '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_BOOL '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_SHORT '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_short)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_LONG '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_long)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_UNSIGNED '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_unsigned)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_SIGNED '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_signed)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_FLOAT '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_DOUBLE '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } diff --git a/dtool/src/cppparser/cppFunctionType.cxx b/dtool/src/cppparser/cppFunctionType.cxx index 8625f7e721..515729cf39 100644 --- a/dtool/src/cppparser/cppFunctionType.cxx +++ b/dtool/src/cppparser/cppFunctionType.cxx @@ -243,6 +243,9 @@ output_instance(ostream &out, int indent_level, CPPScope *scope, if (_flags & F_const_method) { out << " const"; } + if (_flags & F_noexcept) { + out << " noexcept"; + } } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/cppparser/cppFunctionType.h b/dtool/src/cppparser/cppFunctionType.h index 021aeba5ce..b728fa7b22 100644 --- a/dtool/src/cppparser/cppFunctionType.h +++ b/dtool/src/cppparser/cppFunctionType.h @@ -36,6 +36,7 @@ public: F_method_pointer = 0x10, F_unary_op = 0x20, F_operator = 0x40, + F_noexcept = 0x80, }; CPPFunctionType(CPPType *return_type, CPPParameterList *parameters, diff --git a/dtool/src/cppparser/cppInstanceIdentifier.cxx b/dtool/src/cppparser/cppInstanceIdentifier.cxx index 8db68d389d..7cd3c67283 100644 --- a/dtool/src/cppparser/cppInstanceIdentifier.cxx +++ b/dtool/src/cppparser/cppInstanceIdentifier.cxx @@ -133,7 +133,7 @@ add_func_modifier(CPPParameterList *params, int flags) { // function, check if the parameter list is empty. If it is, this // is really a unary operator, so set the unary_op flag. Operators // () and [] are never considered unary operators. - if (_ident != NULL && + if (_ident != NULL && _ident->get_simple_name().substr(0, 9) == "operator ") { if (_ident->get_simple_name() != string("operator ()") && @@ -245,7 +245,13 @@ r_unroll_type(CPPType *start_type, break; case IIT_reference: - result = new CPPReferenceType(r_unroll_type(start_type, mi)); + result = new CPPReferenceType(r_unroll_type(start_type, mi), + CPPReferenceType::VC_lvalue); + break; + + case IIT_rvalue_reference: + result = new CPPReferenceType(r_unroll_type(start_type, mi), + CPPReferenceType::VC_rvalue); break; case IIT_scoped_pointer: diff --git a/dtool/src/cppparser/cppInstanceIdentifier.h b/dtool/src/cppparser/cppInstanceIdentifier.h index 7662292c12..b906a4f386 100644 --- a/dtool/src/cppparser/cppInstanceIdentifier.h +++ b/dtool/src/cppparser/cppInstanceIdentifier.h @@ -32,6 +32,7 @@ class CPPPreprocessor; enum CPPInstanceIdentifierType { IIT_pointer, IIT_reference, + IIT_rvalue_reference, IIT_scoped_pointer, IIT_array, IIT_const, diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 0911921510..591f856da6 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -2035,6 +2035,7 @@ check_keyword(const string &name) { if (name == "__make_seq") return KW_MAKE_SEQ; if (name == "mutable") return KW_MUTABLE; if (name == "namespace") return KW_NAMESPACE; + if (name == "noexcept") return KW_NOEXCEPT; if (name == "new") return KW_NEW; if (name == "operator") return KW_OPERATOR; if (name == "private") return KW_PRIVATE; diff --git a/dtool/src/cppparser/cppReferenceType.cxx b/dtool/src/cppparser/cppReferenceType.cxx index 7438dfe89f..40d6e987da 100644 --- a/dtool/src/cppparser/cppReferenceType.cxx +++ b/dtool/src/cppparser/cppReferenceType.cxx @@ -21,9 +21,10 @@ // Description: //////////////////////////////////////////////////////////////////// CPPReferenceType:: -CPPReferenceType(CPPType *pointing_at) : +CPPReferenceType(CPPType *pointing_at, ValueCategory vcat) : CPPType(CPPFile()), - _pointing_at(pointing_at) + _pointing_at(pointing_at), + _value_category(vcat) { } @@ -146,8 +147,14 @@ void CPPReferenceType:: output_instance(ostream &out, int indent_level, CPPScope *scope, bool complete, const string &prename, const string &name) const { - _pointing_at->output_instance(out, indent_level, scope, complete, - "&" + prename, name); + + if (_value_category == VC_rvalue) { + _pointing_at->output_instance(out, indent_level, scope, complete, + "&&" + prename, name); + } else { + _pointing_at->output_instance(out, indent_level, scope, complete, + "&" + prename, name); + } } //////////////////////////////////////////////////////////////////// @@ -182,7 +189,8 @@ is_equal(const CPPDeclaration *other) const { const CPPReferenceType *ot = ((CPPDeclaration *)other)->as_reference_type(); assert(ot != NULL); - return _pointing_at == ot->_pointing_at; + return (_pointing_at == ot->_pointing_at) && + (_value_category == ot->_value_category); } @@ -198,5 +206,9 @@ is_less(const CPPDeclaration *other) const { const CPPReferenceType *ot = ((CPPDeclaration *)other)->as_reference_type(); assert(ot != NULL); + if (_value_category != ot->_value_category) { + return (_value_category < ot->_value_category); + } + return _pointing_at < ot->_pointing_at; } diff --git a/dtool/src/cppparser/cppReferenceType.h b/dtool/src/cppparser/cppReferenceType.h index 300db0035c..3bf292841e 100644 --- a/dtool/src/cppparser/cppReferenceType.h +++ b/dtool/src/cppparser/cppReferenceType.h @@ -21,13 +21,22 @@ /////////////////////////////////////////////////////////////////// // Class : CPPReferenceType -// Description : +// Description : Either an lvalue- or rvalue-reference. //////////////////////////////////////////////////////////////////// class CPPReferenceType : public CPPType { public: - CPPReferenceType(CPPType *pointing_at); + enum ValueCategory { + VC_lvalue, + VC_rvalue + }; + + CPPReferenceType(CPPType *pointing_at, ValueCategory vcat=VC_lvalue); CPPType *_pointing_at; + ValueCategory _value_category; + + inline bool is_lvalue() const; + inline bool is_rvalue() const; virtual bool is_fully_specified() const; virtual CPPDeclaration *substitute_decl(SubstDecl &subst, From 8098460433ba5ae3ac38e9021ea0685f269fc2b7 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 2 Jan 2015 15:06:47 +0100 Subject: [PATCH 09/83] Use -fno-exceptions for more performance; disable RTTI in release builds --- makepanda/makepanda.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 04b1df78cd..8bb6a92280 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1108,8 +1108,6 @@ def CompileCxx(obj,src,opts): cmd += ' -fno-inline-functions-called-once -fgcse-after-reload' cmd += ' -frerun-cse-after-loop -frename-registers' - if not src.endswith(".c"): - cmd += " -fno-exceptions -fno-rtti" cmd += " -Wa,--noexecstack" # Now add specific release/debug flags. @@ -1135,6 +1133,16 @@ def CompileCxx(obj,src,opts): else: cmd += " -pthread" + if not src.endswith(".c"): + # We don't use exceptions. + if 'EXCEPTIONS' not in opts: + cmd += " -fno-exceptions" + + if 'RTTI' not in opts: + # We always disable RTTI on Android for memory usage reasons. + if optlevel >= 4 or GetTarget() == "android": + cmd += " -fno-rtti" + if PkgSkip("SSE2") == 0 and not arch.startswith("arm"): cmd += " -msse2" @@ -2185,6 +2193,10 @@ def WriteConfigSettings(): if (GetOptimize() >= 4): dtool_config["PRC_SAVE_DESCRIPTIONS"] = 'UNDEF' + if (GetOptimize() >= 4): + # Disable RTTI on release builds. + dtool_config["HAVE_RTTI"] = 'UNDEF' + # Now that we have OS_SIMPLE_THREADS, we can support # SIMPLE_THREADS on exotic architectures like win64, so we no # longer need to disable it for this platform. @@ -3665,7 +3677,7 @@ if (PkgSkip("ROCKET") == 0) and (not RUNTIME): TargetAdd('libp3rocket.dll', input=COMMON_PANDA_LIBS) TargetAdd('libp3rocket.dll', opts=OPTS) - OPTS=['DIR:panda/src/rocket', 'ROCKET'] + OPTS=['DIR:panda/src/rocket', 'ROCKET', 'RTTI', 'EXCEPTIONS'] IGATEFILES=GetDirectoryContents('panda/src/rocket', ["rocketInputHandler.h", "rocketInputHandler.cxx", "rocketRegion.h", "rocketRegion.cxx", "rocketRegion_ext.h"]) TargetAdd('libp3rocket.in', opts=OPTS, input=IGATEFILES) From e8905b840cb13113f4d62c58f6730488628d694d Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 2 Jan 2015 15:25:58 +0100 Subject: [PATCH 10/83] Use C++11 move semantics to dramatically improve PointerTo performance --- dtool/src/dtoolbase/dtoolbase_cc.h | 41 +++++++++--------- panda/src/express/pointerTo.I | 68 ++++++++++++++++++++++++++++++ panda/src/express/pointerTo.h | 10 +++++ panda/src/express/pointerToBase.I | 14 ++++++ panda/src/express/pointerToBase.h | 4 ++ 5 files changed, 118 insertions(+), 19 deletions(-) diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index 94891de299..93d90efe48 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -34,6 +34,7 @@ using namespace std; #define INLINE inline #define TYPENAME typename #define CONSTEXPR +#define NOEXCEPT noexcept #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname) @@ -121,15 +122,28 @@ typedef ios::seekdir ios_seekdir; #endif #if defined(__has_extension) // Clang magic. -#if __has_extension(cxx_constexpr) -#define CONSTEXPR constexpr -#else -#define CONSTEXPR INLINE -#endif +# if __has_extension(cxx_constexpr) +# define CONSTEXPR constexpr +# else +# define CONSTEXPR INLINE +# endif +# if __has_extension(cxx_noexcept) +# define NOEXCEPT noexcept +# else +# define NOEXCEPT +# endif +# if __has_extension(cxx_rvalue_references) +# define USE_MOVE_SEMANTICS +# endif #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && (__cplusplus >= 201103L) -#define CONSTEXPR constexpr +// noexcept was introduced in GCC 4.6, constexpr in GCC 4.7, rvalue refs in +// GCC 4.3. However, GCC only started defining __cplusplus properly in 4.7. +# define CONSTEXPR constexpr +# define NOEXCEPT noexcept +# define USE_MOVE_SEMANTICS #else -#define CONSTEXPR INLINE +# define CONSTEXPR INLINE +# define NOEXCEPT #endif #if defined(WIN32_VC) && !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES) @@ -209,7 +223,7 @@ public: TauProfile(void *&tautimer, char *name, char *type, int group, char *group_name) { Tau_profile_c_timer(&tautimer, name, type, group, group_name); _tautimer = tautimer; - TAU_PROFILE_START(_tautimer); + TAU_PROFILE_START(_tautimer); } ~TauProfile() { if (!__tau_shutdown) { @@ -233,16 +247,5 @@ private: #endif // USE_TAU -// Macros from hell. -#define EXT_METHOD(cl, m) Extension::m() -#define EXT_METHOD_ARGS(cl, m, ...) Extension::m(__VA_ARGS__) -#define EXT_CONST_METHOD(cl, m) Extension::m() const -#define EXT_CONST_METHOD_ARGS(cl, m, ...) Extension::m(__VA_ARGS__) const -#define EXT_NESTED_METHOD(cl1, cl2, m) Extension::m() -#define EXT_NESTED_METHOD_ARGS(cl1, cl2, m, ...) Extension::m(__VA_ARGS__) -#define EXT_NESTED_CONST_METHOD(cl1, cl2, m) Extension::m() const -#define EXT_NESTED_CONST_METHOD_ARGS(cl1, cl2, m, ...) Extension::m(__VA_ARGS__) const -#define CALL_EXT_METHOD(cl, m, obj, ...) invoke_extension(obj).m(__VA_ARGS__) - #endif // __cplusplus #endif diff --git a/panda/src/express/pointerTo.I b/panda/src/express/pointerTo.I index d17d6ed6e8..5b021f8e86 100644 --- a/panda/src/express/pointerTo.I +++ b/panda/src/express/pointerTo.I @@ -35,6 +35,40 @@ PointerTo(const PointerTo ©) : { } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: PointerTo::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE PointerTo:: +PointerTo(PointerTo &&move) NOEXCEPT : + PointerToBase((PointerToBase &&)move) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerTo::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE PointerTo &PointerTo:: +operator = (PointerTo &&move) NOEXCEPT { + To *old_ptr = (To *)this->_void_ptr; + + this->_void_ptr = move._void_ptr; + move._void_ptr = NULL; + + if (old_ptr != (To *)NULL) { + unref_delete(old_ptr); + } + + return *this; +} +#endif + //////////////////////////////////////////////////////////////////// // Function: PointerTo::Destructor // Access: Public @@ -166,6 +200,40 @@ ConstPointerTo(const ConstPointerTo ©) : { } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerTo::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE ConstPointerTo:: +ConstPointerTo(ConstPointerTo &&move) NOEXCEPT : + PointerToBase((PointerToBase &&)move) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerTo::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE ConstPointerTo &ConstPointerTo:: +operator = (ConstPointerTo &&move) NOEXCEPT { + To *old_ptr = (To *)this->_void_ptr; + + this->_void_ptr = move._void_ptr; + move._void_ptr = NULL; + + if (old_ptr != (To *)NULL) { + unref_delete(old_ptr); + } + + return *this; +} +#endif + //////////////////////////////////////////////////////////////////// // Function: ConstPointerTo::Dereference operator // Access: Public diff --git a/panda/src/express/pointerTo.h b/panda/src/express/pointerTo.h index 144bc0eb87..e93ef68f80 100644 --- a/panda/src/express/pointerTo.h +++ b/panda/src/express/pointerTo.h @@ -85,6 +85,11 @@ PUBLISHED: INLINE ~PointerTo(); public: +#ifdef USE_MOVE_SEMANTICS + INLINE PointerTo(PointerTo &&move) NOEXCEPT; + INLINE PointerTo &operator = (PointerTo &&move) NOEXCEPT; +#endif + INLINE To &operator *() const; INLINE To *operator -> () const; // MSVC.NET 2005 insists that we use T *, and not To *, here. @@ -144,6 +149,11 @@ PUBLISHED: INLINE ~ConstPointerTo(); public: +#ifdef USE_MOVE_SEMANTICS + INLINE ConstPointerTo(ConstPointerTo &&move) NOEXCEPT; + INLINE ConstPointerTo &operator = (ConstPointerTo &&move) NOEXCEPT; +#endif + INLINE const To &operator *() const; INLINE const To *operator -> () const; INLINE operator const T *() const; diff --git a/panda/src/express/pointerToBase.I b/panda/src/express/pointerToBase.I index df0b635093..f6c5e192fd 100644 --- a/panda/src/express/pointerToBase.I +++ b/panda/src/express/pointerToBase.I @@ -35,6 +35,20 @@ PointerToBase(const PointerToBase ©) { reassign(copy); } +//////////////////////////////////////////////////////////////////// +// Function: PointerToBase::Move Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +#ifdef USE_MOVE_SEMANTICS +template +INLINE PointerToBase:: +PointerToBase(PointerToBase &&move) NOEXCEPT { + _void_ptr = move._void_ptr; + move._void_ptr = (void *)NULL; +} +#endif + //////////////////////////////////////////////////////////////////// // Function: PointerToBase::Destructor // Access: Protected diff --git a/panda/src/express/pointerToBase.h b/panda/src/express/pointerToBase.h index dd8a610188..495033ff71 100644 --- a/panda/src/express/pointerToBase.h +++ b/panda/src/express/pointerToBase.h @@ -38,6 +38,10 @@ protected: INLINE PointerToBase(const PointerToBase ©); INLINE ~PointerToBase(); +#ifdef USE_MOVE_SEMANTICS + INLINE PointerToBase(PointerToBase &&move) NOEXCEPT; +#endif + INLINE void reassign(To *ptr); INLINE void reassign(const PointerToBase ©); From 5e5a04031f68c5cb1737223d66bd84e37f29f354 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 2 Jan 2015 15:26:47 +0100 Subject: [PATCH 11/83] Remove old decal system to simplify cull/draw process a bit more --- panda/src/pgraph/config_pgraph.cxx | 8 +- panda/src/pgraph/cullBin.cxx | 57 +---- panda/src/pgraph/cullResult.cxx | 74 +----- panda/src/pgraph/cullResult.h | 7 +- panda/src/pgraph/cullTraverser.I | 8 +- panda/src/pgraph/cullTraverser.cxx | 370 +++++----------------------- panda/src/pgraph/cullTraverser.h | 9 +- panda/src/pgraph/cullableObject.I | 118 ++------- panda/src/pgraph/cullableObject.cxx | 120 +-------- panda/src/pgraph/cullableObject.h | 30 +-- 10 files changed, 132 insertions(+), 669 deletions(-) diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 840ce5ba4e..639f7f4a5a 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -257,12 +257,12 @@ ConfigVariableBool retransform_sprites "necessary in order for fog to work correctly on the sprites.")); ConfigVariableBool depth_offset_decals -("depth-offset-decals", false, +("depth-offset-decals", true, PRC_DESC("Set this true to allow decals to be implemented via the advanced " "depth offset feature, if supported, instead of via the traditional " - "(and slower) two-pass approach. This is false by default " - "because it appears that many graphics drivers have issues with " - "their depth offset implementation.")); + "(and slower) two-pass approach. This is currently the only method " + "by which decals are implemented in Panda3D, and as such, this " + "setting is ignored.")); ConfigVariableInt max_collect_vertices ("max-collect-vertices", 65534, diff --git a/panda/src/pgraph/cullBin.cxx b/panda/src/pgraph/cullBin.cxx index 3c16739197..ce1a97c402 100644 --- a/panda/src/pgraph/cullBin.cxx +++ b/panda/src/pgraph/cullBin.cxx @@ -27,7 +27,7 @@ TypeHandle CullBin::_type_handle; //////////////////////////////////////////////////////////////////// // Function: CullBin::Destructor // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// CullBin:: ~CullBin() { @@ -115,7 +115,7 @@ check_flash_color() { } else { _has_flash_color = false; pgraph_cat.warning() - << "Invalid value for flash-bin-" << _name << ": " + << "Invalid value for flash-bin-" << _name << ": " << flash_bin.get_string_value() << "\n"; } #endif // NDEBUG @@ -124,7 +124,7 @@ check_flash_color() { //////////////////////////////////////////////////////////////////// // Function: CullBin::ResultGraphBuilder::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// CullBin::ResultGraphBuilder:: ResultGraphBuilder(PandaNode *root_node) : @@ -142,9 +142,8 @@ ResultGraphBuilder(PandaNode *root_node) : //////////////////////////////////////////////////////////////////// void CullBin::ResultGraphBuilder:: add_object(CullableObject *object) { - if (_current_transform != object->_modelview_transform || - _current_state != object->_state || - object->is_fancy()) { + if (_current_transform != object->_modelview_transform || + _current_state != object->_state) { // Create a new GeomNode to hold the net transform and state. We // choose to create a new GeomNode for each new state, to make it // clearer to the observer when the state changes. @@ -157,57 +156,13 @@ add_object(CullableObject *object) { } record_one_object(_current_node, object); - - if (object->get_next() != (CullableObject *)NULL) { - // Collect the decal base pieces. - CullableObject *base = object->get_next(); - while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) { - record_one_object(_current_node, base); - base = base->get_next(); - } - - if (base != (CullableObject *)NULL) { - // Now, collect all the decals. - _current_node->set_effect(DecalEffect::make()); - int decal_index = 0; - - CPT(TransformState) transform; - CPT(RenderState) state; - PT(GeomNode) decal_node; - CullableObject *decal = base->get_next(); - while (decal != (CullableObject *)NULL) { - if (transform != decal->_modelview_transform || - state != decal->_state || - decal->get_next() != (CullableObject *)NULL) { - // Create a new GeomNode to hold the net transform. - transform = decal->_modelview_transform; - state = decal->_state; - decal_node = new GeomNode("decal_" + format_string(decal_index)); - _current_node->add_child(decal_node); - decal_node->set_transform(transform); - decal_node->set_state(state); - } - - record_one_object(decal_node, decal); - decal = decal->get_next(); - ++decal_index; - } - } - - // Reset the current node pointer for next time so the decal root - // will remain in its own node. - _current_node.clear(); - _current_transform.clear(); - _current_state.clear(); - } - ++_object_index; } //////////////////////////////////////////////////////////////////// // Function: CullBin::ResultGraphBuilder::record_one_object // Access: Private -// Description: Records a single object, without regard to decalling. +// Description: Records a single object. //////////////////////////////////////////////////////////////////// void CullBin::ResultGraphBuilder:: record_one_object(GeomNode *node, CullableObject *object) { diff --git a/panda/src/pgraph/cullResult.cxx b/panda/src/pgraph/cullResult.cxx index 4868d46529..cd795c489f 100644 --- a/panda/src/pgraph/cullResult.cxx +++ b/panda/src/pgraph/cullResult.cxx @@ -57,7 +57,7 @@ static const double bin_color_flash_rate = 1.0; // 1 state change per second //////////////////////////////////////////////////////////////////// // Function: CullResult::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// CullResult:: CullResult(GraphicsStateGuardianBase *gsg, @@ -87,7 +87,7 @@ make_next() const { for (size_t i = 0; i < _bins.size(); ++i) { CullBin *old_bin = _bins[i]; - if (old_bin == (CullBin *)NULL || + if (old_bin == (CullBin *)NULL || old_bin->get_bin_type() != bin_manager->get_bin_type(i)) { new_result->_bins.push_back((CullBin *)NULL); } else { @@ -166,21 +166,19 @@ add_object(CullableObject *object, const CullTraverser *traverser) { // later. This means we must copy the object and add it to // both bins. We can only do this if we do not have an // explicit bin already applied; otherwise, M_dual falls back - // to M_alpha. + // to M_alpha. { const CullBinAttrib *bin_attrib = DCAST(CullBinAttrib, state->get_attrib(CullBinAttrib::get_class_slot())); - if (bin_attrib == (CullBinAttrib *)NULL || + if (bin_attrib == (CullBinAttrib *)NULL || bin_attrib->get_bin_name().empty()) { - // We make a copy of the object to draw the transparent part - // without decals; this gets placed in the transparent bin. + // We make a copy of the object to draw the transparent part; + // this gets placed in the transparent bin. #ifndef NDEBUG - if (m_dual_transparent) + if (m_dual_transparent) #endif { CullableObject *transparent_part = new CullableObject(*object); - CPT(RenderState) transparent_state = object->has_decals() ? - get_dual_transparent_state_decals() : - get_dual_transparent_state(); + CPT(RenderState) transparent_state = get_dual_transparent_state(); transparent_part->_state = state->compose(transparent_state); if (transparent_part->munge_geom (_gsg, _gsg->get_geom_munger(transparent_part->_state, current_thread), @@ -195,9 +193,9 @@ add_object(CullableObject *object, const CullTraverser *traverser) { delete transparent_part; } } - - // Now we can draw the opaque part, with decals. This will - // end up in the opaque bin. + + // Now we can draw the opaque part. This will end up in + // the opaque bin. object->_state = state->compose(get_dual_opaque_state()); #ifndef NDEBUG if (!m_dual_opaque) { @@ -210,7 +208,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) { // M_alpha. } break; - + default: // Other kinds of transparency need no special handling. break; @@ -443,8 +441,6 @@ check_flash_transparency(CPT(RenderState) &state, const LColor &transparency) { // Access: Private // Description: Returns a RenderState that renders only the // transparent parts of an object, in support of M_dual. -// This state is suitable only for objects that do not -// contain decals. //////////////////////////////////////////////////////////////////// CPT(RenderState) CullResult:: get_dual_transparent_state() { @@ -454,10 +450,7 @@ get_dual_transparent_state() { // and hence filling up the depth buffer with large empty spaces // that may obscure other things. However, this does mean we draw // pixels twice where the alpha == 1.0 (since they were already - // drawn in the opaque pass). This is not normally a problem, - // except when we are using decals; in the case of decals, we - // don't want to draw the 1.0 pixels again, since these are the - // ones that may have been decaled onto. + // drawn in the opaque pass). This is not normally a problem. state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f), TransparencyAttrib::make(TransparencyAttrib::M_alpha), DepthWriteAttrib::make(DepthWriteAttrib::M_off), @@ -487,47 +480,6 @@ get_dual_transparent_state() { return state; } -//////////////////////////////////////////////////////////////////// -// Function: CullResult::get_dual_transparent_state_decals -// Access: Private -// Description: Returns a RenderState that renders only the -// transparent parts of an object, but suitable for -// objects that contain decals. -//////////////////////////////////////////////////////////////////// -CPT(RenderState) CullResult:: -get_dual_transparent_state_decals() { - static CPT(RenderState) state = NULL; - if (state == (const RenderState *)NULL) { - // This is exactly the same as above except here we make the alpha - // test of < 1.0 instead of > 0.0. This makes us draw big empty - // pixels where the alpha values are 0.0, but we don't overwrite - // the decals where the pixels are 1.0. - state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, dual_opaque_level), - TransparencyAttrib::make(TransparencyAttrib::M_alpha), - DepthWriteAttrib::make(DepthWriteAttrib::M_off), - RenderState::get_max_priority()); - } - -#ifndef NDEBUG - if (m_dual_flash) { - int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate); - if ((cycle & 1) == 0) { - static CPT(RenderState) flash_state = NULL; - if (flash_state == (const RenderState *)NULL) { - flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.2, 0.2, 1.0f)), - RenderState::get_max_priority()); - flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)), - RenderState::get_max_priority()); - - } - return flash_state; - } - } -#endif // NDEBUG - - return state; -} - //////////////////////////////////////////////////////////////////// // Function: CullResult::get_dual_opaque_state // Access: Private diff --git a/panda/src/pgraph/cullResult.h b/panda/src/pgraph/cullResult.h index 06b7c1a17b..93604fc558 100644 --- a/panda/src/pgraph/cullResult.h +++ b/panda/src/pgraph/cullResult.h @@ -72,12 +72,11 @@ private: static CPT(RenderState) get_alpha_state(); static CPT(RenderState) get_binary_state(); static CPT(RenderState) get_dual_transparent_state(); - static CPT(RenderState) get_dual_transparent_state_decals(); static CPT(RenderState) get_dual_opaque_state(); GraphicsStateGuardianBase *_gsg; PStatCollector _draw_region_pcollector; - + typedef pvector< PT(CullBin) > Bins; Bins _bins; @@ -90,7 +89,7 @@ public: register_type(_type_handle, "CullResult", ReferenceCount::get_class_type()); } - + private: static TypeHandle _type_handle; }; @@ -99,5 +98,3 @@ private: #endif - - diff --git a/panda/src/pgraph/cullTraverser.I b/panda/src/pgraph/cullTraverser.I index 7ee69834e2..291221b2de 100644 --- a/panda/src/pgraph/cullTraverser.I +++ b/panda/src/pgraph/cullTraverser.I @@ -110,12 +110,12 @@ get_initial_state() const { //////////////////////////////////////////////////////////////////// // Function: CullTraverser::get_depth_offset_decals // Access: Published -// Description: Returns the depth_offset_decals flag. See -// set_depth_offset_decals(). +// Description: Returns true, as depth offsets are the only way +// that we implement decals nowadays. //////////////////////////////////////////////////////////////////// INLINE bool CullTraverser:: get_depth_offset_decals() const { - return _depth_offset_decals; + return true; } //////////////////////////////////////////////////////////////////// @@ -199,7 +199,7 @@ get_cull_handler() const { //////////////////////////////////////////////////////////////////// // Function: CullTraverser::set_portal_clipper // Access: Published -// Description: Specifies _portal_clipper object pointer that +// Description: Specifies _portal_clipper object pointer that // subsequent traverse() or traverse_below may use. //////////////////////////////////////////////////////////////////// INLINE void CullTraverser:: diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index 308d52f3b7..292e81565e 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -47,7 +47,7 @@ TypeHandle CullTraverser::_type_handle; //////////////////////////////////////////////////////////////////// // Function: CullTraverser::Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// CullTraverser:: CullTraverser() : @@ -65,7 +65,7 @@ CullTraverser() : //////////////////////////////////////////////////////////////////// // Function: CullTraverser::Copy Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// CullTraverser:: CullTraverser(const CullTraverser ©) : @@ -76,7 +76,6 @@ CullTraverser(const CullTraverser ©) : _has_tag_state_key(copy._has_tag_state_key), _tag_state_key(copy._tag_state_key), _initial_state(copy._initial_state), - _depth_offset_decals(copy._depth_offset_decals), _view_frustum(copy._view_frustum), _cull_handler(copy._cull_handler), _portal_clipper(copy._portal_clipper), @@ -98,7 +97,6 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsg, _gsg = gsg; _initial_state = scene_setup->get_initial_state(); - _depth_offset_decals = _gsg->depth_offset_decals() && depth_offset_decals; _current_thread = Thread::get_current_thread(); @@ -129,43 +127,43 @@ traverse(const NodePath &root) { PT(BoundingVolume) bv = _scene_setup->get_lens()->make_bounds(); if (bv != (BoundingVolume *)NULL && bv->is_of_type(GeometricBoundingVolume::get_class_type())) { - + local_frustum = DCAST(GeometricBoundingVolume, bv); } - + // This local_frustum is in camera space PortalClipper portal_viewer(local_frustum, _scene_setup); if (debug_portal_cull) { portal_viewer.draw_camera_frustum(); } - + // Store this pointer in this set_portal_clipper(&portal_viewer); CullTraverserData data(root, TransformState::make_identity(), - _initial_state, _view_frustum, + _initial_state, _view_frustum, _current_thread); - + traverse(data); - + // Finally add the lines to be drawn if (debug_portal_cull) { portal_viewer.draw_lines(); } - + // Render the frustum relative to the cull center. NodePath cull_center = _scene_setup->get_cull_center(); CPT(TransformState) transform = cull_center.get_transform(root); - + CullTraverserData my_data(data, portal_viewer._previous); my_data._net_transform = my_data._net_transform->compose(transform); traverse(my_data); } else { CullTraverserData data(root, TransformState::make_identity(), - _initial_state, _view_frustum, + _initial_state, _view_frustum, _current_thread); - + traverse(data); } } @@ -181,7 +179,7 @@ void CullTraverser:: traverse(CullTraverserData &data) { if (is_in_view(data)) { if (pgraph_cat.is_spam()) { - pgraph_cat.spam() + pgraph_cat.spam() << "\n" << data._node_path << " " << data._draw_mask << "\n"; } @@ -207,9 +205,9 @@ traverse(CullTraverserData &data) { // up now. show_bounds(data, node_effects->has_show_tight_bounds()); } - + data.apply_transform_and_state(this); - + const FogAttrib *fog = DCAST(FogAttrib, node_reader->get_state()->get_attrib(FogAttrib::get_class_slot())); if (fog != (const FogAttrib *)NULL && fog->get_fog() != (Fog *)NULL) { // If we just introduced a FogAttrib here, call adjust_to_camera() @@ -218,7 +216,7 @@ traverse(CullTraverserData &data) { // need for it. fog->get_fog()->adjust_to_camera(get_camera_transform()); } - + if (fancy_bits & PandaNode::FB_cull_callback) { PandaNode *node = data.node(); if (!node->cull_callback(this, data)) { @@ -247,47 +245,41 @@ traverse_below(CullTraverserData &data) { const RenderEffects *node_effects = node_reader->get_effects(); bool has_decal = !this_node_hidden && node_effects->has_decal(); - if (has_decal && !_depth_offset_decals) { - // Start the three-pass decal rendering if we're not using - // DepthOffsetAttribs to implement decals. - start_decal(data); - - } else { - if (!this_node_hidden) { - node->add_for_draw(this, data); - } - if (has_decal) { - // If we *are* implementing decals with DepthOffsetAttribs, - // apply it now, so that each child of this node gets offset by - // a tiny amount. - data._state = data._state->compose(get_depth_offset_state()); + if (!this_node_hidden) { + node->add_for_draw(this, data); + } + + if (has_decal) { + // If we *are* implementing decals with DepthOffsetAttribs, + // apply it now, so that each child of this node gets offset by + // a tiny amount. + data._state = data._state->compose(get_depth_offset_state()); #ifndef NDEBUG - // This is just a sanity check message. - if (!node->is_geom_node()) { - pgraph_cat.error() - << "DecalEffect applied to " << *node << ", not a GeomNode.\n"; - } + // This is just a sanity check message. + if (!node->is_geom_node()) { + pgraph_cat.error() + << "DecalEffect applied to " << *node << ", not a GeomNode.\n"; + } #endif + } + + // Now visit all the node's children. + PandaNode::Children children = node_reader->get_children(); + node_reader->release(); + int num_children = children.get_num_children(); + if (node->has_selective_visibility()) { + int i = node->get_first_visible_child(); + while (i < num_children) { + CullTraverserData next_data(data, children.get_child(i)); + traverse(next_data); + i = node->get_next_visible_child(i); } - // Now visit all the node's children. - PandaNode::Children children = node_reader->get_children(); - node_reader->release(); - int num_children = children.get_num_children(); - if (node->has_selective_visibility()) { - int i = node->get_first_visible_child(); - while (i < num_children) { - CullTraverserData next_data(data, children.get_child(i)); - traverse(next_data); - i = node->get_next_visible_child(i); - } - - } else { - for (int i = 0; i < num_children; i++) { - CullTraverserData next_data(data, children.get_child(i)); - traverse(next_data); - } + } else { + for (int i = 0; i < num_children; i++) { + CullTraverserData next_data(data, children.get_child(i)); + traverse(next_data); } } } @@ -311,20 +303,20 @@ end_traverse() { // bounding volume. //////////////////////////////////////////////////////////////////// void CullTraverser:: -draw_bounding_volume(const BoundingVolume *vol, +draw_bounding_volume(const BoundingVolume *vol, const TransformState *net_transform, const TransformState *modelview_transform) const { PT(Geom) bounds_viz = make_bounds_viz(vol); - + if (bounds_viz != (Geom *)NULL) { _geoms_pcollector.add_level(2); - CullableObject *outer_viz = - new CullableObject(bounds_viz, get_bounds_outer_viz_state(), + CullableObject *outer_viz = + new CullableObject(bounds_viz, get_bounds_outer_viz_state(), net_transform, modelview_transform, get_scene()); _cull_handler->record_object(outer_viz, this); - - CullableObject *inner_viz = - new CullableObject(bounds_viz, get_bounds_inner_viz_state(), + + CullableObject *inner_viz = + new CullableObject(bounds_viz, get_bounds_inner_viz_state(), net_transform, modelview_transform, get_scene()); _cull_handler->record_object(inner_viz, this); } @@ -360,13 +352,13 @@ show_bounds(CullTraverserData &data, bool tight) { if (bounds_viz != (Geom *)NULL) { _geoms_pcollector.add_level(1); - CullableObject *outer_viz = - new CullableObject(bounds_viz, get_bounds_outer_viz_state(), + CullableObject *outer_viz = + new CullableObject(bounds_viz, get_bounds_outer_viz_state(), net_transform, modelview_transform, get_scene()); _cull_handler->record_object(outer_viz, this); } - + } else { draw_bounding_volume(node->get_bounds(), net_transform, modelview_transform); @@ -378,7 +370,7 @@ show_bounds(CullTraverserData &data, bool tight) { GeomNode *gnode = DCAST(GeomNode, node); int num_geoms = gnode->get_num_geoms(); for (int i = 0; i < num_geoms; ++i) { - draw_bounding_volume(gnode->get_geom(i)->get_bounds(), + draw_bounding_volume(gnode->get_geom(i)->get_bounds(), net_transform, modelview_transform); } } @@ -407,7 +399,7 @@ make_bounds_viz(const BoundingVolume *vol) { ("bounds", GeomVertexFormat::get_v3(), Geom::UH_stream); GeomVertexWriter vertex(vdata, InternalName::get_vertex()); - + PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream); for (int sl = 0; sl < num_slices; ++sl) { PN_stdfloat longitude0 = (PN_stdfloat)sl / (PN_stdfloat)num_slices; @@ -419,11 +411,11 @@ make_bounds_viz(const BoundingVolume *vol) { vertex.add_data3(compute_point(sphere, latitude, longitude1)); } vertex.add_data3(compute_point(sphere, 1.0, longitude0)); - + strip->add_next_vertices(num_stacks * 2); strip->close_primitive(); } - + geom = new Geom(vdata); geom->add_primitive(strip); @@ -438,7 +430,7 @@ make_bounds_viz(const BoundingVolume *vol) { for (int i = 0; i < 8; ++i ) { vertex.add_data3(fvol->get_point(i)); } - + PT(GeomLines) lines = new GeomLines(Geom::UH_stream); lines->add_vertices(0, 1); lines->close_primitive(); lines->add_vertices(1, 2); lines->close_primitive(); @@ -472,7 +464,7 @@ make_bounds_viz(const BoundingVolume *vol) { for (int i = 0; i < 8; ++i ) { vertex.add_data3(box.get_point(i)); } - + PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_stream); tris->add_vertices(0, 4, 5); tris->close_primitive(); @@ -533,7 +525,7 @@ make_tight_bounds_viz(PandaNode *node) const { Geom::UH_stream); GeomVertexWriter vertex(vdata, InternalName::get_vertex(), _current_thread); - + vertex.add_data3(n[0], n[1], n[2]); vertex.add_data3(n[0], n[1], x[2]); vertex.add_data3(n[0], x[1], n[2]); @@ -542,7 +534,7 @@ make_tight_bounds_viz(PandaNode *node) const { vertex.add_data3(x[0], n[1], x[2]); vertex.add_data3(x[0], x[1], n[2]); vertex.add_data3(x[0], x[1], x[2]); - + PT(GeomLinestrips) strip = new GeomLinestrips(Geom::UH_stream); // We wind one long linestrip around the wireframe cube. This @@ -564,7 +556,7 @@ make_tight_bounds_viz(PandaNode *node) const { strip->add_vertex(5); strip->add_vertex(1); strip->close_primitive(); - + geom = new Geom(vdata); geom->add_primitive(strip); } @@ -576,10 +568,10 @@ make_tight_bounds_viz(PandaNode *node) const { // Function: CullTraverser::compute_point // Access: Private, Static // Description: Returns a point on the surface of the sphere. -// latitude and longitude range from 0.0 to 1.0. +// latitude and longitude range from 0.0 to 1.0. //////////////////////////////////////////////////////////////////// LVertex CullTraverser:: -compute_point(const BoundingSphere *sphere, +compute_point(const BoundingSphere *sphere, PN_stdfloat latitude, PN_stdfloat longitude) { PN_stdfloat s1, c1; csincos(latitude * MathNumbers::pi, &s1, &c1); @@ -648,231 +640,3 @@ get_depth_offset_state() { } return state; } - - -//////////////////////////////////////////////////////////////////// -// Function: CullTraverser::start_decal -// Access: Private -// Description: Collects a base node and all of the decals applied to -// it. This involves recursing below the base GeomNode -// to find all the decal geoms. -//////////////////////////////////////////////////////////////////// -void CullTraverser:: -start_decal(const CullTraverserData &data) { - PandaNode *node = data.node(); - if (!node->is_geom_node()) { - pgraph_cat.error() - << "DecalEffect applied to " << *node << ", not a GeomNode.\n"; - return; - } - - const PandaNodePipelineReader *node_reader = data.node_reader(); - - // Build a chain of CullableObjects. The head of the chain will be - // all of the base Geoms in order, followed by an empty - // CullableObject node, followed by all of the decal Geoms, in - // order. - - // Since the CullableObject is a linked list which gets built in - // LIFO order, we start with the decals. - CullableObject *decals = (CullableObject *)NULL; - PandaNode::Children cr = node_reader->get_children(); - int num_children = cr.get_num_children(); - if (node->has_selective_visibility()) { - int i = node->get_first_visible_child(); - while (i < num_children) { - CullTraverserData next_data(data, cr.get_child(i)); - decals = r_get_decals(next_data, decals); - i = node->get_next_visible_child(i); - } - - } else { - for (int i = num_children - 1; i >= 0; i--) { - CullTraverserData next_data(data, cr.get_child(i)); - decals = r_get_decals(next_data, decals); - } - } - - // Now create a new, empty CullableObject to separate the decals - // from the non-decals. - CullableObject *separator = new CullableObject; - separator->set_next(decals); - - // And now get the base Geoms, again in reverse order. - CullableObject *object = separator; - GeomNode *geom_node = DCAST(GeomNode, node); - GeomNode::Geoms geoms = geom_node->get_geoms(); - int num_geoms = geoms.get_num_geoms(); - _geoms_pcollector.add_level(num_geoms); - CPT(TransformState) net_transform = data.get_net_transform(this); - CPT(TransformState) modelview_transform = data.get_modelview_transform(this); - CPT(TransformState) internal_transform = _scene_setup->get_cs_transform()->compose(modelview_transform); - - for (int i = num_geoms - 1; i >= 0; i--) { - const Geom *geom = geoms.get_geom(i); - if (geom->is_empty()) { - continue; - } - - CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i)); - if (state->has_cull_callback() && !state->cull_callback(this, data)) { - // Cull. - continue; - } - - // Cull the Geom bounding volume against the view frustum - // and/or the cull planes. Don't bother unless we've got more - // than one Geom, since otherwise the bounding volume of the - // GeomNode is (probably) the same as that of the one Geom, - // and we've already culled against that. - if (num_geoms > 1) { - if (data._view_frustum != (GeometricBoundingVolume *)NULL) { - // Cull the individual Geom against the view frustum. - CPT(BoundingVolume) geom_volume = geom->get_bounds(); - const GeometricBoundingVolume *geom_gbv = - DCAST(GeometricBoundingVolume, geom_volume); - - int result = data._view_frustum->contains(geom_gbv); - if (result == BoundingVolume::IF_no_intersection) { - // Cull this Geom. - continue; - } - } - if (!data._cull_planes->is_empty()) { - // Also cull the Geom against the cull planes. - CPT(BoundingVolume) geom_volume = geom->get_bounds(); - const GeometricBoundingVolume *geom_gbv = - DCAST(GeometricBoundingVolume, geom_volume); - int result; - data._cull_planes->do_cull(result, state, geom_gbv); - if (result == BoundingVolume::IF_no_intersection) { - // Cull. - continue; - } - } - } - - CullableObject *next = object; - object = - new CullableObject(geom, state, net_transform, - modelview_transform, internal_transform); - object->set_next(next); - } - - if (object != separator) { - // Finally, send the whole list down to the CullHandler for - // processing. The first Geom in the node now represents the - // overall state. - _cull_handler->record_object(object, this); - } else { - // Never mind; there's nothing to render. - delete object; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: CullTraverser::r_get_decals -// Access: Private -// Description: Recursively gets all the decals applied to a -// particular GeomNode. These are built into a -// CullableObject list in LIFO order (so that the -// traversing the list will extract them in the order -// they were encountered in the scene graph). -//////////////////////////////////////////////////////////////////// -CullableObject *CullTraverser:: -r_get_decals(CullTraverserData &data, CullableObject *decals) { - if (is_in_view(data)) { - PandaNodePipelineReader *node_reader = data.node_reader(); - PandaNode *node = data.node(); - - const RenderEffects *node_effects = node_reader->get_effects(); - if (node_effects->has_show_bounds()) { - // If we should show the bounding volume for this node, make it - // up now. - show_bounds(data, node_effects->has_show_tight_bounds()); - } - - data.apply_transform_and_state(this); - - // First, visit all of the node's children. - int num_children = node_reader->get_num_children(); - if (node->has_selective_visibility()) { - int i = node->get_first_visible_child(); - while (i < num_children) { - CullTraverserData next_data(data, node_reader->get_child(i)); - decals = r_get_decals(next_data, decals); - i = node->get_next_visible_child(i); - } - - } else { - for (int i = num_children - 1; i >= 0; i--) { - CullTraverserData next_data(data, node_reader->get_child(i)); - decals = r_get_decals(next_data, decals); - } - } - - // Now, tack on any geoms within the node. - if (node->is_geom_node()) { - GeomNode *geom_node = DCAST(GeomNode, node); - GeomNode::Geoms geoms = geom_node->get_geoms(); - int num_geoms = geoms.get_num_geoms(); - _geoms_pcollector.add_level(num_geoms); - CPT(TransformState) net_transform = data.get_net_transform(this); - CPT(TransformState) modelview_transform = data.get_modelview_transform(this); - CPT(TransformState) internal_transform = _scene_setup->get_cs_transform()->compose(modelview_transform); - - for (int i = num_geoms - 1; i >= 0; i--) { - const Geom *geom = geoms.get_geom(i); - if (geom->is_empty()) { - continue; - } - - CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i)); - if (state->has_cull_callback() && !state->cull_callback(this, data)) { - // Cull. - continue; - } - - // Cull the Geom bounding volume against the view frustum - // and/or the cull planes. Don't bother unless we've got more - // than one Geom, since otherwise the bounding volume of the - // GeomNode is (probably) the same as that of the one Geom, - // and we've already culled against that. - if (num_geoms > 1) { - if (data._view_frustum != (GeometricBoundingVolume *)NULL) { - // Cull the individual Geom against the view frustum. - CPT(BoundingVolume) geom_volume = geom->get_bounds(); - const GeometricBoundingVolume *geom_gbv = - DCAST(GeometricBoundingVolume, geom_volume); - - int result = data._view_frustum->contains(geom_gbv); - if (result == BoundingVolume::IF_no_intersection) { - // Cull this Geom. - continue; - } - } - if (!data._cull_planes->is_empty()) { - // Also cull the Geom against the cull planes. - CPT(BoundingVolume) geom_volume = geom->get_bounds(); - const GeometricBoundingVolume *geom_gbv = - DCAST(GeometricBoundingVolume, geom_volume); - int result; - data._cull_planes->do_cull(result, state, geom_gbv); - if (result == BoundingVolume::IF_no_intersection) { - // Cull. - continue; - } - } - } - - CullableObject *next = decals; - decals = - new CullableObject(geom, state, net_transform, - modelview_transform, internal_transform); - decals->set_next(next); - } - } - } - - return decals; -} diff --git a/panda/src/pgraph/cullTraverser.h b/panda/src/pgraph/cullTraverser.h index 5100b0e7eb..4ec772076f 100644 --- a/panda/src/pgraph/cullTraverser.h +++ b/panda/src/pgraph/cullTraverser.h @@ -87,7 +87,7 @@ PUBLISHED: INLINE static void flush_level(); - void draw_bounding_volume(const BoundingVolume *vol, + void draw_bounding_volume(const BoundingVolume *vol, const TransformState *net_transform, const TransformState *modelview_transform) const; @@ -105,7 +105,7 @@ private: void show_bounds(CullTraverserData &data, bool tight); static PT(Geom) make_bounds_viz(const BoundingVolume *vol); PT(Geom) make_tight_bounds_viz(PandaNode *node) const; - static LVertex compute_point(const BoundingSphere *sphere, + static LVertex compute_point(const BoundingSphere *sphere, PN_stdfloat latitude, PN_stdfloat longitude); static CPT(RenderState) get_bounds_outer_viz_state(); static CPT(RenderState) get_bounds_inner_viz_state(); @@ -121,12 +121,11 @@ private: bool _has_tag_state_key; string _tag_state_key; CPT(RenderState) _initial_state; - bool _depth_offset_decals; PT(GeometricBoundingVolume) _view_frustum; CullHandler *_cull_handler; PortalClipper *_portal_clipper; bool _effective_incomplete_render; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -150,4 +149,4 @@ private: #endif - + diff --git a/panda/src/pgraph/cullableObject.I b/panda/src/pgraph/cullableObject.I index a5d7901dce..f9b32825e5 100644 --- a/panda/src/pgraph/cullableObject.I +++ b/panda/src/pgraph/cullableObject.I @@ -12,6 +12,7 @@ // //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// // Function: CullableObject::Constructor // Access: Public @@ -19,9 +20,7 @@ // filled in later. //////////////////////////////////////////////////////////////////// INLINE CullableObject:: -CullableObject() : - _fancy(false) -{ +CullableObject() { #ifdef DO_MEMORY_USAGE MemoryUsage::update_type(this, get_class_type()); #endif @@ -42,8 +41,7 @@ CullableObject(const Geom *geom, const RenderState *state, _state(state), _net_transform(net_transform), _modelview_transform(modelview_transform), - _internal_transform(scene_setup->get_cs_transform()->compose(modelview_transform)), - _fancy(false) + _internal_transform(scene_setup->get_cs_transform()->compose(modelview_transform)) { #ifdef DO_MEMORY_USAGE MemoryUsage::update_type(this, get_class_type()); @@ -65,20 +63,17 @@ CullableObject(const Geom *geom, const RenderState *state, _state(state), _net_transform(net_transform), _modelview_transform(modelview_transform), - _internal_transform(internal_transform), - _fancy(false) + _internal_transform(internal_transform) { #ifdef DO_MEMORY_USAGE MemoryUsage::update_type(this, get_class_type()); #endif } - //////////////////////////////////////////////////////////////////// // Function: CullableObject::Copy Constructor // Access: Public -// Description: Copies the CullableObject, but does not copy its -// children (decals). +// Description: Copies the CullableObject. //////////////////////////////////////////////////////////////////// INLINE CullableObject:: CullableObject(const CullableObject ©) : @@ -88,8 +83,7 @@ CullableObject(const CullableObject ©) : _state(copy._state), _net_transform(copy._net_transform), _modelview_transform(copy._modelview_transform), - _internal_transform(copy._internal_transform), - _fancy(false) + _internal_transform(copy._internal_transform) { #ifdef DO_MEMORY_USAGE MemoryUsage::update_type(this, get_class_type()); @@ -99,12 +93,10 @@ CullableObject(const CullableObject ©) : //////////////////////////////////////////////////////////////////// // Function: CullableObject::Copy Assignment Operator // Access: Public -// Description: Copies the CullableObject, but does not copy its -// children (decals). +// Description: Copies the CullableObject. //////////////////////////////////////////////////////////////////// INLINE void CullableObject:: operator = (const CullableObject ©) { - nassertv(!_fancy); _geom = copy._geom; _munger = copy._munger; _munged_data = copy._munged_data; @@ -112,29 +104,7 @@ operator = (const CullableObject ©) { _net_transform = copy._net_transform; _modelview_transform = copy._modelview_transform; _internal_transform = copy._internal_transform; -} - -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::is_fancy -// Access: Public -// Description: Returns true if the object has something fancy to it: -// decals, maybe, or a draw_callback, that prevents it -// from being rendered inline. -//////////////////////////////////////////////////////////////////// -INLINE bool CullableObject:: -is_fancy() const { - return _fancy; -} - -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::has_decals -// Access: Public -// Description: Returns true if the object has decals associated with -// it. -//////////////////////////////////////////////////////////////////// -INLINE bool CullableObject:: -has_decals() const { - return _fancy && (_next != (CullableObject *)NULL); + _draw_callback = copy._draw_callback; } //////////////////////////////////////////////////////////////////// @@ -146,8 +116,17 @@ has_decals() const { //////////////////////////////////////////////////////////////////// INLINE void CullableObject:: draw(GraphicsStateGuardianBase *gsg, bool force, Thread *current_thread) { - if (_fancy) { - draw_fancy(gsg, force, current_thread); + if (_draw_callback != (CallbackObject *)NULL) { + // It has a callback associated. + gsg->clear_before_callback(); + gsg->set_state_and_transform(_state, _internal_transform); + GeomDrawCallbackData cbdata(this, gsg, force); + _draw_callback->do_callback(&cbdata); + if (cbdata.get_lost_state()) { + // Tell the GSG to forget its state. + gsg->clear_state_and_transform(); + } + // Now the callback has taken care of drawing. } else { nassertv(_geom != (Geom *)NULL); gsg->set_state_and_transform(_state, _internal_transform); @@ -184,43 +163,7 @@ request_resident() const { //////////////////////////////////////////////////////////////////// INLINE void CullableObject:: set_draw_callback(CallbackObject *draw_callback) { - make_fancy(); - if (draw_callback != _draw_callback) { - if (_draw_callback != (CallbackObject *)NULL) { - unref_delete(_draw_callback); - } - _draw_callback = draw_callback; - if (_draw_callback != (CallbackObject *)NULL) { - _draw_callback->ref(); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::set_next -// Access: Public -// Description: Sets the next object in the decal chain. This next -// object will be destructed when this object destructs. -//////////////////////////////////////////////////////////////////// -INLINE void CullableObject:: -set_next(CullableObject *next) { - make_fancy(); - nassertv(_next == (CullableObject *)NULL); - _next = next; -} - -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::get_next -// Access: Public -// Description: Returns the next object in the decal chain, or NULL -// for the end of the chain. -//////////////////////////////////////////////////////////////////// -INLINE CullableObject *CullableObject:: -get_next() const { - if (_fancy) { - return _next; - } - return NULL; + _draw_callback = draw_callback; } //////////////////////////////////////////////////////////////////// @@ -233,23 +176,6 @@ flush_level() { _sw_sprites_pcollector.flush_level(); } -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::make_fancy -// Access: Private -// Description: Elevates this object to "fancy" status. This means -// that the additional pointers, like _next and -// _draw_callback, have meaningful values and should be -// examined. -//////////////////////////////////////////////////////////////////// -INLINE void CullableObject:: -make_fancy() { - if (!_fancy) { - _fancy = true; - _draw_callback = NULL; - _next = NULL; - } -} - //////////////////////////////////////////////////////////////////// // Function: CullableObject::draw_inline // Access: Private @@ -266,7 +192,7 @@ draw_inline(GraphicsStateGuardianBase *gsg, bool force, Thread *current_thread) //////////////////////////////////////////////////////////////////// // Function: CullableObject::SortPoints::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE CullableObject::SortPoints:: SortPoints(const CullableObject::PointData *array) : @@ -288,7 +214,7 @@ operator () (unsigned short a, unsigned short b) const { //////////////////////////////////////////////////////////////////// // Function: CullableObject::SourceFormat::operator < // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE bool CullableObject::SourceFormat:: operator < (const CullableObject::SourceFormat &other) const { diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index b76fc6b445..6d5e2d2e27 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -30,7 +30,6 @@ #include "geomTriangles.h" #include "light.h" #include "lightMutexHolder.h" -#include "geomDrawCallbackData.h" CullableObject::FormatMap CullableObject::_format_map; LightMutex CullableObject::_format_lock; @@ -180,41 +179,13 @@ munge_geom(GraphicsStateGuardianBase *gsg, #endif } - if (_fancy) { - // Only check the _next pointer if the _fancy flag is set. - if (_next != (CullableObject *)NULL) { - if (_next->_state != (RenderState *)NULL) { - _next->munge_geom(gsg, gsg->get_geom_munger(_next->_state, current_thread), - traverser, force); - } else { - _next->munge_geom(gsg, munger, traverser, force); - } - } - } - return true; } -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::Destructor -// Access: Public -// Description: Automatically deletes the whole chain of these things. -//////////////////////////////////////////////////////////////////// -CullableObject:: -~CullableObject() { - if (_fancy) { - // Only check the _next pointer if the _fancy flag is set. - if (_next != (CullableObject *)NULL) { - delete _next; - } - set_draw_callback(NULL); - } -} - //////////////////////////////////////////////////////////////////// // Function: CullableObject::output // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// void CullableObject:: output(ostream &out) const { @@ -225,7 +196,6 @@ output(ostream &out) const { } } - //////////////////////////////////////////////////////////////////// // Function: CullableObject::munge_points_to_quads // Access: Private @@ -642,7 +612,7 @@ munge_texcoord_light_vector(const CullTraverser *traverser, bool force) { return true; } - if (!_munged_data->has_column(InternalName::get_vertex()) || + if (!_munged_data->has_column(InternalName::get_vertex()) || !_munged_data->has_column(InternalName::get_normal())) { // No vertex or normal; can't compute light vector. return true; @@ -775,97 +745,15 @@ get_flash_hardware_state() { return flash_hardware_state; } -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::draw_fancy -// Access: Private -// Description: Something fancy about this object. Draw it properly. -//////////////////////////////////////////////////////////////////// -void CullableObject:: -draw_fancy(GraphicsStateGuardianBase *gsg, bool force, - Thread *current_thread) { - nassertv(_fancy); - if (_draw_callback != (CallbackObject *)NULL) { - // It has a callback associated. - gsg->clear_before_callback(); - gsg->set_state_and_transform(_state, _internal_transform); - GeomDrawCallbackData cbdata(this, gsg, force); - _draw_callback->do_callback(&cbdata); - if (cbdata.get_lost_state()) { - // Tell the GSG to forget its state. - gsg->clear_state_and_transform(); - } - // Now the callback has taken care of drawing. - - } else if (_next != (CullableObject *)NULL) { - // It has decals. - draw_with_decals(gsg, force, current_thread); - - } else { - // Huh, nothing fancy after all. Somehow the _fancy flag got set - // incorrectly; that's a bug. - gsg->set_state_and_transform(_state, _internal_transform); - draw_inline(gsg, force, current_thread); - nassertv(false); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::draw_with_decals -// Access: Private -// Description: Draws the current CullableObject, assuming it has -// attached decals. -//////////////////////////////////////////////////////////////////// -void CullableObject:: -draw_with_decals(GraphicsStateGuardianBase *gsg, bool force, - Thread *current_thread) { - nassertv(_fancy && _next != (CullableObject *)NULL); - // We draw with a three-step process. - - // First, render all of the base geometry for the first pass. - CPT(RenderState) state = gsg->begin_decal_base_first(); - - CullableObject *base = this; - while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) { - gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform); - base->draw_inline(gsg, force, current_thread); - - base = base->_next; - } - - if (base != (CullableObject *)NULL) { - // Now, draw all the decals. - state = gsg->begin_decal_nested(); - - CullableObject *decal = base->_next; - while (decal != (CullableObject *)NULL) { - gsg->set_state_and_transform(decal->_state->compose(state), decal->_internal_transform); - decal->draw_inline(gsg, force, current_thread); - decal = decal->_next; - } - } - - // And now, re-draw the base geometry, if required. - state = gsg->begin_decal_base_second(); - if (state != (const RenderState *)NULL) { - base = this; - while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) { - gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform); - base->draw_inline(gsg, force, current_thread); - - base = base->_next; - } - } -} - //////////////////////////////////////////////////////////////////// // Function: CullableObject::SourceFormat::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// CullableObject::SourceFormat:: SourceFormat(const GeomVertexFormat *format, bool sprite_texcoord) : _format(format), - _sprite_texcoord(sprite_texcoord) + _sprite_texcoord(sprite_texcoord) { _retransform_sprites = retransform_sprites; } diff --git a/panda/src/pgraph/cullableObject.h b/panda/src/pgraph/cullableObject.h index 19a8731aca..7d4db8fd0d 100644 --- a/panda/src/pgraph/cullableObject.h +++ b/panda/src/pgraph/cullableObject.h @@ -32,17 +32,17 @@ #include "sceneSetup.h" #include "lightMutex.h" #include "callbackObject.h" +#include "geomDrawCallbackData.h" class CullTraverser; //////////////////////////////////////////////////////////////////// // Class : CullableObject // Description : The smallest atom of cull. This is normally just a -// Geom and its associated state, but it also represent -// a number of Geoms to be drawn together, with a number -// of Geoms decalled onto them. +// Geom and its associated state, but it also contain +// a draw callback. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA_PGRAPH CullableObject +class EXPCL_PANDA_PGRAPH CullableObject #ifdef DO_MEMORY_USAGE : public ReferenceCount // We inherit from ReferenceCount just to get the memory type tracking that MemoryUsage provides. #endif // DO_MEMORY_USAGE @@ -57,13 +57,10 @@ public: const TransformState *net_transform, const TransformState *modelview_transform, const TransformState *internal_transform); - + INLINE CullableObject(const CullableObject ©); INLINE void operator = (const CullableObject ©); - INLINE bool is_fancy() const; - INLINE bool has_decals() const; - bool munge_geom(GraphicsStateGuardianBase *gsg, GeomMunger *munger, const CullTraverser *traverser, bool force); @@ -74,11 +71,8 @@ public: INLINE static void flush_level(); INLINE void set_draw_callback(CallbackObject *draw_callback); - INLINE void set_next(CullableObject *next); - INLINE CullableObject *get_next() const; public: - ~CullableObject(); ALLOC_DELETED_CHAIN(CullableObject); void output(ostream &out) const; @@ -91,17 +85,9 @@ public: CPT(TransformState) _net_transform; CPT(TransformState) _modelview_transform; CPT(TransformState) _internal_transform; + PT(CallbackObject) _draw_callback; private: - bool _fancy; - - // Fancy things below. These pointers are only meaningful if - // _fancy, above, is true. - CallbackObject *_draw_callback; - CullableObject *_next; // for decals - -private: - INLINE void make_fancy(); bool munge_points_to_quads(const CullTraverser *traverser, bool force); bool munge_texcoord_light_vector(const CullTraverser *traverser, bool force); @@ -110,10 +96,6 @@ private: INLINE void draw_inline(GraphicsStateGuardianBase *gsg, bool force, Thread *current_thread); - void draw_fancy(GraphicsStateGuardianBase *gsg, bool force, - Thread *current_thread); - void draw_with_decals(GraphicsStateGuardianBase *gsg, bool force, - Thread *current_thread); private: // This class is used internally by munge_points_to_quads(). From 3831d445761721f897c11bc993e78a932a622d7e Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 2 Jan 2015 22:38:02 +0100 Subject: [PATCH 12/83] Fix issue with resetting ScissorAttrib state https://www.panda3d.org/forums/viewtopic.php?f=1&t=17505 --- .../glstuff/glGraphicsStateGuardian_src.cxx | 61 ++++++++++++++++--- .../src/glstuff/glGraphicsStateGuardian_src.h | 2 + 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 86a0a3672a..222ae9d977 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -316,6 +316,7 @@ CLP(GraphicsStateGuardian)(GraphicsEngine *engine, GraphicsPipe *pipe) : _force_flush = gl_force_flush; _scissor_enabled = false; + _scissor_attrib_active = false; #ifdef DO_PSTATS if (gl_finish) { @@ -2468,6 +2469,8 @@ prepare_display_region(DisplayRegionPipelineReader *dr) { _draw_buffer_type |= _current_properties->get_aux_mask(); set_draw_buffer(_draw_buffer_type); + int count = dr->get_num_regions(); + if (dr->get_scissor_enabled()) { if (GLCAT.is_spam()) { GLCAT.spam() @@ -2475,6 +2478,7 @@ prepare_display_region(DisplayRegionPipelineReader *dr) { } glEnable(GL_SCISSOR_TEST); _scissor_enabled = true; + _scissor_array.resize(count); } else { if (GLCAT.is_spam()) { GLCAT.spam() @@ -2482,27 +2486,35 @@ prepare_display_region(DisplayRegionPipelineReader *dr) { } glDisable(GL_SCISSOR_TEST); _scissor_enabled = false; + _scissor_array.clear(); } + _scissor_attrib_active = false; + #ifndef OPENGLES if (_supports_viewport_arrays) { - int count = dr->get_num_regions(); - GLfloat *viewports = (GLfloat *)alloca(sizeof(GLfloat) * 4 * count); - GLint *scissors = (GLint *)alloca(sizeof(GLint) * 4 * count); + GLfloat *viewports = (GLfloat *)alloca(sizeof(GLfloat) * 4 * count); + + // We store the scissor regions in a vector since we may need + // to switch back to it in do_issue_scissor. for (int i = 0; i < count; ++i) { - GLint *sr = scissors + i * 4; + LVecBase4i sr; dr->get_region_pixels(i, sr[0], sr[1], sr[2], sr[3]); GLfloat *vr = viewports + i * 4; vr[0] = (GLfloat) sr[0]; vr[1] = (GLfloat) sr[1]; vr[2] = (GLfloat) sr[2]; vr[3] = (GLfloat) sr[3]; + if (_scissor_enabled) { + _scissor_array[i] = sr; + } } _glViewportArrayv(0, count, viewports); - if (dr->get_scissor_enabled()) { - _glScissorArrayv(0, count, scissors); + if (_scissor_enabled) { + _glScissorArrayv(0, count, _scissor_array[0].get_data()); } + if (GLCAT.is_spam()) { GLCAT.spam() << "glViewportArrayv(0, " << count << ", [\n"; @@ -2511,12 +2523,12 @@ prepare_display_region(DisplayRegionPipelineReader *dr) { GLCAT.spam(false) << vr[0] << ", " << vr[1] << ", " << vr[2] << ", " << vr[3] << ",\n"; } GLCAT.spam(false) << "])\n"; - if (dr->get_scissor_enabled()) { + if (_scissor_enabled) { GLCAT.spam() << "glScissorArrayv(0, " << count << ", [\n"; for (int i = 0; i < count; ++i) { - GLint *sr = scissors + i * 4; - GLCAT.spam(false) << sr[0] << ", " << sr[1] << ", " << sr[2] << ", " << sr[3] << ",\n"; + const LVecBase4i &sr = _scissor_array[i]; + GLCAT.spam(false) << sr << ",\n"; } } GLCAT.spam(false) << "])\n"; @@ -2526,9 +2538,13 @@ prepare_display_region(DisplayRegionPipelineReader *dr) { #endif // OPENGLES { glViewport(x, y, width, height); - if (dr->get_scissor_enabled()) { + if (_scissor_enabled) { glScissor(x, y, width, height); + + _scissor_array.resize(1); + _scissor_array[0].set(x, y, width, height); } + if (GLCAT.is_spam()) { GLCAT.spam() << "glViewport(" << x << ", " << y << ", " << width << ", " << height << ")\n"; @@ -11984,5 +12000,30 @@ do_issue_scissor() { << "glScissor(" << x << ", " << y << ", " << width << ", " << height << ")\n"; } glScissor(x, y, width, height); + + _scissor_attrib_active = true; + + } else if (_scissor_attrib_active) { + _scissor_attrib_active = false; + + if (_scissor_array.size() > 0) { + // Scissoring is enabled on the display region. + // Revert to the scissor state specified in the DisplayRegion. + if (_supports_viewport_arrays) { + _glScissorArrayv(0, _scissor_array.size(), _scissor_array[0].get_data()); + } else { + const LVecBase4i sr = _scissor_array[0]; + glScissor(sr[0], sr[1], sr[2], sr[3]); + } + + } else if (_scissor_enabled) { + // The display region had no scissor enabled. Disable scissoring. + if (GLCAT.is_spam()) { + GLCAT.spam() + << "glDisable(GL_SCISSOR_TEST)\n"; + } + glDisable(GL_SCISSOR_TEST); + _scissor_enabled = false; + } } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index f89a84600b..23786533e6 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -550,6 +550,8 @@ protected: bool _point_perspective; bool _vertex_blending_enabled; bool _scissor_enabled; + bool _scissor_attrib_active; + epvector _scissor_array; #ifndef OPENGLES_1 PT(Shader) _current_shader; From 33ef39b7dbb2ae069c7d4ee2f9fe70617fa8dd69 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 3 Jan 2015 16:33:19 +0100 Subject: [PATCH 13/83] Remove modules that seem obsolete from direct tree --- direct/src/autorestart/Sources.pp | 8 - direct/src/autorestart/autorestart.c | 901 --------------- direct/src/directscripts/Doxyfile.python | 3 +- direct/src/heapq/Sources.pp | 29 - direct/src/heapq/heapq.cxx | 240 ---- direct/src/http/LandingPage.py | 2 +- direct/src/http/LandingPageHTML.py | 2 +- direct/src/http/WebRequest.py | 2 +- direct/src/pyinst/Builder.py | 504 --------- direct/src/pyinst/Sources.pp | 0 direct/src/pyinst/__init__.py | 0 direct/src/pyinst/archive.py | 246 ---- direct/src/pyinst/archive_rt.py | 226 ---- direct/src/pyinst/archivebuilder.py | 81 -- direct/src/pyinst/bindepend.py | 169 --- direct/src/pyinst/carchive.py | 204 ---- direct/src/pyinst/carchive_rt.py | 157 --- direct/src/pyinst/finder.py | 178 --- direct/src/pyinst/icon.py | 138 --- direct/src/pyinst/imputil.py | 487 -------- direct/src/pyinst/installutils.py | 91 -- direct/src/pyinst/ltoc.py | 85 -- direct/src/pyinst/mkarchive.py | 42 - direct/src/pyinst/modulefinder.py | 436 ------- direct/src/pyinst/resource.py | 317 ------ direct/src/pyinst/tocfilter.py | 131 --- direct/src/showbase/ElementTree.py | 1251 --------------------- direct/src/showbase/HTMLTree.py | 2 +- direct/src/showbase/PythonUtil.py | 1 - direct/src/test/ModelScreenShot.py | 71 -- direct/src/test/ModelScreenShotGlobals.py | 6 - direct/src/test/Sources.pp | 0 direct/src/test/__init__.py | 0 33 files changed, 5 insertions(+), 6005 deletions(-) delete mode 100644 direct/src/autorestart/Sources.pp delete mode 100644 direct/src/autorestart/autorestart.c delete mode 100755 direct/src/heapq/Sources.pp delete mode 100755 direct/src/heapq/heapq.cxx delete mode 100644 direct/src/pyinst/Builder.py delete mode 100644 direct/src/pyinst/Sources.pp delete mode 100644 direct/src/pyinst/__init__.py delete mode 100644 direct/src/pyinst/archive.py delete mode 100644 direct/src/pyinst/archive_rt.py delete mode 100644 direct/src/pyinst/archivebuilder.py delete mode 100644 direct/src/pyinst/bindepend.py delete mode 100644 direct/src/pyinst/carchive.py delete mode 100644 direct/src/pyinst/carchive_rt.py delete mode 100644 direct/src/pyinst/finder.py delete mode 100644 direct/src/pyinst/icon.py delete mode 100644 direct/src/pyinst/imputil.py delete mode 100644 direct/src/pyinst/installutils.py delete mode 100644 direct/src/pyinst/ltoc.py delete mode 100644 direct/src/pyinst/mkarchive.py delete mode 100644 direct/src/pyinst/modulefinder.py delete mode 100644 direct/src/pyinst/resource.py delete mode 100644 direct/src/pyinst/tocfilter.py delete mode 100755 direct/src/showbase/ElementTree.py delete mode 100755 direct/src/test/ModelScreenShot.py delete mode 100644 direct/src/test/ModelScreenShotGlobals.py delete mode 100644 direct/src/test/Sources.pp delete mode 100644 direct/src/test/__init__.py diff --git a/direct/src/autorestart/Sources.pp b/direct/src/autorestart/Sources.pp deleted file mode 100644 index a85fc78a17..0000000000 --- a/direct/src/autorestart/Sources.pp +++ /dev/null @@ -1,8 +0,0 @@ -#begin bin_target - // This program only compiles on Unix. - #define BUILD_TARGET $[UNIX_PLATFORM] - #define C++FLAGS -DWITHIN_PANDA - - #define TARGET autorestart - #define SOURCES autorestart.c -#end bin_target diff --git a/direct/src/autorestart/autorestart.c b/direct/src/autorestart/autorestart.c deleted file mode 100644 index bfcad109de..0000000000 --- a/direct/src/autorestart/autorestart.c +++ /dev/null @@ -1,901 +0,0 @@ -/* Filename: autorestart.c - * Created by: drose (05Sep02) - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifdef WITHIN_PANDA -#include "dtoolbase.h" -#endif - -#include -#include -#include -#include /* for strerror */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_LIBCURL -#include -#endif - -/* The maximum number of seconds to wait for a process to go away - after issuing SIGTERM. This is only used in watchdog mode, when -W - is provided on the command line. */ -#define MAX_WAITTERM_SEC 10 - -char **params = NULL; -char *logfile_name = NULL; -char *pidfile_name = NULL; -int dont_fork = 0; -char *watchdog_url = NULL; -int watchdog_start_sec = 0; -int watchdog_cycle_sec = 0; -int watchdog_timeout_sec = 0; -char *startup_username = NULL; -char *startup_groupname = NULL; -char *startup_chdir = NULL; -int logfile_fd = -1; -int stop_on_terminate = 0; -int stop_always = 0; -char *respawn_script = NULL; -int respawn_count_time = 0; - -/* If requested, delay these many seconds between restart attempts */ -int respawn_delay_time = 5; - - -/* We shouldn't respawn more than (spam_respawn_count - 1) times over - spam_respawn_time seconds. */ -int spam_respawn_count = 5; -int spam_respawn_time = 60; -int spam_restart_delay_time = 600; /* Optionally, do not exit if we spam too much; simply sleep for this many seconds*/ - - - -pid_t child_pid = 0; -pid_t watchdog_pid = 0; - -#define TIME_BUFFER_SIZE 128 - -/* Keep track of the frequency with which we respawn, so we can report - this to our respawn script. */ -typedef struct respawn_record_struct { - time_t _time; - struct respawn_record_struct *_next; -} respawn_record; - -respawn_record *respawns = NULL; - -int -record_respawn(time_t now) { - /* Records the respawning event in the respawn_record, and returns - the number of respawns in the last respawn_count_time - interval. */ - respawn_record *rec; - respawn_record *next; - int count; - - if (respawn_count_time <= 0) { - /* We're not tracking respawns if respawn_count_time is 0. */ - return 0; - } - - rec = (respawn_record *)malloc(sizeof(respawn_record)); - rec->_time = now; - rec->_next = respawns; - respawns = rec; - - /* Now walk through the rest of the list and count up the number of - respawn events until we reach a record more than - respawn_count_time seconds old. */ - count = 0; - while (rec->_next != NULL && - (now - rec->_time) <= respawn_count_time) { - rec = rec->_next; - count++; - } - - /* The remaining respawn records get removed. */ - next = rec->_next; - rec->_next = NULL; - while (next != NULL) { - rec = next; - next = rec->_next; - free(rec); - } - - return count; -} - -void -invoke_respawn_script(time_t now) { - char buffer[32]; - char *new_command; - int new_command_length; - - /* The process is about to be respawned; run the script that we were - given on the command line. */ - if (respawn_count_time <= 0) { - /* We're not counting respawn times, so just run the script - directly. */ - system(respawn_script); - - } else { - /* We are counting respawn times, so append that information as a - parameter to the command. */ - sprintf(buffer, " %d", record_respawn(now)); - new_command_length = strlen(respawn_script) + strlen(buffer); - new_command = (char *)malloc(new_command_length + 1); - strcpy(new_command, respawn_script); - strcat(new_command, buffer); - assert(strlen(new_command) == new_command_length); - - system(new_command); - - free(new_command); - } -} - -/* A callback function passed to libcurl that simply discards the data - retrieved from the server. We only care about the HTTP status. */ -size_t -watchdog_bitbucket(void *ptr, size_t size, size_t nmemb, void *userdata) { - return size * nmemb; -} - -/* Waits up to timeout_ms for a particular child to terminate. - Returns 0 if the timeout expires. */ -pid_t -waitpid_timeout(pid_t child_pid, int *status_ptr, int timeout_ms) { - pid_t result; - struct timeval now, tv; - int now_ms, start_ms, elapsed_ms; - - gettimeofday(&now, NULL); - start_ms = now.tv_sec * 1000 + now.tv_usec / 1000; - - result = waitpid(child_pid, status_ptr, WNOHANG); - while (result == 0) { - gettimeofday(&now, NULL); - now_ms = now.tv_sec * 1000 + now.tv_usec / 1000; - elapsed_ms = now_ms - start_ms; - - if (elapsed_ms > timeout_ms) { - /* Tired of waiting. */ - return 0; - } - - /* Yield the timeslice and wait some more. */ - tv.tv_sec = 0; - tv.tv_usec = 1; - select(0, NULL, NULL, NULL, &tv); - result = waitpid(child_pid, status_ptr, WNOHANG); - } - if (result == -1) { - perror("waitpid"); - } - - return result; -} - - -/* Poll the requested URL until a failure or timeout occurs, or until - the child terminates on its own. Returns 1 on HTTP failure or - timeout, 0 on self-termination. In either case, *status_ptr is - filled in with the status value returned by waitpid().*/ -int -do_watchdog(int *status_ptr) { -#ifndef HAVE_LIBCURL - fprintf(stderr, "Cannot watchdog; no libcurl available.\n"); - return 0; -#else /* HAVE_LIBCURL */ - - CURL *curl; - CURLcode res; - char error_buffer[CURL_ERROR_SIZE]; - pid_t wresult; - - // Before we start polling the URL, wait at least start milliseconds. - wresult = waitpid_timeout(child_pid, status_ptr, watchdog_start_sec * 1000); - if (wresult == child_pid) { - // The child terminated on its own before we got started. - return 0; - } - - curl = curl_easy_init(); - if (!curl) { - fprintf(stderr, "Cannot watchdog; curl failed to init.\n"); - return 0; - } - - curl_easy_setopt(curl, CURLOPT_URL, watchdog_url); - /*curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);*/ - curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, watchdog_timeout_sec * 1000); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, watchdog_bitbucket); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "autorestart"); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1); - curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1); - - res = curl_easy_perform(curl); - while (res == 0) { - /* 0: The HTTP request finished successfully (but might or might - not have returned an error code like a 404). */ - long http_response = 0; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response); - if ((http_response / 100) != 2) { - /* Anything in the 200 range is deemed success. Anything else - is deemed failure. */ - fprintf(stderr, "%s returned %ld\n", watchdog_url, http_response); - break; - } - - wresult = waitpid_timeout(child_pid, status_ptr, watchdog_cycle_sec * 1000); - if (wresult == child_pid) { - /* The process terminated on its own. Return 0 to indicate this. */ - return 0; - } - - res = curl_easy_perform(curl); - } - - curl_easy_cleanup(curl); - - /* Failed to retrieve the watchdog URL. */ - if (res != 0) { - fprintf(stderr, "Failed to contact %s: %s\n", watchdog_url, error_buffer); - } - - /* Kill the child process and wait for it to go away. */ - kill(child_pid, SIGTERM); - - pid_t result = waitpid_timeout(child_pid, status_ptr, MAX_WAITTERM_SEC * 1000); - if (result != child_pid) { - if (result == -1) { - perror("waitpid"); - } else { - /* SIGTERM didn't make the process die. Try SIGKILL. */ - fprintf(stderr, "Force-killing child process\n"); - kill(child_pid, SIGKILL); - result = waitpid_timeout(child_pid, status_ptr, MAX_WAITTERM_SEC * 1000); - if (result == -1) { - perror("waitpid"); - } - } - } - - /* Return 1 to indicate we killed the child due to an HTTP error. */ - return 1; -#endif /* HAVE_LIBCURL */ -} - -void -exec_process() { - /* First, output the command line to the log file. */ - char **p; - for (p = params; *p != NULL; ++p) { - fprintf(stderr, "%s ", *p); - } - fprintf(stderr, "\n"); - execvp(params[0], params); - fprintf(stderr, "Cannot exec %s: %s\n", params[0], strerror(errno)); - - /* Exit with a status of 0, to indicate to the parent process that - we should stop. */ - exit(0); -} - -int -spawn_process() { - /* Spawns the child process. Returns true if the process terminated - by itself and should be respawned, false if it was explicitly - killed (or some other error condition exists), and it should not - respawn any more. */ - pid_t wresult; - int status; - int error_exit; - - child_pid = fork(); - if (child_pid < 0) { - /* Fork error. */ - perror("fork"); - return 0; - } - - if (child_pid == 0) { - /* Child. Exec the process. */ - fprintf(stderr, "Child pid is %d.\n", getpid()); - exec_process(); - /* Shouldn't get here. */ - exit(1); - } - - /* Parent. */ - - error_exit = 0; - - if (watchdog_url != NULL) { - /* If we're watchdogging, then go check the URL. This function - won't return until the URL fails or the child exits. */ - error_exit = do_watchdog(&status); - - } else { - /* If we're not watchdogging, then just wait for the child to - terminate, and diagnose the reason. */ - wresult = waitpid(child_pid, &status, 0); - if (wresult < 0) { - perror("waitpid"); - return 0; - } - } - - /* Now that we've returned from waitpid, clear the child pid number - so our signal handler doesn't get too confused. */ - child_pid = 0; - - if (error_exit) { - /* An HTTP error exit is a reason to respawn. */ - return 1; - - } else if (WIFSIGNALED(status)) { - int signal = WTERMSIG(status); - fprintf(stderr, "\nprocess caught signal %d.\n\n", signal); - /* A signal exit is a reason to respawn unless the signal is TERM - or KILL. */ - return !stop_on_terminate || (signal != SIGTERM && signal != SIGKILL); - - } else { - int exit_status = WEXITSTATUS(status); - fprintf(stderr, "\nprocess exited with status %d.\n\n", WEXITSTATUS(status)); - /* Normal exit is a reason to respawn if the status indicates failure. */ - return !stop_on_terminate || (exit_status != 0); - } -} - -void -sigterm_handler() { - pid_t wresult; - int status; - time_t now; - char time_buffer[TIME_BUFFER_SIZE]; - - now = time(NULL); - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - - fprintf(stderr, "\nsigterm caught at %s; shutting down.\n", time_buffer); - if (child_pid == 0) { - fprintf(stderr, "no child process.\n\n"); - - } else { - kill(child_pid, SIGTERM); - - wresult = waitpid(child_pid, &status, 0); - if (wresult < 0) { - perror("waitpid"); - } else { - fprintf(stderr, "child process terminated.\n\n"); - } - } - exit(1); -} - -void -sighup_handler() { - time_t now; - char time_buffer[TIME_BUFFER_SIZE]; - - now = time(NULL); - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - - fprintf(stderr, "\nsighup caught at %s.\n", time_buffer); - if (child_pid == 0) { - fprintf(stderr, "no child process.\n\n"); - - } else { - kill(child_pid, SIGHUP); - } -} - -void -sigalarm_handler() { - fprintf(stderr, "sleep epoch was complete.\n"); -} - -void -do_autorestart() { - char time_buffer[TIME_BUFFER_SIZE]; - time_t now; - time_t *spam_respawn = NULL; - int sri, num_sri; - struct sigaction sa; - - if (spam_respawn_count > 1) { - spam_respawn = (time_t *)malloc(sizeof(time_t) * spam_respawn_count); - } - - /* Make our process its own process group. */ - setpgid(0, 0); - - /* Set up a signal handler to trap SIGTERM. */ - sa.sa_handler = sigterm_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (sigaction(SIGTERM, &sa, NULL) < 0) { - perror("sigaction"); - } - - /* Set up a signal handler to trap SIGHUP. We pass this into the - child. */ - sa.sa_handler = sighup_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (sigaction(SIGHUP, &sa, NULL) < 0) { - perror("sigaction"); - } - - if (logfile_fd >= 0) { - /* If we have a logfile, dup it onto stdout and stderr. */ - dup2(logfile_fd, STDOUT_FILENO); - dup2(logfile_fd, STDERR_FILENO); - close(logfile_fd); - } - - /* Make sure stdin is closed. */ - close(STDIN_FILENO); - - now = time(NULL); - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - fprintf(stderr, "autorestart begun at %s.\n", time_buffer); - - if (pidfile_name != NULL) { - unlink(pidfile_name); - FILE *pidfile = fopen(pidfile_name, "w"); - if (pidfile == NULL) { - fprintf(stderr, "Could not write pidfile %s\n", pidfile_name); - } else { - fprintf(pidfile, "%d\n", getpid()); - fclose(pidfile); - } - } - - sri = 1; - num_sri = 1; - if (spam_respawn_count > 1) { - spam_respawn[1] = now; - } - - while (spawn_process()) { - now = time(NULL); - - if (respawn_script != NULL) { - invoke_respawn_script(now); - } - - if (respawn_delay_time) { - sleep(respawn_delay_time); - } - - /* Make sure we're not respawning too fast. */ - if (spam_respawn_count > 1) { - sri = (sri + 1) % spam_respawn_count; - spam_respawn[sri] = now; - if (num_sri < spam_respawn_count) { - num_sri++; - } else { - time_t last = spam_respawn[(sri + 1) % spam_respawn_count]; - if (now - last < spam_respawn_time) - { - if(!spam_restart_delay_time) - { - fprintf(stderr, "respawning too fast, giving up.\n"); - break; - } - else - { - num_sri = 1; /* reset num_sri */ - fprintf(stderr, "respawning too fast, will sleep for %d seconds.\n", spam_restart_delay_time); - signal (SIGALRM, sigalarm_handler); - alarm(spam_restart_delay_time); - pause(); - signal (SIGALRM, SIG_IGN); - } - } - } - } - - if (stop_always) { - fprintf(stderr, "instructed to not autorestart, exiting.\n"); - break; - } - - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - fprintf(stderr, "respawning at %s.\n", time_buffer); - } - - now = time(NULL); - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - fprintf(stderr, "autorestart terminated at %s.\n", time_buffer); - exit(0); -} - -void -double_fork() { - pid_t child, grandchild, wresult; - int status; - - /* Fork once, then again, to disassociate the child from the command - shell process group. */ - child = fork(); - if (child < 0) { - /* Failure to fork. */ - perror("fork"); - exit(1); - } - - if (child == 0) { - /* Child. Fork again. */ - grandchild = fork(); - if (grandchild < 0) { - perror("fork"); - exit(1); - } - - if (grandchild == 0) { - /* Grandchild. Begin useful work. */ - do_autorestart(); - /* Shouldn't get here. */ - exit(1); - } - - /* Child. Report the new pid, then terminate gracefully. */ - fprintf(stderr, "Spawned, monitoring pid is %d.\n", grandchild); - exit(0); - } - - /* Parent. Wait for the child to terminate, then return. */ - wresult = waitpid(child, &status, 0); - if (wresult < 0) { - perror("waitpid"); - exit(1); - } - - if (!WIFEXITED(status)) { - if (WIFSIGNALED(status)) { - fprintf(stderr, "child caught signal %d unexpectedly.\n", WTERMSIG(status)); - } else { - fprintf(stderr, "child exited with status %d.\n", WEXITSTATUS(status)); - } - exit(1); - } -} - -void -usage() { - fprintf(stderr, - "\n" - "autorestart [opts] program [args . . . ]\n" - "autorestart -h\n\n"); -} - -void -help() { - usage(); - fprintf(stderr, - "This program is used to run a program as a background task and\n" - "automatically restart it should it terminate for any reason other\n" - "than normal exit or explicit user kill.\n\n" - - "If the program exits with a status of 0, indicating successful\n" - "completion, it is not restarted.\n\n" - - "If the program is terminated via a TERM or KILL signal (e.g. via\n" - "kill [pid] or kill -9 [pid]), it is assumed the user meant for the\n" - "process to stop, and it is not restarted.\n\n" - - "Options:\n\n" - - " -l logfilename\n" - " Route stdout and stderr from the child process into the indicated\n" - " log file.\n\n" - - " -p pidfilename\n" - " Write the pid of the monitoring process to the indicated pidfile.\n\n" - " -f\n" - " Don't fork autorestart itself; run it as a foreground process. \n" - " (Normally, autorestart forks itself to run as a background process.)\n" - " In this case, the file named by -p is not used.\n\n" - - " -n\n" - " Do not attempt to restart the process under any circumstance.\n" - " The program can still be used to execute a script on abnormal\n" - " process termination.\n\n" - - " -t\n" - " Stop on terminate: don't restart if the child process exits\n" - " normally or is killed with a SIGTERM. With this flag, the\n" - " child process will be restarted only if it exits with a\n" - " non-zero exit status, or if it is killed with a signal other\n" - " than SIGTERM. Without this flag, the default behavior is to\n" - " restart the child process if it exits for any reason.\n\n" - - " -r count,secs,sleep\n" - " Sleep 'sleep' seconds if the process respawns 'count' times\n" - " within 'secs' seconds. This is designed to prevent respawning\n" - " from using too many system resources if something is wrong with\n" - " the child process. The default value is %d,%d,%d. Use -r 0,0,0\n" - " to disable this feature.\n\n" - - " -s \"command\"\n" - " Run the indicated command or script each time the process is\n" - " respawned, using the system() call. This may be useful, for\n" - " instance, to notify an operator via email each time a respawn\n" - " occurs. If -c is also specified, an additional parameter will\n" - " be appended to the command, indicating the number of times the\n" - " respawn has occurred in the given time interval.\n\n" - - " -c secs\n" - " Specifies the number of seconds over which to count respawn events\n" - " for the purposes of passing an argument to the script named with\n" - " -s.\n\n" - - " -d secs\n" - " Specifies the number of seconds to delay for between restarts.\n" - " The default is %d.\n\n" - -#ifdef HAVE_LIBCURL - " -W watchdog_url,start,cycle,timeout\n" - " Specifies an optional URL to watch while waiting for the process\n" - " to terminate. If this is specified, autorestart will start the process,\n" - " wait start seconds, and then repeatedly poll the indicated URL\n" - " every cycle seconds. If a HTTP failure code is detected,\n" - " or no response is received within timeout seconds, then the\n" - " child is terminated and restarted. The start, cycle, and timeout\n" - " parameters are all required.\n\n" -#endif /* HAVE_LIBCURL */ - - " -U username\n" - " Change to the indicated user upon startup. The logfile is still\n" - " created as the initial user.\n\n" - - " -G groupname\n" - " Change to the indicated group upon startup.\n\n" - - " -D dirname\n" - " Change to the indicated working directory upon startup. The logfile\n" - " is still created relative to the initial startup directory.\n\n" - - " -h\n" - " Output this help information.\n\n", - spam_respawn_count, spam_respawn_time, spam_restart_delay_time, respawn_delay_time); -} - -void -parse_int_triplet(char *param, int *a, int *b, int *c) { - char *comma; - char *comma2; - - comma = strchr(param, ','); - if (comma == NULL) { - fprintf(stderr, "Comma required: %s\n", param); - exit(1); - } - - comma2 = strchr(comma+1, ','); - if (comma2 == NULL) { - fprintf(stderr, "Second comma required: %s\n", param); - exit(1); - } - - *comma = '\0'; - *comma2 = '\0'; - - *a = atoi(param); - *b = atoi(comma + 1); - *c = atoi(comma2 + 1); -} - -void -parse_watchdog(char *param) { - char *comma; - char *comma2; - char *comma3; - -#ifndef HAVE_LIBCURL - fprintf(stderr, "-W requires autorestart to have been compiled with libcurl support.\n"); - exit(1); -#endif /* HAVE_LIBCURL */ - - comma = strrchr(param, ','); - if (comma == NULL) { - fprintf(stderr, "Comma required: %s\n", param); - exit(1); - } - *comma = '\0'; - - comma2 = strrchr(param, ','); - if (comma2 == NULL) { - *comma = ','; - fprintf(stderr, "Second comma required: %s\n", param); - exit(1); - } - *comma2 = '\0'; - - comma3 = strrchr(param, ','); - if (comma3 == NULL) { - *comma = ','; - *comma2 = ','; - fprintf(stderr, "Third comma required: %s\n", param); - exit(1); - } - *comma3 = '\0'; - - watchdog_url = param; - watchdog_start_sec = atoi(comma3 + 1); - watchdog_cycle_sec = atoi(comma2 + 1); - watchdog_timeout_sec = atoi(comma + 1); -} - - -int -main(int argc, char *argv[]) { - extern char *optarg; - extern int optind; - /* The initial '+' instructs GNU getopt not to reorder switches. */ - static const char *optflags = "+l:p:fntr:s:c:d:W:U:G:D:h"; - int flag; - - flag = getopt(argc, argv, optflags); - while (flag != EOF) { - switch (flag) { - case 'l': - logfile_name = optarg; - break; - - case 'p': - pidfile_name = optarg; - break; - - case 'f': - dont_fork = 1; - break; - - case 'n': - stop_always = 1; - break; - - case 't': - stop_on_terminate = 1; - break; - - case 'r': - parse_int_triplet(optarg, &spam_respawn_count, &spam_respawn_time, &spam_restart_delay_time); - break; - - case 's': - respawn_script = optarg; - break; - - case 'c': - respawn_count_time = atoi(optarg); - break; - - case 'd': - respawn_delay_time = atoi(optarg); - break; - - case 'W': - parse_watchdog(optarg); - break; - - case 'U': - startup_username = optarg; - break; - - case 'G': - startup_groupname = optarg; - break; - - case 'D': - startup_chdir = optarg; - break; - - case 'h': - help(); - return 1; - - case '?': - case '+': - usage(); - return 1; - - default: - fprintf(stderr, "Unhandled switch: -%c\n", flag); - return 1; - } - flag = getopt(argc, argv, optflags); - } - - argc -= (optind - 1); - argv += (optind - 1); - - if (argc < 2) { - fprintf(stderr, "No program to execute given.\n"); - usage(); - return 1; - } - - params = &argv[1]; - - if (logfile_name != NULL) { - logfile_fd = open(logfile_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (logfile_fd < 0) { - fprintf(stderr, "Cannot write to logfile %s: %s\n", - logfile_name, strerror(errno)); - return 1; - } - fprintf(stderr, "Generating output to %s.\n", logfile_name); - } - - if (startup_chdir != NULL) { - if (chdir(startup_chdir) != 0) { - perror(startup_chdir); - return 1; - } - } - - if (startup_groupname != NULL) { - struct group *grp; - grp = getgrnam(startup_groupname); - if (grp == NULL) { - perror(startup_groupname); - return 1; - } - - if (setgid(grp->gr_gid) != 0) { - perror(startup_groupname); - return 1; - } - } - - if (startup_username != NULL) { - struct passwd *pwd; - pwd = getpwnam(startup_username); - if (pwd == NULL) { - perror(startup_username); - return 1; - } - - if (setuid(pwd->pw_uid) != 0) { - perror(startup_username); - return 1; - } - } - - if (dont_fork) { - do_autorestart(); - } else { - double_fork(); - } - - return 0; -} - diff --git a/direct/src/directscripts/Doxyfile.python b/direct/src/directscripts/Doxyfile.python index 32ba23481d..81b68dc6b2 100644 --- a/direct/src/directscripts/Doxyfile.python +++ b/direct/src/directscripts/Doxyfile.python @@ -643,8 +643,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = built/direct/test \ - built/direct/plugin \ +EXCLUDE = built/direct/plugin \ built/direct/plugin_npapi \ built/direct/plugin_activex \ built/direct/plugin_installer \ diff --git a/direct/src/heapq/Sources.pp b/direct/src/heapq/Sources.pp deleted file mode 100755 index e072ecf367..0000000000 --- a/direct/src/heapq/Sources.pp +++ /dev/null @@ -1,29 +0,0 @@ -// DIR_TYPE "metalib" indicates we are building a shared library that -// consists mostly of references to other shared libraries. Under -// Windows, this directly produces a DLL (as opposed to the regular -// src libraries, which don't produce anything but a pile of OBJ files -// under Windows). - -#define DIR_TYPE metalib - -// This directory strictly contains a Python utility; therefore, only -// build it if we actually have Python. -#define BUILD_DIRECTORY $[HAVE_PYTHON] - - -#define OTHER_LIBS \ - pandaexpress:m \ - p3dconfig:c p3dtoolconfig:m \ - p3dtoolutil:c p3dtoolbase:c p3prc:c p3dtool:m - -#begin metalib_target - #define TARGET p3heapq - - // Tell ppremake to treat this file as if it had been generated via - // interrogate. On OSX, this will move it into the .so, instead of - // the .dylib, so that it can be imported into Python. - #define PYTHON_MODULE_ONLY 1 - - #define SOURCES heapq.cxx -#end metalib_target - diff --git a/direct/src/heapq/heapq.cxx b/direct/src/heapq/heapq.cxx deleted file mode 100755 index dcfe34f4bd..0000000000 --- a/direct/src/heapq/heapq.cxx +++ /dev/null @@ -1,240 +0,0 @@ - -/* Note: This module can probably go away when we upgrade to Python 2.4. - Python 2.3 has a heapq implementation, but it is in Python. This is - reported to be about 20x faster. In 2.4 they reimplemented heapq in C so - it should be comparable to this. At this time though, Python 2.4 is - still in alpha. - - Note: This code has been bastardized to only work on Tasks temporarily. - -*/ - -#include - -/* Prototypes */ -static PyObject * heappush(PyObject *self, PyObject *args); -static PyObject * heappop(PyObject *self, PyObject *args); -static PyObject * heapreplace(PyObject *self, PyObject *args); -static PyObject * heapify(PyObject *self, PyObject *args); -static int _siftdown(PyObject *list, int startpos, int pos); -static int _siftup(PyObject *list, int pos); - -#ifdef _WIN32 -extern "C" __declspec(dllexport) void initlibheapq(void); -extern "C" __declspec(dllexport) void initlibp3heapq(void); -#else -extern "C" void initlibheapq(); -extern "C" void initlibp3heapq(); -#endif - -static PyObject * -heappush(PyObject *self, PyObject *args) { - int len; - PyObject *list = NULL; - PyObject *node = NULL; - - if (!PyArg_ParseTuple(args,"O!O",&PyList_Type,&list,&node)) - return NULL; - - len = PyList_Size(list); - if (PyList_Append(list,node)) - return NULL; - - if (_siftdown(list,0,len)) - return NULL; - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -heappop(PyObject *self, PyObject *args) { - PyObject *list = NULL; - PyObject *node = NULL; - PyObject *returnNode = NULL; - int len; - - if (!PyArg_ParseTuple(args,"O!",&PyList_Type,&list)) - return NULL; - - len = PyList_Size(list); - if (len == 0) { - /* Special-case most common failure cause */ - PyErr_SetString(PyExc_IndexError, "pop from empty list"); - return NULL; - } - - node = PySequence_GetItem(list,-1); - PySequence_DelItem(list,-1); - - len -= 1; - if (len > 0) { - returnNode = PySequence_GetItem(list,0); - PyList_SetItem(list,0,node); - if (_siftup(list,0)) - return NULL; - } else { - returnNode = node; - } - - return returnNode; -} - -static PyObject * -heapreplace(PyObject *self, PyObject *args) { - PyObject *list = NULL; - PyObject *node = NULL; - PyObject *returnNode = NULL; - int len; - - if (!PyArg_ParseTuple(args,"O!O",&PyList_Type,&list,&node)) - return NULL; - - len = PyList_Size(list); - if (len == 0) { - /* Special-case most common failure cause */ - PyErr_SetString(PyExc_IndexError, "replace on an empty list"); - return NULL; - } - - returnNode = PySequence_GetItem(list,0); - PySequence_SetItem(list,0,node); - if (_siftup(list,0)) - return NULL; - - return returnNode; -} - -static PyObject * -heapify(PyObject *self, PyObject *args) { - int n, i; - PyObject *list; - - if (!PyArg_ParseTuple(args,"O!",&PyList_Type,&list)) - return NULL; - n = (PyList_Size(list)/2)-1; - - for (i=n;i>=0;i--) { - if (_siftup(list,i)) - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -static int -_siftdown(PyObject *list, int startpos, int pos) { - PyObject *newitem, *parent; - int parentpos; - - newitem = PySequence_GetItem(list,pos); - - PyObject *newitem_wakeTime_obj = PyObject_GetAttrString(newitem, "wakeTime"); - double newitem_wakeTime = 0.0; - if (newitem_wakeTime_obj != NULL) { - newitem_wakeTime = PyFloat_AS_DOUBLE(newitem_wakeTime_obj); - Py_DECREF(newitem_wakeTime_obj); - } - - while (pos > startpos) { - parentpos = (pos - 1) >> 1; - parent = PyList_GetItem(list,parentpos); - - /* - cmp = PyObject_RichCompareBool(parent,newitem,Py_LE); - if (cmp > 0) - break; - else if (cmp < 0) - return -1; - */ - - PyObject *parent_wakeTime_obj = PyObject_GetAttrString(parent, "wakeTime"); - double parent_wakeTime = 0.0; - if (parent_wakeTime_obj != NULL) { - parent_wakeTime = PyFloat_AS_DOUBLE(parent_wakeTime_obj); - Py_DECREF(parent_wakeTime_obj); - } - - if (parent_wakeTime <= newitem_wakeTime) { - break; - } - - Py_INCREF(parent); - PyList_SetItem(list,pos,parent); - pos = parentpos; - } - PyList_SetItem(list,pos,newitem); - return 0; -} - -static int -_siftup(PyObject *list, int pos) { - PyObject *newitem, *right, *child; - int endpos, rightpos, childpos; - int startpos = pos; - - endpos = PyList_Size(list); - newitem = PySequence_GetItem(list,pos); - - childpos = (2*pos)+1; - while (childpos < endpos) { - rightpos = childpos + 1; - child = PySequence_Fast_GET_ITEM(list,childpos); - - PyObject *child_wakeTime_obj = PyObject_GetAttrString(child, "wakeTime"); - double child_wakeTime = 0.0; - if (child_wakeTime_obj != NULL) { - child_wakeTime = PyFloat_AS_DOUBLE(child_wakeTime_obj); - Py_DECREF(child_wakeTime_obj); - } - - - if (rightpos < endpos) { - right = PySequence_Fast_GET_ITEM(list,rightpos); - - PyObject *right_wakeTime_obj = PyObject_GetAttrString(right, "wakeTime"); - double right_wakeTime = 0.0; - if (right_wakeTime_obj != NULL) { - right_wakeTime = PyFloat_AS_DOUBLE(right_wakeTime_obj); - Py_DECREF(right_wakeTime_obj); - } - - /* - cmp = PyObject_RichCompareBool(right,child,Py_LE); - if (cmp > 0) - childpos = rightpos; - else if (cmp < 0) - return -1; - */ - - if (right_wakeTime <= child_wakeTime) { - childpos = rightpos; - } - } - child = PySequence_GetItem(list,childpos); - PyList_SetItem(list,pos,child); - pos = childpos; - childpos = (2*pos)+1; - } - PyList_SetItem(list,pos,newitem); - - return _siftdown(list,startpos,pos); -} - -static PyMethodDef heapqcMethods[] = { - {"heappush",heappush,METH_VARARGS}, - {"heappop",heappop,METH_VARARGS}, - {"heapreplace",heapreplace,METH_VARARGS}, - {"heapify",heapify,METH_VARARGS}, - {NULL, NULL} /* Sentinel */ -}; - -void initlibheapq(void) { - (void) Py_InitModule("libheapq", heapqcMethods); -}; - -void initlibp3heapq(void) { - (void) Py_InitModule("libp3heapq", heapqcMethods); -}; - diff --git a/direct/src/http/LandingPage.py b/direct/src/http/LandingPage.py index 927994d326..212e3a6e20 100755 --- a/direct/src/http/LandingPage.py +++ b/direct/src/http/LandingPage.py @@ -3,7 +3,7 @@ from direct.directnotify.DirectNotifyGlobal import directNotify from pandac.PandaModules import VirtualFileSystem from pandac.PandaModules import Filename from pandac.PandaModules import DSearchPath -from direct.showbase import ElementTree as ET +import xml.etree.ElementTree as ET import LandingPageHTML from StringIO import StringIO diff --git a/direct/src/http/LandingPageHTML.py b/direct/src/http/LandingPageHTML.py index b40eac6324..bc04caf80e 100755 --- a/direct/src/http/LandingPageHTML.py +++ b/direct/src/http/LandingPageHTML.py @@ -1,6 +1,6 @@ # -- Text content for the landing page. You should change these for yours! -- -from direct.showbase import ElementTree as ET +import xml.etree.ElementTree as ET title = "Landing Page" defaultTitle = title diff --git a/direct/src/http/WebRequest.py b/direct/src/http/WebRequest.py index 95b058ef5e..dc40be7e28 100755 --- a/direct/src/http/WebRequest.py +++ b/direct/src/http/WebRequest.py @@ -4,7 +4,7 @@ from direct.directnotify.DirectNotifyGlobal import directNotify from direct.task.TaskManagerGlobal import taskMgr from direct.task import Task from LandingPage import LandingPage -from direct.showbase import ElementTree as ET +import xml.etree.ElementTree as ET notify = directNotify.newCategory('WebRequestDispatcher') diff --git a/direct/src/pyinst/Builder.py b/direct/src/pyinst/Builder.py deleted file mode 100644 index b43f18172b..0000000000 --- a/direct/src/pyinst/Builder.py +++ /dev/null @@ -1,504 +0,0 @@ -import string -import pprint -import sys -import os -import ConfigParser -import pprint -import shutil -import tempfile -import ltoc -import tocfilter -import resource -import archive -import archivebuilder -import carchive - -logfile = None -autopath = [] -built = {} -copyFile = None - -class Target: - def __init__(self, cfg, sectnm, cnvrts): - self.children = [] - self._dependencies = ltoc.lTOC() # the stuff an outer package will need to use me - self.cfg = cfg - self.__name__ = 'joe' - for optnm in cfg.options(sectnm): - cnvrt = cnvrts.get(optnm, 'getstringlist') - if cnvrt: - f = getattr(self, cnvrt, None) - if f: - self.__dict__[optnm] = f(cfg.get(sectnm, optnm)) - if not hasattr(self, 'name'): - self.name = self.__name__ - print "Initializing", self.__name__ - self.pathprefix = autopath + self.pathprefix - self.pathprefix.append(os.path.join(pyinsthome, 'support')) - for z in self.zlib: - if z in self.cfg.sections(): - self.children.append(z) - else: - raise ValueError, "%s - zlib '%s' does not refer to a sections" \ - % (self.name, z) - for i in range(len(self.misc)): - x = self.misc[i] - if x in self.cfg.sections(): - if self.cfg.get(x, "type") == 'PYZ': - self.zlib.append(x) - self.misc[i] = None - self.children.append(x) - self.misc = filter(None, self.misc) - self.edit() - self.toc = ltoc.lTOC() - for thingie in self.excludes: - try: - fltr = tocfilter.makefilter(thingie, self.pathprefix) - except ValueError: - print "Warning: '%s' not found - no filter created" % thingie - else: - self.toc.addFilter(fltr) - if self.exstdlib: - self.toc.addFilter(tocfilter.StdLibFilter()) - if self.extypes: - self.toc.addFilter(tocfilter.ExtFilter(self.extypes)) - if self.expatterns: - self.toc.addFilter(tocfilter.PatternFilter(self.expatterns)) - - ##------utilities------## - def dump(self): - logfile.write("---- %s: %s -----\n" % (self.__class__.__name__, self.name)) - pprint.pprint(self.__dict__, logfile) - def getstringlist(self, opt): - tmp = string.split(opt, ',') - return filter(None, map(string.strip, tmp)) - def getstring(self, opt): - return opt - def getbool(self, opt): - if opt in ('0','f','F','n','N'): - return 0 - return 1 - ##-----framework-----## - def build(self): - print "Gathering components of %s" % self.name - self.gather() - logfile.write("Final Table of Contents for %s:\n" % self.name) - pprint.pprint(self.toc.toList(), logfile) - print "Creating %s" % self.name - self.assemble() - ##-----overrideables-----## - def edit(self): - pass - def gather(self): - pass - def assemble(self): - pass - -class PYZTarget(Target): - def __init__(self, cfg, sectnm, cnvrts): - Target.__init__(self, cfg, sectnm, cnvrts) - # to use a PYZTarget, you'll need imputil and archive - archivebuilder.GetCompiled([os.path.join(pyinsthome, 'imputil.py')]) - print "pyinsthome:", pyinsthome - imputil = resource.makeresource('imputil.py', [pyinsthome]) - self._dependencies.append(imputil) - archivebuilder.GetCompiled([os.path.join(pyinsthome, 'archive_rt.py')]) - archmodule = resource.makeresource('archive_rt.py', [pyinsthome]) - self._dependencies.merge(archmodule.dependencies()) - self._dependencies.append(archmodule) - self.toc.addFilter(archmodule) - self.toc.addFilter(imputil) - for mod in archmodule.modules: - self.toc.addFilter(mod) - def edit(self): - if self.extypes: - print "PYZ target %s ignoring extypes = %s" % (self.__name__, self.extypes) - - def gather(self): - for script in self.dependencies: - rsrc = resource.makeresource(script, self.pathprefix) - if not isinstance(rsrc, resource.scriptresource): - print "Bug alert - Made %s from %s!" % (rsrc, script) - self.toc.merge(rsrc.modules) - logfile.write("lTOC after expanding 'depends':\n") - pprint.pprint(self.toc.toList(), logfile) - for thingie in self.includes + self.directories + self.packages: - rsrc = resource.makeresource(thingie, self.pathprefix) -## if not isinstance(rsrc, resource.pythonresource): -## print "PYZ target %s ignoring include %s" % (self.name, thingie) -## else: - self.toc.merge(rsrc.contents()) - logfile.write("lTOC after includes, dir, pkgs:\n") - pprint.pprint(self.toc.toList(), logfile) - self.toc.addFilter(tocfilter.ExtFilter(['.py', '.pyc', '.pyo'], 1)) - logfile.write("Applying the following filters:\n") - pprint.pprint(self.toc.filters, logfile) - self.toc.filter() - - def assemble(self): - contents = self.toc.toList() - if contents: - lib = archive.ZlibArchive() - lib.build(self.name, archivebuilder.GetCompiled(self.toc.toList())) - -class CollectTarget(Target): - def __init__(self, cfg, sectnm, cnvrts): - Target.__init__(self, cfg, sectnm, cnvrts) - - _rsrcdict = {'COLLECT': resource.dirresource, 'PYZ': resource.zlibresource, 'CARCHIVE': resource.archiveresource} - - def gather(self): - if self.support: - # the bare minimum - self.toc.merge([resource.makeresource('python20.dll')]) - self.toc.merge([resource.makeresource('exceptions.pyc').asBinary()]) - # zlib, bindepends, misc, trees, destdir - for i in range(len(self.zlib)): - # z refers to the section name - z = self.zlib[i] - nm = self.cfg.get(z, 'name') - try: - self.toc.merge([resource.makeresource(nm, ['.'])]) - except ValueError: - # zlibs aren't written if they turn out to be empty - self.zlib[i] = None - self.zlib = filter(None, self.zlib) - if self.zlib: - target = built.get(self.zlib[0], None) - if target: - self.toc.merge(target._dependencies) - for script in self.bindepends: - rsrc = resource.makeresource(script, self.pathprefix) - self.toc.merge(rsrc.binaries) - logfile.write('ltoc after bindepends:\n') - pprint.pprint(self.toc.toList(), logfile) - for thingie in self.misc: - if thingie in self.cfg.sections(): - name = self.cfg.get(thingie, "name") - typ = self.cfg.get(thingie, "type") - klass = self._rsrcdict.get(typ, resource.dataresource) - rsrc = apply(klass, (name, name)) - #now make sure we have the stuff the resource requires - target = built.get(thingie, None) - if target: - self.toc.merge(target._dependencies) - else: - rsrc = resource.makeresource(thingie, self.pathprefix) - self.toc.merge(rsrc.contents()) - logfile.write('ltoc after misc:\n') - pprint.pprint(self.toc.toList(), logfile) - for script in self.script: - if string.find(script, '.') == -1: - script = script + '.py' - rsrc = resource.makeresource(script, self.pathprefix) - if rsrc.typ == 'm': - rsrc.typ = 's' - self.toc.merge([rsrc]) - logfile.write('ltoc after scripts:\n') - pprint.pprint(self.toc.toList(), logfile) - for tree in self.trees: - try: - rsrc = resource.treeresource('.', tree) - except ValueError: - print "tree %s not found" % tree - else: - self.toc.merge(rsrc.contents()) - logfile.write('ltoc after trees:\n') - pprint.pprint(self.toc.toList(), logfile) - self.toc.addFilter(tocfilter.TypeFilter(['d'])) - logfile.write("Applying the following filters:\n") - pprint.pprint(self.toc.filters, logfile) - self.toc.filter() - #don't dupe stuff in a zlib that's part of this target - if self.zlib: - ztoc = ltoc.lTOC() - for zlibnm in self.zlib: - target = built.get(zlibnm, None) - if target: - ztoc.merge(target.toc) - for i in range(len(self.toc)-1, -1, -1): - rsrc = self.toc[i] - if isinstance(rsrc, resource.moduleresource) and rsrc in ztoc: - del self.toc[i] - - def assemble(self): - if os.path.exists(self.name): - if os.path.isdir(self.name): - for fnm in os.listdir(self.name): - try: - os.remove(os.path.join(self.name, fnm)) - except: - print "Could not delete file %s" % os.path.join(self.name, fnm) - else: - os.makedirs(self.name) - mysite = [] - for nm, path, typ in self.toc.toList(): - shutil.copy2(path, self.name) - if typ == 'z': - mysite.append('imputil.FuncImporter(archive.ZlibArchive("%s", 0).get_code).install()' % nm) - if mysite: - mysite.insert(0, 'import archive, imputil') - open(os.path.join(self.name, 'site.py'),'w').write(string.join(mysite, '\n')) - - -class ArchiveTarget(CollectTarget): - usefullname = 1 - def __init__(self, cfg, sectnm, cnvrts): - CollectTarget.__init__(self, cfg, sectnm, cnvrts) - archivebuilder.GetCompiled([os.path.join(pyinsthome, 'carchive_rt.py')]) - carchmodule = resource.makeresource('carchive_rt.py', [pyinsthome]) - self._dependencies.merge(carchmodule.dependencies()) - self._dependencies.append(carchmodule) - - def edit(self): - if self.destdir: - print "Warning 'destdir = %s' ignored for %s" % (self.destdir, self.name) - - def gather(self): - CollectTarget.gather(self) - - _cdict = {'s':2,'m':1,'b':1,'x':1,'a':0,'z':0, 'p':1} - - def assemble(self, pkgnm=None): - if pkgnm is None: - pkgnm = self.name - arch = carchive.CArchive() - toc = [] - pytoc = [] - for nm, path, typ in self.toc.toList(): - compress = self._cdict[typ] - if typ == 'b' or (self.usefullname and typ in 'ms'): - nm = os.path.basename(path) - if typ == 'm': - pytoc.append((nm, path, compress, typ)) - else: - toc.append((nm, path, compress, typ)) - toc = toc + archivebuilder.GetCompiled(pytoc) - arch.build(pkgnm, toc) - return arch - -class FullExeTarget(ArchiveTarget): - usefullname = 0 - def __init__(self, cfg, sectnm, cnvrts): - ArchiveTarget.__init__(self, cfg, sectnm, cnvrts) - - def gather(self): - for script in self.script: - #print "FullExeTarget.gather: script is", repr(script) - rsrc = resource.makeresource(script, self.pathprefix) - rsrc = resource.scriptresource(rsrc.name, rsrc.path) - #print " resource is", repr(rsrc) - self.toc.merge(rsrc.binaries) - ArchiveTarget.gather(self) - if not self.zlib: - self.toc.merge(rsrc.modules) - self._dependencies = ltoc.lTOC() - - _cdict = {'s':2,'m':0,'b':1,'x':0,'a':0,'z':0} - _edict = { (1, 1):'Runw_d.exe', (1, 0):'Runw.exe', (0, 1):'Run_d.exe', (0, 0):'Run.exe'} - - def assemble(self): - pkgname = tempfile.mktemp() - arch = ArchiveTarget.assemble(self, pkgname) - exe = self._edict[(self.userunw, self.debug)] - exe = os.path.normpath(os.path.join(pyinsthome, 'support', exe)) -## copyFile([exe, pkgname], self.name) -## os.remove(pkgname) - # Thomas Heller's icon code - # my version - if self.icon: - myexe = tempfile.mktemp() - copyFile (exe, myexe) - try: - from icon import CopyIcons - CopyIcons(myexe, self.icon) - except ImportError: - print "win32api is required for updating icons" - print "You should have win32api.pyd and PyWinTypes20.dll" - print "in the installation directory." - print "Please copy them to Python's DLLS subdirectory" - print "(or install Mark Hammond's Win32 extensions)." -## iconfile = None -## for name in self.cfg.sections(): -## if self.cfg.get (name, "type") == "STANDALONE": -## try: -## iconfile = self.cfg.get (name, "iconfile") -## except: -## pass -## if iconfile: -## from icon import CopyIcons -## CopyIcons (myexe, iconfile) - copyFile ([myexe, pkgname], self.name) - os.remove(myexe) - else: - copyFile([exe, pkgname], self.name) - #os.remove(pkgname) - -class ExeTarget(FullExeTarget): - def __init__(self, cfg, sectnm, cnvrts): - FullExeTarget.__init__(self, cfg, sectnm, cnvrts) - - def edit(self): - if not self.script: - raise ValueError, "EXE target %s requires 'script=