diff --git a/.gitignore b/.gitignore index a6cc43e4..a5f72e0f 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,6 @@ server.dylib.dSYM/ # files generated by running a mod config.cfg +# shader files +*.tmp diff --git a/mp/game/mod_hl2mp/materials/example_model_material.vmt b/mp/game/mod_hl2mp/materials/example_model_material.vmt new file mode 100644 index 00000000..219f60f2 --- /dev/null +++ b/mp/game/mod_hl2mp/materials/example_model_material.vmt @@ -0,0 +1,7 @@ +"Mod_Example_Model" +{ + "$basetexture" "Models/props_c17/Oil_Drum001g" +// "$basetexturetransform" "center 0 0 scale 1 2 rotate 0 translate 0 0" +// "$AlphaTestReference" "0.5" + "$surfaceprop" "metal" +} diff --git a/mp/game/mod_hl2mp/shaders/fxc/example_model_ps20b.vcs b/mp/game/mod_hl2mp/shaders/fxc/example_model_ps20b.vcs new file mode 100644 index 00000000..616b536f Binary files /dev/null and b/mp/game/mod_hl2mp/shaders/fxc/example_model_ps20b.vcs differ diff --git a/mp/game/mod_hl2mp/shaders/fxc/example_model_vs20.vcs b/mp/game/mod_hl2mp/shaders/fxc/example_model_vs20.vcs new file mode 100644 index 00000000..633eda48 Binary files /dev/null and b/mp/game/mod_hl2mp/shaders/fxc/example_model_vs20.vcs differ diff --git a/mp/src/createallprojects b/mp/src/createallprojects index 4677ca79..4f44d066 100755 --- a/mp/src/createallprojects +++ b/mp/src/createallprojects @@ -1,4 +1,4 @@ #!/bin/bash -devtools/bin/vpc /hl2 /episodic +everything /mksln everything +devtools/bin/vpc /hl2mp +everything /mksln everything diff --git a/mp/src/creategameprojects b/mp/src/creategameprojects index ae1d12cc..0fa9b4ed 100755 --- a/mp/src/creategameprojects +++ b/mp/src/creategameprojects @@ -1,4 +1,4 @@ #!/bin/bash -devtools/bin/vpc /hl2 /episodic +game /mksln games +devtools/bin/vpc /hl2mp +game /mksln games diff --git a/mp/src/devtools/bin/buildshaderlist.pl b/mp/src/devtools/bin/buildshaderlist.pl new file mode 100644 index 00000000..57790ace --- /dev/null +++ b/mp/src/devtools/bin/buildshaderlist.pl @@ -0,0 +1,22 @@ +use File::DosGlob; +@ARGV = map { + my @g = File::DosGlob::glob($_) if /[*?]/; + @g ? @g : $_; + } @ARGV; + +open FILE, ">__tmpshaderlist.txt"; + +foreach $arg (@ARGV) +{ + if( $arg =~ m/\.fxc$/i || $arg =~ m/\.vsh$/i || $arg =~ m/\.psh$/i ) + { + print $arg . "\n"; + print FILE $arg . "\n"; + } +} + +close FILE; + +system "buildshaders.bat __tmpshaderlist"; + +unlink "__tmpshaderlist.txt"; \ No newline at end of file diff --git a/mp/src/devtools/bin/checkshaderchecksums.pl b/mp/src/devtools/bin/checkshaderchecksums.pl new file mode 100644 index 00000000..e41509f2 --- /dev/null +++ b/mp/src/devtools/bin/checkshaderchecksums.pl @@ -0,0 +1,116 @@ +use String::CRC32; +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; + +sub GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub GetShaderSrc +{ + my $shadername = shift; + if ( $shadername =~ m/^(.*)-----/i ) + { + return $1; + } + else + { + return $shadername; + } +} + +sub GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub GetShaderBase +{ + my $shadername = shift; + if ( $shadername =~ m/-----(.*)$/i ) + { + return $1; + } + else + { + my $shadertype = &GetShaderType( $shadername ); + $shadername =~ s/\.$shadertype//i; + return $shadername; + } +} + +$g_x360 = 0; +$g_vcsext = ".vcs"; + +while( 1 ) +{ + $inputbase = shift; + + if( $inputbase =~ m/-x360/ ) + { + $g_x360 = 1; + $g_vcsext = ".360.vcs"; + } + else + { + last; + } +} + +# rip the txt off the end if it's there. +$inputbase =~ s/\.txt//i; + +my @srcfiles = &LoadShaderListFile( $inputbase ); + +foreach $srcfile ( @srcfiles ) +{ + my $shadertype = &GetShaderType( $srcfile ); + my $shaderbase = &GetShaderBase( $srcfile ); + my $shadersrc = &GetShaderSrc( $srcfile ); + my $vcsFileName = "..\\..\\..\\game\\hl2\\shaders\\$shadertype\\$shaderbase" . $g_vcsext; +# print "shadersrc: $shadersrc vcsFileName: $vcsFileName\n"; + + if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) ) + { + next; # skip _ps20 files for 360 + } + + &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 1 ); +} diff --git a/mp/src/devtools/bin/copyshaderincfiles.pl b/mp/src/devtools/bin/copyshaderincfiles.pl new file mode 100644 index 00000000..21702d8f --- /dev/null +++ b/mp/src/devtools/bin/copyshaderincfiles.pl @@ -0,0 +1,75 @@ +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; +use Cwd; +use String::CRC32; + +my $txtfilename = shift; +my $arg = shift; + +my $is360 = 0; +my $platformextension = ""; +if( $arg =~ m/-x360/i ) +{ + $is360 = 1; + $platformextension = ".360"; +} + +open TXTFILE, "<$txtfilename"; + +my $src; +my $dst; +while( $src = ) +{ + # get rid of comments + $src =~ s,//.*,,g; + + # skip blank lines + if( $src =~ m/^\s*$/ ) + { + next; + } + + # Get rid of newlines. + $src =~ s/\n//g; + + # Save off the shader source filename. + my $dst = $src; + + $dst =~ s/_tmp//gi; + + # Does the dst exist? + my $dstexists = -e $dst; + my $srcexists = -e $src; + # What are the time stamps for the src and dst? + my $srcmodtime = ( stat $src )[9]; + my $dstmodtime = ( stat $dst )[9]; + + # Open for edit or add if different than what is in perforce already. + if( !$dstexists || ( $srcmodtime != $dstmodtime ) ) + { + # Make the target writable if it exists + if( $dstexists ) + { + MakeFileWritable( $dst ); + } + + my $dir = $dst; + $dir =~ s,([^/\\]*$),,; # rip the filename off the end + my $filename = $1; + + # create the target directory if it doesn't exist + if( !$dstexists ) + { + &MakeDirHier( $dir, 0777 ); + } + + # copy the file to its targets. . . we want to see STDERR here if there is an error. + my $cmd = "copy $src $dst > nul"; +# print STDERR "$cmd\n"; + system $cmd; + + MakeFileReadOnly( $dst ); + } +} + +close TXTFILE; diff --git a/mp/src/devtools/bin/copyshaders.pl b/mp/src/devtools/bin/copyshaders.pl new file mode 100644 index 00000000..53839298 --- /dev/null +++ b/mp/src/devtools/bin/copyshaders.pl @@ -0,0 +1,172 @@ +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; +use Cwd; +use String::CRC32; + +sub ReadInputFileWithIncludes +{ + local( $filename ) = shift; + + local( *INPUT ); + local( $output ); + + open INPUT, "<$filename" || die; + + local( $line ); + local( $linenum ) = 1; + while( $line = ) + { + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + $output.= ReadInputFileWithIncludes( $1 ); + } + else + { + $output .= $line; + } + } + + close INPUT; + return $output; +} + +sub PatchCRC +{ + my $filename = shift; + my $crc = shift; +# print STDERR "PatchCRC( $filename, $crc )\n"; + local( *FP ); + open FP, "+<$filename" || die; + binmode( FP ); + seek FP, 6 * 4, 0; + my $uInt = "I"; + if( $filename =~ m/360/ ) + { + $uInt = "N"; + } + print FP pack $uInt, $crc; + close FP; +} + +my $txtfilename = shift; +my $arg = shift; + +my $is360 = 0; +my $platformextension = ""; +if( $arg =~ m/-x360/i ) +{ + $is360 = 1; + $platformextension = ".360"; +} + +# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist. +my $changelistnumber = `valve_p4_create_changelist.cmd ..\\..\\..\\game\\hl2\\shaders \"Shader Auto Checkout VCS\"`; +# Get rid of the newline +$changelistnumber =~ s/\n//g; + +my $changelistarg = ""; +if( $changelistnumber != 0 ) +{ + $changelistarg = "-c $changelistnumber" +} + +open TXTFILE, "<$txtfilename"; + +my $src; +my $dst; +while( $src = ) +{ + # get rid of comments + $src =~ s,//.*,,g; + + # skip blank lines + if( $src =~ m/^\s*$/ ) + { + next; + } + + # Get rid of newlines. + $src =~ s/\n//g; + + # Save off the shader source filename. + my $shadersrcfilename = $src; + $shadersrcfilename =~ s/-----.*$//; + # use only target basename. + $src =~ s/^.*-----//; + + # where the binary vcs file is + my $spath = ""; + + if ( $shadersrcfilename =~ m@\.fxc@i ) + { + $spath = "shaders\\fxc\\"; + } + if ( $shadersrcfilename =~ m@\.vsh@i ) + { + $spath = "shaders\\vsh\\"; + } + if ( $shadersrcfilename =~ m@\.psh@i ) + { + $spath = "shaders\\psh\\"; + } + + # make the source have path and extension + $src = $spath . $src . $platformextension . ".vcs"; + + # build the dest filename. + $dst = $src; + + $dst =~ s/shaders\\/..\\..\\..\\game\\hl2\\shaders\\/i; + + # Does the dst exist? + my $dstexists = -e $dst; + my $srcexists = -e $src; + # What are the time stamps for the src and dst? + my $srcmodtime = ( stat $src )[9]; + my $dstmodtime = ( stat $dst )[9]; + + # Write $dst to a file so that we can do perforce stuff to it later. + local( *VCSLIST ); + open VCSLIST, ">>vcslist.txt" || die; + print VCSLIST $dst . "\n"; + close VCSLIST; + + # Open for edit or add if different than what is in perforce already. + if( !$dstexists || ( $srcmodtime != $dstmodtime ) ) + { + if ( $srcexists && $shadersrcfilename =~ m@\.fxc@i ) + { + # Get the CRC for the source file. + my $srccode = ReadInputFileWithIncludes( $shadersrcfilename ); + my $crc = crc32( $srccode ); + + # Patch the source VCS file with the CRC32 of the source code used to build that file. + PatchCRC( $src, $crc ); + } + + # Make the target vcs writable if it exists + if( $dstexists ) + { + MakeFileWritable( $dst ); + } + + my $dir = $dst; + $dir =~ s,([^/\\]*$),,; # rip the filename off the end + my $filename = $1; + + # create the target directory if it doesn't exist + if( !$dstexists ) + { + &MakeDirHier( $dir, 0777 ); + } + + # copy the file to its targets. . . we want to see STDERR here if there is an error. + my $cmd = "copy $src $dst > nul"; +# print STDERR "$cmd\n"; + system $cmd; + + MakeFileReadOnly( $dst ); + } +} + +close TXTFILE; diff --git a/mp/src/devtools/bin/d3dx9_33.dll b/mp/src/devtools/bin/d3dx9_33.dll new file mode 100644 index 00000000..a005f8fa Binary files /dev/null and b/mp/src/devtools/bin/d3dx9_33.dll differ diff --git a/mp/src/devtools/bin/fix_particle_operator_names.pl b/mp/src/devtools/bin/fix_particle_operator_names.pl new file mode 100644 index 00000000..86fd0f0f --- /dev/null +++ b/mp/src/devtools/bin/fix_particle_operator_names.pl @@ -0,0 +1,110 @@ +#!perl +use File::Find; + +&BuildRemapTable; + +find(\&convert, "." ); + + +sub convert + { + return unless (/\.pcf$/i); + return if (/^tmp\.pcf$/i); + return if (/^tmp2\.pcf$/i); + return if (/360\.pcf$/i); + print STDERR "process ", $File::Find::name," ($_) dir=",`cd`," \n"; + my $fname=$_; + print `p4 edit $fname`; + print `dmxconvert -i $_ -o tmp.pcf -oe keyvalues2`; + open(TMP, "tmp.pcf" ) || return; + open(OUT, ">tmp2.pcf" ) || die; + while() + { + s/[\n\r]//g; + if ( (/^(\s*\"functionName\"\s*\"string\"\s*\")(.*)\"(.*)$/) && + length($map{$2}) ) + { + $_=$1.$map{$2}.'"'.$3; + } + if ( (/^(\s*\"name\"\s*\"string\"\s*\")(.*)\"(.*)$/) && + length($map{$2}) ) + { + $_=$1.$map{$2}.'"'.$3; + } + print OUT "$_\n"; + } + close OUT; + close TMP; + print `dmxconvert -i tmp2.pcf -o $fname -ie keyvalues2 -oe binary`; + unlink "tmp.pcf"; + unlink "tmp2.pcf"; +} + + + + + + + + + + + + +sub BuildRemapTable +{ + $map{"alpha_fade"}= "Alpha Fade and Decay"; + $map{"alpha_fade_in_random"}= "Alpha Fade In Random"; + $map{"alpha_fade_out_random"}= "Alpha Fade Out Random"; + $map{"basic_movement"}= "Movement Basic"; + $map{"color_fade"}= "Color Fade"; + $map{"controlpoint_light"}= "Color Light From Control Point"; + $map{"Dampen Movement Relative to Control Point"}= "Movement Dampen Relative to Control Point"; + $map{"Distance Between Control Points Scale"}= "Remap Distance Between Two Control Points to Scalar"; + $map{"Distance to Control Points Scale"}= "Remap Distance to Control Point to Scalar"; + $map{"lifespan_decay"}= "Lifespan Decay"; + $map{"lock to bone"}= "Movement Lock to Bone"; + $map{"postion_lock_to_controlpoint"}= "Movement Lock to Control Point"; + $map{"maintain position along path"}= "Movement Maintain Position Along Path"; + $map{"Match Particle Velocities"}= "Movement Match Particle Velocities"; + $map{"Max Velocity"}= "Movement Max Velocity"; + $map{"noise"}= "Noise Scalar"; + $map{"vector noise"}= "Noise Vector"; + $map{"oscillate_scalar"}= "Oscillate Scalar"; + $map{"oscillate_vector"}= "Oscillate Vector"; + $map{"Orient Rotation to 2D Direction"}= "Rotation Orient to 2D Direction"; + $map{"radius_scale"}= "Radius Scale"; + $map{"Random Cull"}= "Cull Random"; + $map{"remap_scalar"}= "Remap Scalar"; + $map{"rotation_movement"}= "Rotation Basic"; + $map{"rotation_spin"}= "Rotation Spin Roll"; + $map{"rotation_spin yaw"}= "Rotation Spin Yaw"; + $map{"alpha_random"}= "Alpha Random"; + $map{"color_random"}= "Color Random"; + $map{"create from parent particles"}= "Position From Parent Particles"; + $map{"Create In Hierarchy"}= "Position In CP Hierarchy"; + $map{"random position along path"}= "Position Along Path Random"; + $map{"random position on model"}= "Position on Model Random"; + $map{"sequential position along path"}= "Position Along Path Sequential"; + $map{"position_offset_random"}= "Position Modify Offset Random"; + $map{"position_warp_random"}= "Position Modify Warp Random"; + $map{"position_within_box"}= "Position Within Box Random"; + $map{"position_within_sphere"}= "Position Within Sphere Random"; + $map{"Inherit Velocity"}= "Velocity Inherit from Control Point"; + $map{"Initial Repulsion Velocity"}= "Velocity Repulse from World"; + $map{"Initial Velocity Noise"}= "Velocity Noise"; + $map{"Initial Scalar Noise"}= "Remap Noise to Scalar"; + $map{"Lifespan from distance to world"}= "Lifetime from Time to Impact"; + $map{"Pre-Age Noise"}= "Lifetime Pre-Age Noise"; + $map{"lifetime_random"}= "Lifetime Random"; + $map{"radius_random"}= "Radius Random"; + $map{"random yaw"}= "Rotation Yaw Random"; + $map{"Randomly Flip Yaw"}= "Rotation Yaw Flip Random"; + $map{"rotation_random"}= "Rotation Random"; + $map{"rotation_speed_random"}= "Rotation Speed Random"; + $map{"sequence_random"}= "Sequence Random"; + $map{"second_sequence_random"}= "Sequence Two Random"; + $map{"trail_length_random"}= "Trail Length Random"; + $map{"velocity_random"}= "Velocity Random"; +} + diff --git a/mp/src/devtools/bin/linux/ccache b/mp/src/devtools/bin/linux/ccache index 9846e22d..3ef6b8e9 100755 Binary files a/mp/src/devtools/bin/linux/ccache and b/mp/src/devtools/bin/linux/ccache differ diff --git a/mp/src/devtools/bin/osx32/ccache b/mp/src/devtools/bin/osx32/ccache index 36a7081d..86afc048 100755 Binary files a/mp/src/devtools/bin/osx32/ccache and b/mp/src/devtools/bin/osx32/ccache differ diff --git a/mp/src/devtools/bin/shaderinfo.pl b/mp/src/devtools/bin/shaderinfo.pl new file mode 100644 index 00000000..ae0b96c8 --- /dev/null +++ b/mp/src/devtools/bin/shaderinfo.pl @@ -0,0 +1,36 @@ +#! perl + +my $fname=shift || die "format is shaderinfo blah.vcs"; + +open(SHADER, $fname) || die "can't open $fname"; +binmode SHADER; + +read(SHADER,$header,20); +($ver,$ntotal,$ndynamic,$flags,$centroidmask)=unpack("LLLLL",$header); + +#print "Version $ver total combos=$ntotal, num dynamic combos=$ndynamic,\n flags=$flags, centroid mask=$centroidmask\n"; + +read(SHADER,$refsize,4); +$refsize=unpack("L",$refsize); +#print "Size of reference shader for diffing=$refsize\n"; + +seek(SHADER,$refsize,1); + +$nskipped_combos=0; +for(1..$ntotal) + { + read(SHADER,$combodata,8); + ($ofs,$combosize)=unpack("LL",$combodata); + if ( $ofs == 0xffffffff) + { + $nskipped_combos++; + } + else + { + } + } +#print "$nskipped_combos skipped, for an actual total of ",$ntotal-$nskipped_combos,"\n"; +#print "Real to skipped ratio = ",($ntotal-$nskipped_combos)/$ntotal,"\n"; +# csv output - name, real combos, virtual combos, dynamic combos +my $real_combos=$ntotal-$nskipped_combos; +print "$fname,$real_combos,$ntotal,$ndynamic\n"; diff --git a/mp/src/devtools/bin/splitdiff3.pl b/mp/src/devtools/bin/splitdiff3.pl new file mode 100644 index 00000000..e38b493a --- /dev/null +++ b/mp/src/devtools/bin/splitdiff3.pl @@ -0,0 +1,54 @@ +$infilename = shift; +$outfilename1 = shift; +$outfilename2 = shift; +open INPUT, $infilename || die; +@input = ; +close INPUT; + +open MERGEDMINE, ">$outfilename1" || die; +open MERGEDTHEIRS, ">$outfilename2" || die; + +for( $i = 0; $i < scalar( @input ); $i++ ) +{ + $line = $input[$i]; + + if( $line =~ m/^(.*)<<<<<<>>>>>>/ ) + { + $first = $second = 0; + print MERGEDTHEIRS $1; + next; + } + + if( $first ) + { + print MERGEDMINE $line; + } + elsif( $second ) + { + print MERGEDTHEIRS $line; + } + else + { + print MERGEDMINE $line; + print MERGEDTHEIRS $line; + } +} + +close MERGEDMINE; +close MERGEDTHEIRS; diff --git a/mp/src/devtools/bin/uniqifylist.pl b/mp/src/devtools/bin/uniqifylist.pl new file mode 100644 index 00000000..d8d40afd --- /dev/null +++ b/mp/src/devtools/bin/uniqifylist.pl @@ -0,0 +1,6 @@ +foreach $_ (sort <> ) +{ + next if( defined( $prevline ) && $_ eq $prevline ); + $prevline = $_; + print; +} diff --git a/mp/src/devtools/bin/valve_perl_helpers.pl b/mp/src/devtools/bin/valve_perl_helpers.pl new file mode 100644 index 00000000..5cd2aa04 --- /dev/null +++ b/mp/src/devtools/bin/valve_perl_helpers.pl @@ -0,0 +1,558 @@ +sub BackToForwardSlash +{ + my( $path ) = shift; + $path =~ s,\\,/,g; + return $path; +} + +sub RemoveFileName +{ + my( $in ) = shift; + $in = &BackToForwardSlash( $in ); + $in =~ s,/[^/]*$,,; + return $in; +} + +sub RemovePath +{ + my( $in ) = shift; + $in = &BackToForwardSlash( $in ); + $in =~ s,^(.*)/([^/]*)$,$2,; + return $in; +} + +sub MakeDirHier +{ + my( $in ) = shift; +# print "MakeDirHier( $in )\n"; + $in = &BackToForwardSlash( $in ); + my( @path ); + while( $in =~ m,/, ) # while $in still has a slash + { + my( $end ) = &RemovePath( $in ); + push @path, $end; +# print $in . "\n"; + $in = &RemoveFileName( $in ); + } + my( $i ); + my( $numelems ) = scalar( @path ); + my( $curpath ); + for( $i = $numelems - 1; $i >= 0; $i-- ) + { + $curpath .= "/" . $path[$i]; + my( $dir ) = $in . $curpath; + if( !stat $dir ) + { +# print "mkdir $dir\n"; + mkdir $dir, 0777; + } + } +} + +sub FileExists +{ + my $filename = shift; + my @statresult = stat $filename; + my $iswritable = @statresult != 0; + return $iswritable; +} + +sub MakeFileWritable +{ + my $filename = shift; + if ( &FileExists( $filename ) ) + { + chmod 0666, $filename || die; + } +} + +sub MakeFileReadOnly +{ + my $filename = shift; + chmod 0444, $filename || die; +} + +# Run a command and get stdout and stderr to an array +sub RunCommand +{ + my $cmd = shift; +# print STDERR "command: $cmd\n"; + system "$cmd > cmdout.txt 2>&1" || die; + local( *FILE ); + open FILE, "; +# print STDERR "command output: @output\n"; + close FILE; + unlink "cmdout.txt" || die; + return @output; +} + +sub PerforceEditOrAdd +{ + return; + my $filename = shift; + my $changelistarg = shift; + + # Is the file on the client? + my $cmd = "p4 fstat \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $p4output = join "", @p4output; + if( $p4output =~ m/no such file/ ) + { + # not on client. . add + my $cmd = "p4 add $changelistarg $filename"; + my @p4output = &RunCommand( $cmd ); + my $p4output = join "", @p4output; + if( $p4output =~ m/opened for add/ ) + { + print $p4output; + return; + } + print "ERROR: $p4output"; + return; + } + + # The file is known to be on the client at this point. + + # Is it open for edit? + if( $p4output =~ m/action edit/ ) + { + # Is is open for edit, let's see if it's still different. + # check for opened files that are not different from the revision in the depot. + my $cmd = "p4 diff -sr \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + # check for empty string + if( !( $outputstring =~ m/^\s*$/ ) ) + { + my $cmd = "p4 revert \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + print $outputstring; + return; + } + } + + # check for unopened files that are different from the revision in the depot. + my $cmd = "p4 diff -se \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + # check for empty string + if( $outputstring =~ m/^\s*$/ ) + { + &MakeFileReadOnly( $filename ); + return; + } + + # We need to edit the file since it is known to be different here. + my $cmd = "p4 edit $changelistarg \"$filename\""; + my @p4output = &RunCommand( $cmd ); + + my $line; + foreach $line ( @p4output ) + { + if( $line =~ m/not on client/ ) + { + #print "notonclient..."; + print "ERROR: @p4output\n"; + return; + } + if( $line =~ m/currently opened for edit/ ) + { + return; + } + if( $line =~ m/opened for edit/ ) + { + print $line; + } + } +} + +sub FileIsWritable +{ + local( $filename ) = shift; + local( @statresult ) = stat $filename; + local( $mode, $iswritable ); + $mode = oct( $statresult[2] ); + $iswritable = ( $mode & 2 ) != 0; + return $iswritable; +} + +sub TouchFile +{ + my $filename = shift; + if( !&FileExists( $filename ) ) + { + if( !open FILE, ">$filename" ) + { + die; + } + close FILE; + } + my $now = time; + local( *FILE ); + utime $now, $now, $filename; +} + +sub FileExistsInPerforce +{ + my $filename = shift; + my @output = &RunCommand( "p4 fstat $filename" ); + my $line; + foreach $line (@output) + { + if( $line =~ m/no such file/ ) + { + return 0; + } + } + return 1; +} + +sub PerforceWriteFile +{ + my $filename = shift; + my $filecontents = shift; +# my $changelistname = shift; + + # Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist. +# my $changelistnumber = `valve_p4_create_changelist.cmd . \"$changelistname\"`; + # Get rid of the newline +# $changelistnumber =~ s/\n//g; + +# my $changelistarg = ""; +# if( $changelistnumber != 0 ) +# { +# $changelistarg = "-c $changelistnumber" +# } + + # Make the target vcs writable if it exists + MakeFileWritable( $filename ); + + # Write the file. + local( *FP ); + open FP, ">$filename"; + print FP $filecontents; + close FP; + + # Do whatever needs to happen with perforce for this file. +# &PerforceEditOrAdd( $filename, $changelistarg ); +} + +sub WriteFile +{ + my $filename = shift; + my $filecontents = shift; + + # Make the target vcs writable if it exists + MakeFileWritable( $filename ); + + # Write the file. + local( *FP ); + open FP, ">$filename"; + print FP $filecontents; + close FP; +} + +sub PrintCleanPerforceOutput +{ + my $line; + while( $line = shift ) + { + if( $line =~ m/currently opened/i ) + { + next; + } + if( $line =~ m/already opened for edit/i ) + { + next; + } + if( $line =~ m/also opened/i ) + { + next; + } + if( $line =~ m/add of existing file/i ) + { + next; + } + print $line; + } +} + +# HACK!!!! Need to pass something in to do this rather than hard coding. +sub NormalizePerforceFilename +{ + my $line = shift; + + # remove newlines. + $line =~ s/\n//; + # downcase. + $line =~ tr/[A-Z]/[a-z]/; + # backslash to forwardslash + $line =~ s,\\,/,g; + + # for inc files HACK! + $line =~ s/^.*(fxctmp9.*)/$1/i; + $line =~ s/^.*(vshtmp9.*)/$1/i; + + # for vcs files. HACK! + $line =~ s,^.*game/hl2/shaders/,,i; + + return $line; +} + +sub MakeSureFileExists +{ + local( $filename ) = shift; + local( $testexists ) = shift; + local( $testwrite ) = shift; + + local( @statresult ) = stat $filename; + if( !@statresult && $testexists ) + { + die "$filename doesn't exist!\n"; + } + local( $mode, $iswritable ); + $mode = oct( $statresult[2] ); + $iswritable = ( $mode & 2 ) != 0; + if( !$iswritable && $testwrite ) + { + die "$filename isn't writable!\n"; + } +} + +sub LoadShaderListFile_GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub LoadShaderListFile_GetShaderSrc +{ + my $shadername = shift; + if ( $shadername =~ m/^(.*)-----/i ) + { + return $1; + } + else + { + return $shadername; + } +} + +sub LoadShaderListFile_GetShaderBase +{ + my $shadername = shift; + if ( $shadername =~ m/-----(.*)$/i ) + { + return $1; + } + else + { + my $shadertype = &LoadShaderListFile_GetShaderType( $shadername ); + $shadername =~ s/\.$shadertype//i; + return $shadername; + } +} + +sub LoadShaderListFile +{ + my $inputbase = shift; + + my @srcfiles; + &MakeSureFileExists( "$inputbase.txt", 1, 0 ); + + open SHADERLISTFILE, "<$inputbase.txt" || die; + my $line; + while( $line = ) + { + $line =~ s/\/\/.*$//; # remove comments "//..." + $line =~ s/^\s*//; # trim leading whitespace + $line =~ s/\s*$//; # trim trailing whitespace + next if( $line =~ m/^\s*$/ ); + if( $line =~ m/\.fxc/ || $line =~ m/\.vsh/ || $line =~ m/\.psh/ ) + { + my $shaderbase = &LoadShaderListFile_GetShaderBase( $line ); + + if( $ENV{"DIRECTX_FORCE_MODEL"} =~ m/^30$/i ) # forcing all shaders to be ver. 30 + { + my $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps30/i; + $targetbase =~ s/_ps20b/_ps30/i; + $targetbase =~ s/_ps20/_ps30/i; + $targetbase =~ s/_vs20/_vs30/i; + $targetbase =~ s/_vsxx/_vs30/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + else + { + if( $shaderbase =~ m/_ps2x/i ) + { + my $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps20/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + + $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps20b/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + elsif( $shaderbase =~ m/_vsxx/i ) + { + my $targetbase = $shaderbase; + $targetbase =~ s/_vsxx/_vs11/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + + $targetbase = $shaderbase; + $targetbase =~ s/_vsxx/_vs20/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + else + { + push @srcfiles, ( $line . "-----" . $shaderbase ); + } + } + } + } + close SHADERLISTFILE; + return @srcfiles; +} + +sub ReadInputFileWithIncludes +{ + local( $filename ) = shift; +# print STDERR "ReadInputFileWithIncludes: $filename\n"; + + local( *INPUT ); + local( $output ); + +# print STDERR "before open\n"; + open INPUT, "<$filename" || die; +# print STDERR "after open\n"; + + local( $line ); + while( $line = ) + { +# print STDERR $line; + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + $output.= ReadInputFileWithIncludes( $1 ); + } + else + { + $output .= $line; + } + } + + close INPUT; + return $output; +} + +sub GetCRCFromSourceFile +{ + my $filename = shift; + my $data = &ReadInputFileWithIncludes( $filename ); +# print STDERR $data; + $crc = crc32( $data ); +# print STDERR "GetCRCFromSourceFile: $crc\n"; + return $crc; +} + +sub GetCRCFromVCSFile +{ + my $filename = shift; +# print STDERR "GetCRCFromVCSFile $filename\n"; + local( *FP ); + open FP, "<$filename" || die "GetCRCFromVCSFile: can't open file $filename\n"; + binmode( FP ); + + # unpack arguments + my $sInt = "i"; + my $uInt = "I"; + if( $filename =~ m/\.360\./ ) + { + # Change arguments to "big endian long" + $sInt = "N"; + $uInt = "N"; + } + + my $header; + read FP, $header, 7 * 4 || die "updateshaders.pl:GetCRCFromVCSFile: can't read header for $filename\n"; + my $version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc; + ($version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc) = unpack "$sInt$sInt$sInt$uInt$uInt$uInt$uInt", $header; + unless( $version == 4 || $version == 5 || $version == 6 ) + { + print STDERR "ERROR: GetCRCFromVCSFile: $filename is version $version\n"; + return 0; + } +# print STDERR "version: $version\n"; +# print STDERR "numCombos: $numCombos\n"; +# print STDERR "numDynamicCombos: $numDynamicCombos\n"; +# print STDERR "flags: $flags\n"; +# print STDERR "centroidMask: $centroidMask\n"; +# print STDERR "refSize: $refSize\n"; +# print STDERR "GetCRCFromVCSFile: $crc\n"; + close( FP ); + return $crc; +} + +sub CheckCRCAgainstTarget +{ + my $srcFileName = shift; + my $vcsFileName = shift; + my $warn = shift; + + # Make sure both files exist. +# print STDERR "$srcFileName doesn't exist\n" if( !( -e $srcFileName ) ); +# print STDERR "$vcsFileName doesn't exist\n" if( !( -e $vcsFileName ) ); + if( !( -e $srcFileName ) ) + { + if( $warn ) + { + print "$srcFileName missing\n"; + } + return 0; + } + if( !( -e $vcsFileName ) ) + { + if( $warn ) + { + print "$vcsFileName missing\n"; + } + return 0; + } +# print STDERR "CheckCRCAgainstTarget( $srcFileName, $vcsFileName );\n"; +# print STDERR "vcsFileName: $vcsFileName\n"; +# print STDERR "vcsFileName: $srcFileName\n"; + my $vcsCRC = &GetCRCFromVCSFile( $vcsFileName ); + my $srcCRC = &GetCRCFromSourceFile( $srcFileName ); + if( $warn && ( $vcsCRC != $srcCRC ) ) + { + print "$vcsFileName checksum ($vcsCRC) != $srcFileName checksum: ($srcCRC)\n"; + } + +# return 0; # use this to skip crc checking. +# if( $vcsCRC == $srcCRC ) +# { +# print STDERR "CRC passed for $srcFileName $vcsFileName $vcsCRC\n"; +# } + return $vcsCRC == $srcCRC; +} + +1; diff --git a/mp/src/devtools/bin/vpc.exe b/mp/src/devtools/bin/vpc.exe index 0c084858..ddc1328c 100644 Binary files a/mp/src/devtools/bin/vpc.exe and b/mp/src/devtools/bin/vpc.exe differ diff --git a/mp/src/devtools/bin/vpc_linux b/mp/src/devtools/bin/vpc_linux index b0302349..d6534046 100755 Binary files a/mp/src/devtools/bin/vpc_linux and b/mp/src/devtools/bin/vpc_linux differ diff --git a/mp/src/devtools/bin/vpc_osx b/mp/src/devtools/bin/vpc_osx index 7194daac..0f9ef14b 100755 Binary files a/mp/src/devtools/bin/vpc_osx and b/mp/src/devtools/bin/vpc_osx differ diff --git a/mp/src/devtools/makefile_base_posix.mak b/mp/src/devtools/makefile_base_posix.mak index f4689c4b..7ad95035 100644 --- a/mp/src/devtools/makefile_base_posix.mak +++ b/mp/src/devtools/makefile_base_posix.mak @@ -1,503 +1,509 @@ -# -# Base makefile for Linux and OSX -# -# !!!!! Note to future editors !!!!! -# -# before you make changes, make sure you grok: -# 1. the difference between =, :=, +=, and ?= -# 2. how and when this base makefile gets included in the generated makefile(s) -# ( see http://www.gnu.org/software/make/manual/make.html#Flavors ) -# -# Command line prefixes: -# - errors are ignored -# @ command is not printed to stdout before being executed -# + command is executed even if Make is invoked in "do not exec" mode - -OS := $(shell uname) -HOSTNAME := $(shell hostname) - --include $(SRCROOT)/devtools/steam_def.mak --include $(SRCROOT)/devtools/sourcesdk_def.mak - -# To build with clang, set the following in your environment: -# CC = clang -# CXX = clang++ - -ifeq ($(CFG), release) - # With gcc 4.6.3, engine.so went from 7,383,765 to 8,429,109 when building with -O3. - # There also was no speed difference running at 1280x1024. May 2012, mikesart. - # tonyp: The size increase was likely caused by -finline-functions and -fipa-cp-clone getting switched on with -O3. - # -fno-omit-frame-pointer: need this for stack traces with perf. - OptimizerLevel_CompilerSpecific = -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer -ftree-vectorize -fpredictive-commoning -funswitch-loops -else - OptimizerLevel_CompilerSpecific = -O0 - #-O1 -finline-functions -endif - -# CPPFLAGS == "c/c++ *preprocessor* flags" - not "cee-plus-plus flags" -ARCH_FLAGS = -BUILDING_MULTI_ARCH = 0 -CPPFLAGS = $(DEFINES) $(addprefix -I, $(abspath $(INCLUDEDIRS) )) -CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE -CXXFLAGS = $(CFLAGS) -DEFINES += -DVPROF_LEVEL=1 -DGNUC -DNO_HOOK_MALLOC -DNO_MALLOC_OVERRIDE -LDFLAGS = $(CFLAGS) $(GCC_ExtraLinkerFlags) $(OptimizerLevel) -GENDEP_CXXFLAGS = -MD -MP -MF $(@:.o=.P) -MAP_FLAGS = -Srv_GAMEOUTPUTFILE = -COPY_DLL_TO_SRV = 0 - - -ifeq ($(STEAM_BRANCH),1) - WARN_FLAGS = -Wall -Wextra -Wshadow -Wno-invalid-offsetof -else - WARN_FLAGS = -Wno-write-strings -Wno-multichar -endif - -WARN_FLAGS += -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Werror=return-type -fdiagnostics-show-option -Wformat -Wformat-security - - -ifeq ($(OS),Linux) - # We should always specify -Wl,--build-id, as documented at: - # http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId - LDFLAGS += -Wl,--build-id - # Set USE_VALVE_BINDIR to build with /Steam/tools/linux in the /valve/bin path. - # Dedicated server uses this. - ifeq ($(USE_VALVE_BINDIR),1) - # dedicated server flags - ifeq ($(TARGET_PLATFORM),linux64) - VALVE_BINDIR = /valve/bin64/ - MARCH_TARGET = nocona - else - VALVE_BINDIR = /valve/bin/ - MARCH_TARGET = pentium4 - endif - STRIP_FLAGS = - else - # linux desktop client flags - VALVE_BINDIR = - # If the steam-runtime is available, use it. We should just default to using it when - # buildbot and everyone has a bit of time to get it installed. - ifneq "$(wildcard /valve/steam-runtime/bin/)" "" - # The steam-runtime is incompatible with clang at this point, so disable it - # if clang is enabled. - ifneq ($(CXX),clang++) - VALVE_BINDIR = /valve/steam-runtime/bin/ - endif - endif - GCC_VER = - MARCH_TARGET = pentium4 - # On dedicated servers, some plugins depend on global variable symbols in addition to functions. - # So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2. - STRIP_FLAGS = -x - endif - - ifeq ($(CXX),clang++) - # Clang does not support -mfpmath=sse because it uses whatever - # instruction set extensions are available by default. - SSE_GEN_FLAGS = -msse2 - else - SSE_GEN_FLAGS = -msse2 -mfpmath=sse - endif - - CCACHE := $(SRCROOT)/devtools/bin/linux/ccache - - ifeq ($(origin GCC_VER), undefined) - GCC_VER=-4.6 - endif - ifeq ($(origin AR), default) - AR = $(VALVE_BINDIR)ar crs - endif - ifeq ($(origin CC),default) - CC = $(CCACHE) $(VALVE_BINDIR)gcc$(GCC_VER) - endif - ifeq ($(origin CXX), default) - CXX = $(CCACHE) $(VALVE_BINDIR)g++$(GCC_VER) - endif - # Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to - # a ccache quirk. Could also upgrade ccache. - # http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html - ifeq ($(CC),clang) - CC = $(CCACHE) $(VALVE_BINDIR)clang -Qunused-arguments - endif - ifeq ($(CXX),clang++) - CXX = $(CCACHE) $(VALVE_BINDIR)clang++ -Qunused-arguments - endif - LINK ?= $(CC) - - ifeq ($(TARGET_PLATFORM),linux64) - # nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2) - ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2 - LD_SO = ld-linux-x86_64.so.2 - LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.a) - LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++-pic.a) - else - # pentium4 = MMX, SSE, SSE2 - no SSE3 (added in prescott) # -msse3 -mfpmath=sse - ARCH_FLAGS += -m32 -march=$(MARCH_TARGET) -mtune=core2 $(SSE_GEN_FLAGS) - LD_SO = ld-linux.so.2 - LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) - LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) - LDFLAGS += -m32 - endif - - GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh - ifeq ($(CFG),release) - STRIP ?= strip $(STRIP_FLAGS) -S - # CFLAGS += -ffunction-sections -fdata-sections - # LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections - else - STRIP ?= true - endif - VSIGN ?= true - - ifeq ($(SOURCE_SDK), 1) - Srv_GAMEOUTPUTFILE := $(GAMEOUTPUTFILE:.so=_srv.so) - COPY_DLL_TO_SRC := 1 - endif - - LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map - - SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined - - _WRAP := -Xlinker --wrap= - PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \ - $(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \ - $(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \ - $(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \ - $(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath - - LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group - LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread - - LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group - LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt - -endif - -ifeq ($(OS),Darwin) - CCACHE := $(SRCROOT)/devtools/bin/osx32/ccache - MAC_SDK_VER ?= 10.6 - MAC_SDK := macosx$(MAC_SDK_VER) - SYSROOT := $(shell xcodebuild -sdk $(MAC_SDK) -version Path) - - ifneq ($(origin MAC_SDK_VER), file) - $(warning Attempting build with SDK version $(MAC_SDK_VER), only 10.6 is supported and recommended!) - endif - - ifeq ($(SYSROOT),) - FIRSTSDK := $(firstword $(sort $(shell xcodebuild -showsdks | grep macosx | sed 's/.*macosx//'))) - $(error Could not find SDK version $(MAC_SDK_VER). Install and configure Xcode 4.3, or build with: make MAC_SDK_VER=$(FIRSTSDK)) - endif - - ifeq ($(origin CC), default) - # Test to see if you have a compiler in the right place, if you - # don't abort with an error - CLANG := $(shell xcrun -sdk $(MAC_SDK) -find clang) - ifeq ($(wildcard $(CLANG)),) - $(error Unable to find C compiler, install and configure Xcode 4.3) - endif - - CC := $(CCACHE) $(CLANG) -Qunused-arguments - endif - - ifeq ($(origin CXX), default) - CXXLANG := $(shell xcrun -sdk $(MAC_SDK) -find clang++) - ifeq ($(wildcard $(CXXLANG)),) - $(error Unable to find C++ compiler, install and configure Xcode 4.3) - endif - - CXX := $(CCACHE) $(CXXLANG) -Qunused-arguments - endif - LINK ?= $(CXX) - - ifeq ($(origin AR), default) - AR := $(shell xcrun -sdk $(MAC_SDK) -find libtool) -static -o - endif - - ifeq ($(TARGET_PLATFORM),osx64) - ARCH_FLAGS += -arch x86_64 -m64 -march=core2 - else ifeq (,$(findstring -arch x86_64,$(GCC_ExtraCompilerFlags))) - ARCH_FLAGS += -arch i386 -m32 -march=prescott -momit-leaf-frame-pointer -mtune=core2 - else - # dirty hack to build a universal binary - don't specify the architecture - ARCH_FLAGS += -arch i386 -Xarch_i386 -march=prescott -Xarch_i386 -mtune=core2 -Xarch_i386 -momit-leaf-frame-pointer -Xarch_x86_64 -march=core2 - endif - - GEN_SYM ?= $(shell xcrun -sdk $(MAC_SDK) -find dsymutil) - ifeq ($(CFG),release) - STRIP ?= strip -S - else - STRIP ?= true - endif - ifeq ($(SOURCE_SDK), 1) - VSIGN ?= true - else - VSIGN ?= $(SRCROOT)/devtools/bin/vsign - endif - - CPPFLAGS += -I$(SYSROOT)/usr/include/malloc - CFLAGS += -isysroot $(SYSROOT) -mmacosx-version-min=10.5 -fasm-blocks - - LIB_START_EXE = -lm -ldl -lpthread - LIB_END_EXE = - - LIB_START_SHLIB = - LIB_END_SHLIB = - - SHLIBLDFLAGS = $(LDFLAGS) -bundle -flat_namespace -undefined suppress -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms - - ifeq (lib,$(findstring lib,$(GAMEOUTPUTFILE))) - SHLIBLDFLAGS = $(LDFLAGS) -dynamiclib -current_version 1.0 -compatibility_version 1.0 -install_name @rpath/$(basename $(notdir $(GAMEOUTPUTFILE))).dylib $(SystemLibraries) -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms - endif - -endif - -# -# Profile-directed optimizations. -# Note: Last time these were tested 3/5/08, it actually slowed down the server benchmark by 5%! -# -# First, uncomment these, build, and test. It will generate .gcda and .gcno files where the .o files are. -# PROFILE_LINKER_FLAG=-fprofile-arcs -# PROFILE_COMPILER_FLAG=-fprofile-arcs -# -# Then, comment the above flags out again and rebuild with this flag uncommented: -# PROFILE_COMPILER_FLAG=-fprofile-use -# - -############################################################################# -# The compiler command lne for each src code file to compile -############################################################################# - -OBJ_DIR = ./obj_$(NAME)_$(TARGET_PLATFORM)$(TARGET_PLATFORM_EXT)/$(CFG) -CPP_TO_OBJ = $(CPPFILES:.cpp=.o) -CXX_TO_OBJ = $(CPP_TO_OBJ:.cxx=.o) -CC_TO_OBJ = $(CXX_TO_OBJ:.cc=.o) -MM_TO_OBJ = $(CC_TO_OBJ:.mm=.o) -C_TO_OBJ = $(MM_TO_OBJ:.c=.o) -OBJS = $(addprefix $(OBJ_DIR)/, $(notdir $(C_TO_OBJ))) - -ifeq ($(MAKE_VERBOSE),1) - QUIET_PREFIX = - QUIET_ECHO_POSTFIX = -else - QUIET_PREFIX = @ - QUIET_ECHO_POSTFIX = > /dev/null -endif - -ifeq ($(MAKE_CC_VERBOSE),1) -CC += -v -endif - -ifeq ($(CONFTYPE),lib) - LIB_File = $(OUTPUTFILE) -endif - -ifeq ($(CONFTYPE),dll) - SO_File = $(OUTPUTFILE) -endif - -ifeq ($(CONFTYPE),exe) - EXE_File = $(OUTPUTFILE) -endif - -# we generate dependencies as a side-effect of compilation now -GEN_DEP_FILE= - -PRE_COMPILE_FILE = - -POST_COMPILE_FILE = - -ifeq ($(BUILDING_MULTI_ARCH),1) - SINGLE_ARCH_CXXFLAGS=$(subst -arch x86_64,,$(CXXFLAGS)) - COMPILE_FILE = \ - $(QUIET_PREFIX) \ - echo "---- $(lastword $(subst /, ,$<)) as MULTIARCH----";\ - mkdir -p $(OBJ_DIR) && \ - $(CXX) $(SINGLE_ARCH_CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< && \ - $(CXX) $(CXXFLAGS) -o $@ -c $< -else - COMPILE_FILE = \ - $(QUIET_PREFIX) \ - echo "---- $(lastword $(subst /, ,$<)) ----";\ - mkdir -p $(OBJ_DIR) && \ - $(CXX) $(CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< -endif - -ifneq "$(origin VALVE_NO_AUTO_P4)" "undefined" - P4_EDIT_START = chmod -R +w - P4_EDIT_END = || true - P4_REVERT_START = true - P4_REVERT_END = -else - ifndef P4_EDIT_CHANGELIST - # You can use an environment variable to specify what changelist to check the Linux Binaries out into. Normally the default - # setting is best, but here is an alternate example: - # export P4_EDIT_CHANGELIST_CMD="echo 1424335" - # ?= means that if P4_EDIT_CHANGELIST_CMD is already set it won't be changed. - P4_EDIT_CHANGELIST_CMD ?= p4 changes -c `p4 client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1 - P4_EDIT_CHANGELIST := $(shell $(P4_EDIT_CHANGELIST_CMD)) - endif - ifeq ($(P4_EDIT_CHANGELIST),) - # If we haven't found a changelist to check out to then create one. The name must match the one from a few - # lines above or else a new changelist will be created each time. - # Warning: the behavior of 'echo' is not consistent. In bash you need the "-e" option in order for \n to be - # interpreted as a line-feed, but in dash you do not, and if "-e" is passed along then it is printed, which - # confuses p4. So, if you run this command from the bash shell don't forget to add "-e" to the echo command. - P4_EDIT_CHANGELIST = $(shell echo "Change: new\nDescription: POSIX Auto Checkout" | p4 change -i | cut -f 2 -d ' ') - endif - - P4_EDIT_START := for f in - P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - edit -c $(P4_EDIT_CHANGELIST); else p4 edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) - P4_REVERT_START := for f in - P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - revert; else p4 revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) -endif - -ifeq ($(CONFTYPE),dll) -all: $(OTHER_DEPENDENCIES) $(OBJS) $(GAMEOUTPUTFILE) - @echo $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX) -else -all: $(OTHER_DEPENDENCIES) $(OBJS) $(OUTPUTFILE) - @echo $(OUTPUTFILE) $(QUIET_ECHO_POSTFIX) -endif - -.PHONY: clean cleantargets cleanandremove rebuild relink RemoveOutputFile SingleFile - - -rebuild : - $(MAKE) -f $(firstword $(MAKEFILE_LIST)) cleanandremove - $(MAKE) -f $(firstword $(MAKEFILE_LIST)) - - -# Use the relink target to force to relink the project. -relink: RemoveOutputFile all - -RemoveOutputFile: - rm -f $(OUTPUTFILE) - - -# This rule is so you can say "make SingleFile SingleFilename=/home/myname/valve_main/src/engine/language.cpp" and have it only build that file. -# It basically just translates the full filename to create a dependency on the appropriate .o file so it'll build that. -SingleFile : RemoveSingleFile $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o - @echo "" - -RemoveSingleFile: - $(QUIET_PREFIX) rm -f $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o - -clean: -ifneq "$(OBJ_DIR)" "" - $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)" - $(QUIET_PREFIX) rm -rf $(OBJ_DIR) -endif -ifneq "$(OUTPUTFILE)" "" - $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ - echo "p4 revert $(OUTPUTFILE)"; \ - $(P4_REVERT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END); \ - fi; -endif -ifneq "$(OTHER_DEPENDENCIES)" "" - $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)" - $(QUIET_PREFIX) rm -f $(OTHER_DEPENDENCIES) -endif -ifneq "$(GAMEOUTPUTFILE)" "" - $(QUIET_PREFIX) echo "p4 revert $(GAMEOUTPUTFILE)" - $(QUIET_PREFIX) $(P4_REVERT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END) -endif - - -# Do the above cleaning, except with p4 edit and rm. Reason being ar crs adds and replaces obj files to the -# archive. However if you've renamed or deleted a source file, $(AR) won't remove it. This can leave -# us with archive files that have extra unused symbols, and also potentially cause compilation errors -# when you rename a file and have many duplicate symbols. -cleanandremove: -ifneq "$(OBJ_DIR)" "" - $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)" - $(QUIET_PREFIX) -rm -rf $(OBJ_DIR) -endif -ifneq "$(OUTPUTFILE)" "" - $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ - echo "p4 edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \ - $(P4_EDIT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); \ - fi; - $(QUIET_PREFIX) -rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT); -endif -ifneq "$(OTHER_DEPENDENCIES)" "" - $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)" - $(QUIET_PREFIX) -rm -f $(OTHER_DEPENDENCIES) -endif -ifneq "$(GAMEOUTPUTFILE)" "" - $(QUIET_PREFIX) echo "p4 edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)" - $(QUIET_PREFIX) $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END) - $(QUIET_PREFIX) -rm -f $(GAMEOUTPUTFILE) -endif - - -# This just deletes the final targets so it'll do a relink next time we build. -cleantargets: - $(QUIET_PREFIX) rm -f $(OUTPUTFILE) $(GAMEOUTPUTFILE) - - -$(LIB_File): $(OTHER_DEPENDENCIES) $(OBJS) - $(QUIET_PREFIX) -$(P4_EDIT_START) $(LIB_File) $(P4_EDIT_END); - $(QUIET_PREFIX) $(AR) $(LIB_File) $(OBJS) $(LIBFILES); - -SO_GameOutputFile = $(GAMEOUTPUTFILE) - -# Remove the target before installing a file over it; this prevents existing -# instances of the game from crashing due to the overwrite. -$(SO_GameOutputFile): $(SO_File) - $(QUIET_PREFIX) \ - $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END) && \ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- COPYING TO $@ [$(CFG)] ----";\ - echo "----" $(QUIET_ECHO_POSTFIX); - $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END); - $(QUIET_PREFIX) -mkdir -p `dirname $(GAMEOUTPUTFILE)` > /dev/null; - $(QUIET_PREFIX) rm -f $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX); - $(QUIET_PREFIX) cp -v $(OUTPUTFILE) $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX); - $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); - $(QUIET_PREFIX) $(GEN_SYM) $(GAMEOUTPUTFILE); - $(QUIET_PREFIX) -$(STRIP) $(GAMEOUTPUTFILE); - $(QUIET_PREFIX) $(VSIGN) -signvalve $(GAMEOUTPUTFILE); - $(QUIET_PREFIX) if [ "$(COPY_DLL_TO_SRV)" = "1" ]; then\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- COPYING TO $(Srv_GAMEOUTPUTFILE) ----";\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - cp -v $(GAMEOUTPUTFILE) $(Srv_GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);\ - cp -v $(GAMEOUTPUTFILE)$(SYM_EXT) $(Srv_GAMEOUTPUTFILE)$(SYM_EXT) $(QUIET_ECHO_POSTFIX);\ - fi; - $(QUIET_PREFIX) if [ "$(IMPORTLIBRARY)" != "" ]; then\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- COPYING TO IMPORT LIBRARY $(IMPORTLIBRARY) ----";\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - $(P4_EDIT_START) $(IMPORTLIBRARY) $(P4_EDIT_END) && \ - mkdir -p `dirname $(IMPORTLIBRARY)` > /dev/null && \ - cp -v $(OUTPUTFILE) $(IMPORTLIBRARY); \ - fi; - - -$(SO_File): $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES) - $(QUIET_PREFIX) \ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- LINKING $@ [$(CFG)] ----";\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - \ - $(LINK) $(LINK_MAP_FLAGS) $(SHLIBLDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_SHLIB) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_SHLIB); - $(VSIGN) -signvalve $(OUTPUTFILE); - - -$(EXE_File) : $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES) - $(QUIET_PREFIX) \ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- LINKING EXE $@ [$(CFG)] ----";\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - \ - $(P4_EDIT_START) $(OUTPUTFILE) $(P4_EDIT_END);\ - $(LINK) $(LINK_MAP_FLAGS) $(LDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_EXE) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_EXE); - $(QUIET_PREFIX) -$(P4_EDIT_START) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); - $(QUIET_PREFIX) $(GEN_SYM) $(OUTPUTFILE); - $(QUIET_PREFIX) -$(STRIP) $(OUTPUTFILE); - $(QUIET_PREFIX) $(VSIGN) -signvalve $(OUTPUTFILE); - - -tags: - etags -a -C -o $(SRCROOT)/TAGS *.cpp *.cxx *.h *.hxx +# +# Base makefile for Linux and OSX +# +# !!!!! Note to future editors !!!!! +# +# before you make changes, make sure you grok: +# 1. the difference between =, :=, +=, and ?= +# 2. how and when this base makefile gets included in the generated makefile(s) +# ( see http://www.gnu.org/software/make/manual/make.html#Flavors ) +# +# Command line prefixes: +# - errors are ignored +# @ command is not printed to stdout before being executed +# + command is executed even if Make is invoked in "do not exec" mode + +OS := $(shell uname) +HOSTNAME := $(shell hostname) + +-include $(SRCROOT)/devtools/steam_def.mak +-include $(SRCROOT)/devtools/sourcesdk_def.mak + +# To build with clang, set the following in your environment: +# CC = clang +# CXX = clang++ + +ifeq ($(CFG), release) + # With gcc 4.6.3, engine.so went from 7,383,765 to 8,429,109 when building with -O3. + # There also was no speed difference running at 1280x1024. May 2012, mikesart. + # tonyp: The size increase was likely caused by -finline-functions and -fipa-cp-clone getting switched on with -O3. + # -fno-omit-frame-pointer: need this for stack traces with perf. + OptimizerLevel_CompilerSpecific = -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer -ftree-vectorize -fpredictive-commoning -funswitch-loops +else + OptimizerLevel_CompilerSpecific = -O0 + #-O1 -finline-functions +endif + +# CPPFLAGS == "c/c++ *preprocessor* flags" - not "cee-plus-plus flags" +ARCH_FLAGS = +BUILDING_MULTI_ARCH = 0 +CPPFLAGS = $(DEFINES) $(addprefix -I, $(abspath $(INCLUDEDIRS) )) +CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE +# In -std=gnu++0x mode we get lots of errors about "error: narrowing conversion". -fpermissive +# turns these into warnings in gcc, and -Wno-c++11-narrowing suppresses them entirely in clang 3.1+. +ifeq ($(CXX),clang++) + CXXFLAGS = $(CFLAGS) -Wno-c++11-narrowing -Wno-dangling-else +else + CXXFLAGS = $(CFLAGS) -fpermissive +endif +DEFINES += -DVPROF_LEVEL=1 -DGNUC -DNO_HOOK_MALLOC -DNO_MALLOC_OVERRIDE +LDFLAGS = $(CFLAGS) $(GCC_ExtraLinkerFlags) $(OptimizerLevel) +GENDEP_CXXFLAGS = -MD -MP -MF $(@:.o=.P) +MAP_FLAGS = +Srv_GAMEOUTPUTFILE = +COPY_DLL_TO_SRV = 0 + + +ifeq ($(STEAM_BRANCH),1) + WARN_FLAGS = -Wall -Wextra -Wshadow -Wno-invalid-offsetof +else + WARN_FLAGS = -Wno-write-strings -Wno-multichar +endif + +WARN_FLAGS += -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Werror=return-type -fdiagnostics-show-option -Wformat -Wformat-security + + +ifeq ($(OS),Linux) + # We should always specify -Wl,--build-id, as documented at: + # http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId + LDFLAGS += -Wl,--build-id + # Set USE_VALVE_BINDIR to build with /Steam/tools/linux in the /valve/bin path. + # Dedicated server uses this. + ifeq ($(USE_VALVE_BINDIR),1) + # dedicated server flags + ifeq ($(TARGET_PLATFORM),linux64) + VALVE_BINDIR = /valve/bin64/ + MARCH_TARGET = nocona + else + VALVE_BINDIR = /valve/bin/ + MARCH_TARGET = pentium4 + endif + STRIP_FLAGS = + else + # linux desktop client flags + VALVE_BINDIR = + # If the steam-runtime is available, use it. We should just default to using it when + # buildbot and everyone has a bit of time to get it installed. + ifneq "$(wildcard /valve/steam-runtime/bin/)" "" + # The steam-runtime is incompatible with clang at this point, so disable it + # if clang is enabled. + ifneq ($(CXX),clang++) + VALVE_BINDIR = /valve/steam-runtime/bin/ + endif + endif + GCC_VER = + MARCH_TARGET = pentium4 + # On dedicated servers, some plugins depend on global variable symbols in addition to functions. + # So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2. + STRIP_FLAGS = -x + endif + + ifeq ($(CXX),clang++) + # Clang does not support -mfpmath=sse because it uses whatever + # instruction set extensions are available by default. + SSE_GEN_FLAGS = -msse2 + else + SSE_GEN_FLAGS = -msse2 -mfpmath=sse + endif + + CCACHE := $(SRCROOT)/devtools/bin/linux/ccache + + ifeq ($(origin GCC_VER), undefined) + GCC_VER=-4.6 + endif + ifeq ($(origin AR), default) + AR = $(VALVE_BINDIR)ar crs + endif + ifeq ($(origin CC),default) + CC = $(CCACHE) $(VALVE_BINDIR)gcc$(GCC_VER) + endif + ifeq ($(origin CXX), default) + CXX = $(CCACHE) $(VALVE_BINDIR)g++$(GCC_VER) + endif + # Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to + # a ccache quirk. Could also upgrade ccache. + # http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html + ifeq ($(CC),clang) + CC = $(CCACHE) $(VALVE_BINDIR)clang -Qunused-arguments + endif + ifeq ($(CXX),clang++) + CXX = $(CCACHE) $(VALVE_BINDIR)clang++ -Qunused-arguments + endif + LINK ?= $(CC) + + ifeq ($(TARGET_PLATFORM),linux64) + # nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2) + ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2 + LD_SO = ld-linux-x86_64.so.2 + LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.a) + LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++-pic.a) + else + # pentium4 = MMX, SSE, SSE2 - no SSE3 (added in prescott) # -msse3 -mfpmath=sse + ARCH_FLAGS += -m32 -march=$(MARCH_TARGET) -mtune=core2 $(SSE_GEN_FLAGS) + LD_SO = ld-linux.so.2 + LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) + LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) + LDFLAGS += -m32 + endif + + GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh + ifeq ($(CFG),release) + STRIP ?= strip $(STRIP_FLAGS) -S + # CFLAGS += -ffunction-sections -fdata-sections + # LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections + else + STRIP ?= true + endif + VSIGN ?= true + + ifeq ($(SOURCE_SDK), 1) + Srv_GAMEOUTPUTFILE := $(GAMEOUTPUTFILE:.so=_srv.so) + COPY_DLL_TO_SRV := 1 + endif + + LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map + + SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined + + _WRAP := -Xlinker --wrap= + PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \ + $(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \ + $(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \ + $(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \ + $(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath + + LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group + LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread + + LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group + LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt + +endif + +ifeq ($(OS),Darwin) + CCACHE := $(SRCROOT)/devtools/bin/osx32/ccache + MAC_SDK_VER ?= 10.6 + MAC_SDK := macosx$(MAC_SDK_VER) + SYSROOT := $(shell xcodebuild -sdk $(MAC_SDK) -version Path) + + ifneq ($(origin MAC_SDK_VER), file) + $(warning Attempting build with SDK version $(MAC_SDK_VER), only 10.6 is supported and recommended!) + endif + + ifeq ($(SYSROOT),) + FIRSTSDK := $(firstword $(sort $(shell xcodebuild -showsdks | grep macosx | sed 's/.*macosx//'))) + $(error Could not find SDK version $(MAC_SDK_VER). Install and configure Xcode 4.3, or build with: make MAC_SDK_VER=$(FIRSTSDK)) + endif + + ifeq ($(origin CC), default) + # Test to see if you have a compiler in the right place, if you + # don't abort with an error + CLANG := $(shell xcrun -sdk $(MAC_SDK) -find clang) + ifeq ($(wildcard $(CLANG)),) + $(error Unable to find C compiler, install and configure Xcode 4.3) + endif + + CC := $(CCACHE) $(CLANG) -Qunused-arguments + endif + + ifeq ($(origin CXX), default) + CXXLANG := $(shell xcrun -sdk $(MAC_SDK) -find clang++) + ifeq ($(wildcard $(CXXLANG)),) + $(error Unable to find C++ compiler, install and configure Xcode 4.3) + endif + + CXX := $(CCACHE) $(CXXLANG) -Qunused-arguments + endif + LINK ?= $(CXX) + + ifeq ($(origin AR), default) + AR := $(shell xcrun -sdk $(MAC_SDK) -find libtool) -static -o + endif + + ifeq ($(TARGET_PLATFORM),osx64) + ARCH_FLAGS += -arch x86_64 -m64 -march=core2 + else ifeq (,$(findstring -arch x86_64,$(GCC_ExtraCompilerFlags))) + ARCH_FLAGS += -arch i386 -m32 -march=prescott -momit-leaf-frame-pointer -mtune=core2 + else + # dirty hack to build a universal binary - don't specify the architecture + ARCH_FLAGS += -arch i386 -Xarch_i386 -march=prescott -Xarch_i386 -mtune=core2 -Xarch_i386 -momit-leaf-frame-pointer -Xarch_x86_64 -march=core2 + endif + + GEN_SYM ?= $(shell xcrun -sdk $(MAC_SDK) -find dsymutil) + ifeq ($(CFG),release) + STRIP ?= strip -S + else + STRIP ?= true + endif + ifeq ($(SOURCE_SDK), 1) + VSIGN ?= true + else + VSIGN ?= $(SRCROOT)/devtools/bin/vsign + endif + + CPPFLAGS += -I$(SYSROOT)/usr/include/malloc + CFLAGS += -isysroot $(SYSROOT) -mmacosx-version-min=10.5 -fasm-blocks + + LIB_START_EXE = -lm -ldl -lpthread + LIB_END_EXE = + + LIB_START_SHLIB = + LIB_END_SHLIB = + + SHLIBLDFLAGS = $(LDFLAGS) -bundle -flat_namespace -undefined suppress -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms + + ifeq (lib,$(findstring lib,$(GAMEOUTPUTFILE))) + SHLIBLDFLAGS = $(LDFLAGS) -dynamiclib -current_version 1.0 -compatibility_version 1.0 -install_name @rpath/$(basename $(notdir $(GAMEOUTPUTFILE))).dylib $(SystemLibraries) -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms + endif + +endif + +# +# Profile-directed optimizations. +# Note: Last time these were tested 3/5/08, it actually slowed down the server benchmark by 5%! +# +# First, uncomment these, build, and test. It will generate .gcda and .gcno files where the .o files are. +# PROFILE_LINKER_FLAG=-fprofile-arcs +# PROFILE_COMPILER_FLAG=-fprofile-arcs +# +# Then, comment the above flags out again and rebuild with this flag uncommented: +# PROFILE_COMPILER_FLAG=-fprofile-use +# + +############################################################################# +# The compiler command lne for each src code file to compile +############################################################################# + +OBJ_DIR = ./obj_$(NAME)_$(TARGET_PLATFORM)$(TARGET_PLATFORM_EXT)/$(CFG) +CPP_TO_OBJ = $(CPPFILES:.cpp=.o) +CXX_TO_OBJ = $(CPP_TO_OBJ:.cxx=.o) +CC_TO_OBJ = $(CXX_TO_OBJ:.cc=.o) +MM_TO_OBJ = $(CC_TO_OBJ:.mm=.o) +C_TO_OBJ = $(MM_TO_OBJ:.c=.o) +OBJS = $(addprefix $(OBJ_DIR)/, $(notdir $(C_TO_OBJ))) + +ifeq ($(MAKE_VERBOSE),1) + QUIET_PREFIX = + QUIET_ECHO_POSTFIX = +else + QUIET_PREFIX = @ + QUIET_ECHO_POSTFIX = > /dev/null +endif + +ifeq ($(MAKE_CC_VERBOSE),1) +CC += -v +endif + +ifeq ($(CONFTYPE),lib) + LIB_File = $(OUTPUTFILE) +endif + +ifeq ($(CONFTYPE),dll) + SO_File = $(OUTPUTFILE) +endif + +ifeq ($(CONFTYPE),exe) + EXE_File = $(OUTPUTFILE) +endif + +# we generate dependencies as a side-effect of compilation now +GEN_DEP_FILE= + +PRE_COMPILE_FILE = + +POST_COMPILE_FILE = + +ifeq ($(BUILDING_MULTI_ARCH),1) + SINGLE_ARCH_CXXFLAGS=$(subst -arch x86_64,,$(CXXFLAGS)) + COMPILE_FILE = \ + $(QUIET_PREFIX) \ + echo "---- $(lastword $(subst /, ,$<)) as MULTIARCH----";\ + mkdir -p $(OBJ_DIR) && \ + $(CXX) $(SINGLE_ARCH_CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< && \ + $(CXX) $(CXXFLAGS) -o $@ -c $< +else + COMPILE_FILE = \ + $(QUIET_PREFIX) \ + echo "---- $(lastword $(subst /, ,$<)) ----";\ + mkdir -p $(OBJ_DIR) && \ + $(CXX) $(CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< +endif + +ifneq "$(origin VALVE_NO_AUTO_P4)" "undefined" + P4_EDIT_START = chmod -R +w + P4_EDIT_END = || true + P4_REVERT_START = true + P4_REVERT_END = +else + ifndef P4_EDIT_CHANGELIST + # You can use an environment variable to specify what changelist to check the Linux Binaries out into. Normally the default + # setting is best, but here is an alternate example: + # export P4_EDIT_CHANGELIST_CMD="echo 1424335" + # ?= means that if P4_EDIT_CHANGELIST_CMD is already set it won't be changed. + P4_EDIT_CHANGELIST_CMD ?= p4 changes -c `p4 client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1 + P4_EDIT_CHANGELIST := $(shell $(P4_EDIT_CHANGELIST_CMD)) + endif + ifeq ($(P4_EDIT_CHANGELIST),) + # If we haven't found a changelist to check out to then create one. The name must match the one from a few + # lines above or else a new changelist will be created each time. + # Warning: the behavior of 'echo' is not consistent. In bash you need the "-e" option in order for \n to be + # interpreted as a line-feed, but in dash you do not, and if "-e" is passed along then it is printed, which + # confuses p4. So, if you run this command from the bash shell don't forget to add "-e" to the echo command. + P4_EDIT_CHANGELIST = $(shell echo "Change: new\nDescription: POSIX Auto Checkout" | p4 change -i | cut -f 2 -d ' ') + endif + + P4_EDIT_START := for f in + P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - edit -c $(P4_EDIT_CHANGELIST); else p4 edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) + P4_REVERT_START := for f in + P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - revert; else p4 revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) +endif + +ifeq ($(CONFTYPE),dll) +all: $(OTHER_DEPENDENCIES) $(OBJS) $(GAMEOUTPUTFILE) + @echo $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX) +else +all: $(OTHER_DEPENDENCIES) $(OBJS) $(OUTPUTFILE) + @echo $(OUTPUTFILE) $(QUIET_ECHO_POSTFIX) +endif + +.PHONY: clean cleantargets cleanandremove rebuild relink RemoveOutputFile SingleFile + + +rebuild : + $(MAKE) -f $(firstword $(MAKEFILE_LIST)) cleanandremove + $(MAKE) -f $(firstword $(MAKEFILE_LIST)) + + +# Use the relink target to force to relink the project. +relink: RemoveOutputFile all + +RemoveOutputFile: + rm -f $(OUTPUTFILE) + + +# This rule is so you can say "make SingleFile SingleFilename=/home/myname/valve_main/src/engine/language.cpp" and have it only build that file. +# It basically just translates the full filename to create a dependency on the appropriate .o file so it'll build that. +SingleFile : RemoveSingleFile $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o + @echo "" + +RemoveSingleFile: + $(QUIET_PREFIX) rm -f $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o + +clean: +ifneq "$(OBJ_DIR)" "" + $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)" + $(QUIET_PREFIX) rm -rf $(OBJ_DIR) +endif +ifneq "$(OUTPUTFILE)" "" + $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ + echo "p4 revert $(OUTPUTFILE)"; \ + $(P4_REVERT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END); \ + fi; +endif +ifneq "$(OTHER_DEPENDENCIES)" "" + $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)" + $(QUIET_PREFIX) rm -f $(OTHER_DEPENDENCIES) +endif +ifneq "$(GAMEOUTPUTFILE)" "" + $(QUIET_PREFIX) echo "p4 revert $(GAMEOUTPUTFILE)" + $(QUIET_PREFIX) $(P4_REVERT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END) +endif + + +# Do the above cleaning, except with p4 edit and rm. Reason being ar crs adds and replaces obj files to the +# archive. However if you've renamed or deleted a source file, $(AR) won't remove it. This can leave +# us with archive files that have extra unused symbols, and also potentially cause compilation errors +# when you rename a file and have many duplicate symbols. +cleanandremove: +ifneq "$(OBJ_DIR)" "" + $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)" + $(QUIET_PREFIX) -rm -rf $(OBJ_DIR) +endif +ifneq "$(OUTPUTFILE)" "" + $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ + echo "p4 edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \ + $(P4_EDIT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); \ + fi; + $(QUIET_PREFIX) -rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT); +endif +ifneq "$(OTHER_DEPENDENCIES)" "" + $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)" + $(QUIET_PREFIX) -rm -f $(OTHER_DEPENDENCIES) +endif +ifneq "$(GAMEOUTPUTFILE)" "" + $(QUIET_PREFIX) echo "p4 edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)" + $(QUIET_PREFIX) $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END) + $(QUIET_PREFIX) -rm -f $(GAMEOUTPUTFILE) +endif + + +# This just deletes the final targets so it'll do a relink next time we build. +cleantargets: + $(QUIET_PREFIX) rm -f $(OUTPUTFILE) $(GAMEOUTPUTFILE) + + +$(LIB_File): $(OTHER_DEPENDENCIES) $(OBJS) + $(QUIET_PREFIX) -$(P4_EDIT_START) $(LIB_File) $(P4_EDIT_END); + $(QUIET_PREFIX) $(AR) $(LIB_File) $(OBJS) $(LIBFILES); + +SO_GameOutputFile = $(GAMEOUTPUTFILE) + +# Remove the target before installing a file over it; this prevents existing +# instances of the game from crashing due to the overwrite. +$(SO_GameOutputFile): $(SO_File) + $(QUIET_PREFIX) \ + $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END) && \ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- COPYING TO $@ [$(CFG)] ----";\ + echo "----" $(QUIET_ECHO_POSTFIX); + $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END); + $(QUIET_PREFIX) -mkdir -p `dirname $(GAMEOUTPUTFILE)` > /dev/null; + $(QUIET_PREFIX) rm -f $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX); + $(QUIET_PREFIX) cp -v $(OUTPUTFILE) $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX); + $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); + $(QUIET_PREFIX) $(GEN_SYM) $(GAMEOUTPUTFILE); + $(QUIET_PREFIX) -$(STRIP) $(GAMEOUTPUTFILE); + $(QUIET_PREFIX) $(VSIGN) -signvalve $(GAMEOUTPUTFILE); + $(QUIET_PREFIX) if [ "$(COPY_DLL_TO_SRV)" = "1" ]; then\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- COPYING TO $(Srv_GAMEOUTPUTFILE) ----";\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + cp -v $(GAMEOUTPUTFILE) $(Srv_GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);\ + cp -v $(GAMEOUTPUTFILE)$(SYM_EXT) $(Srv_GAMEOUTPUTFILE)$(SYM_EXT) $(QUIET_ECHO_POSTFIX);\ + fi; + $(QUIET_PREFIX) if [ "$(IMPORTLIBRARY)" != "" ]; then\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- COPYING TO IMPORT LIBRARY $(IMPORTLIBRARY) ----";\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + $(P4_EDIT_START) $(IMPORTLIBRARY) $(P4_EDIT_END) && \ + mkdir -p `dirname $(IMPORTLIBRARY)` > /dev/null && \ + cp -v $(OUTPUTFILE) $(IMPORTLIBRARY); \ + fi; + + +$(SO_File): $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES) + $(QUIET_PREFIX) \ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- LINKING $@ [$(CFG)] ----";\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + \ + $(LINK) $(LINK_MAP_FLAGS) $(SHLIBLDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_SHLIB) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_SHLIB); + $(VSIGN) -signvalve $(OUTPUTFILE); + + +$(EXE_File) : $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES) + $(QUIET_PREFIX) \ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- LINKING EXE $@ [$(CFG)] ----";\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + \ + $(P4_EDIT_START) $(OUTPUTFILE) $(P4_EDIT_END);\ + $(LINK) $(LINK_MAP_FLAGS) $(LDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_EXE) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_EXE); + $(QUIET_PREFIX) -$(P4_EDIT_START) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); + $(QUIET_PREFIX) $(GEN_SYM) $(OUTPUTFILE); + $(QUIET_PREFIX) -$(STRIP) $(OUTPUTFILE); + $(QUIET_PREFIX) $(VSIGN) -signvalve $(OUTPUTFILE); + + +tags: + etags -a -C -o $(SRCROOT)/TAGS *.cpp *.cxx *.h *.hxx diff --git a/mp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll b/mp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll new file mode 100644 index 00000000..d76adbc0 Binary files /dev/null and b/mp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll differ diff --git a/mp/src/dx9sdk/utilities/dx_proxy.dll b/mp/src/dx9sdk/utilities/dx_proxy.dll new file mode 100644 index 00000000..676a897d Binary files /dev/null and b/mp/src/dx9sdk/utilities/dx_proxy.dll differ diff --git a/mp/src/game/client/c_baseanimating.cpp b/mp/src/game/client/c_baseanimating.cpp index 137923d4..1086c301 100644 --- a/mp/src/game/client/c_baseanimating.cpp +++ b/mp/src/game/client/c_baseanimating.cpp @@ -1543,6 +1543,8 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater ApplyBoneMatrixTransform( GetBoneForWrite( i ) ); } } + + } //----------------------------------------------------------------------------- @@ -3233,7 +3235,7 @@ int C_BaseAnimating::InternalDrawModel( int flags ) if ( !GetModelPtr() ) return 0; - UpdateBoneAttachments( flags ); + UpdateBoneAttachments( ); if ( IsEffectActive( EF_ITEM_BLINK ) ) { @@ -6255,7 +6257,7 @@ bool C_BaseAnimating::ShouldResetSequenceOnNewModel( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_BaseAnimating::UpdateBoneAttachments( int flags ) +void C_BaseAnimating::UpdateBoneAttachments( void ) { if ( !m_pAttachedTo ) return; diff --git a/mp/src/game/client/c_baseanimating.h b/mp/src/game/client/c_baseanimating.h index d1c99868..5f30d8f8 100644 --- a/mp/src/game/client/c_baseanimating.h +++ b/mp/src/game/client/c_baseanimating.h @@ -228,7 +228,7 @@ public: int GetNumBoneAttachments(); C_BaseAnimating* GetBoneAttachment( int i ); virtual void NotifyBoneAttached( C_BaseAnimating* attachTarget ); - virtual void UpdateBoneAttachments( int flags ); + virtual void UpdateBoneAttachments( void ); //bool solveIK(float a, float b, const Vector &Foot, const Vector &Knee1, Vector &Knee2); //void DebugIK( mstudioikchain_t *pikchain ); diff --git a/mp/src/game/client/c_baseentity.h b/mp/src/game/client/c_baseentity.h index 955e80c5..3ea4b7fd 100644 --- a/mp/src/game/client/c_baseentity.h +++ b/mp/src/game/client/c_baseentity.h @@ -743,6 +743,7 @@ public: virtual void SetHealth(int iHealth) {} virtual int GetHealth() const { return 0; } virtual int GetMaxHealth() const { return 1; } + virtual bool IsVisibleToTargetID( void ) { return false; } // Returns the health fraction float HealthFraction() const; @@ -1004,6 +1005,7 @@ public: virtual bool IsBaseObject( void ) const { return false; } virtual bool IsBaseCombatWeapon( void ) const { return false; } virtual class C_BaseCombatWeapon *MyCombatWeaponPointer() { return NULL; } + virtual bool IsCombatItem( void ) const { return false; } virtual bool IsBaseTrain( void ) const { return false; } diff --git a/mp/src/game/client/c_team_objectiveresource.cpp b/mp/src/game/client/c_team_objectiveresource.cpp index 7d31036d..e0412d27 100644 --- a/mp/src/game/client/c_team_objectiveresource.cpp +++ b/mp/src/game/client/c_team_objectiveresource.cpp @@ -87,7 +87,10 @@ IMPLEMENT_CLIENTCLASS_DT_NOBASE(C_BaseTeamObjectiveResource, DT_BaseTeamObjectiv RecvPropArray3( RECVINFO_ARRAY(m_iTeamInZone), RecvPropInt( RECVINFO(m_iTeamInZone[0]) ) ), RecvPropArray3( RECVINFO_ARRAY(m_bBlocked), RecvPropInt( RECVINFO(m_bBlocked[0]) ) ), RecvPropArray3( RECVINFO_ARRAY(m_iOwner), RecvPropInt( RECVINFO(m_iOwner[0]), 0, RecvProxy_Owner ) ), + RecvPropArray3( RECVINFO_ARRAY(m_bCPCapRateScalesWithPlayers), RecvPropBool( RECVINFO(m_bCPCapRateScalesWithPlayers[0]) ) ), RecvPropString( RECVINFO(m_pszCapLayoutInHUD), 0, RecvProxy_CapLayout ), + RecvPropFloat( RECVINFO(m_flCustomPositionX) ), + RecvPropFloat( RECVINFO(m_flCustomPositionY) ), END_RECV_TABLE() C_BaseTeamObjectiveResource *g_pObjectiveResource = NULL; @@ -151,6 +154,9 @@ C_BaseTeamObjectiveResource::C_BaseTeamObjectiveResource() m_flNodeHillData[i] = 0; } + m_flCustomPositionX = -1.f; + m_flCustomPositionY = -1.f; + g_pObjectiveResource = this; } @@ -173,6 +179,9 @@ void C_BaseTeamObjectiveResource::OnPreDataChanged( DataUpdateType_t updateType m_iOldUpdateCapHudParity = m_iUpdateCapHudParity; m_bOldControlPointsReset = m_bControlPointsReset; + m_flOldCustomPositionX = m_flCustomPositionX; + m_flOldCustomPositionY = m_flCustomPositionY; + memcpy( m_flOldLazyCapPerc, m_flLazyCapPerc, sizeof(float)*m_iNumControlPoints ); memcpy( m_flOldUnlockTimes, m_flUnlockTimes, sizeof(float)*m_iNumControlPoints ); memcpy( m_flOldCPTimerTimes, m_flCPTimerTimes, sizeof(float)*m_iNumControlPoints ); @@ -229,6 +238,11 @@ void C_BaseTeamObjectiveResource::OnDataChanged( DataUpdateType_t updateType ) } } } + + if ( m_flOldCustomPositionX != m_flCustomPositionX || m_flOldCustomPositionY != m_flCustomPositionY ) + { + UpdateControlPoint( "controlpoint_updatelayout" ); + } } //----------------------------------------------------------------------------- @@ -373,7 +387,7 @@ void C_BaseTeamObjectiveResource::ClientThink() if ( iPlayersCapping > 0 ) { float flReduction = gpGlobals->curtime - m_flCapLastThinkTime[i]; - if ( mp_capstyle.GetInt() == 1 ) + if ( mp_capstyle.GetInt() == 1 && m_bCPCapRateScalesWithPlayers[i] ) { // Diminishing returns for successive players. for ( int iPlayer = 1; iPlayer < iPlayersCapping; iPlayer++ ) @@ -423,7 +437,8 @@ void C_BaseTeamObjectiveResource::ClientThink() if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->TeamMayCapturePoint(m_iCappingTeam[i],i) ) { float flCapLength = m_flTeamCapTime[ TEAM_ARRAY(i,m_iCappingTeam[i]) ]; - float flDecrease = (flCapLength / mp_capdeteriorate_time.GetFloat()) * (gpGlobals->curtime - m_flCapLastThinkTime[i]); + float flDecreaseScale = m_bCPCapRateScalesWithPlayers[i] ? mp_capdeteriorate_time.GetFloat() : flCapLength; + float flDecrease = (flCapLength / flDecreaseScale) * (gpGlobals->curtime - m_flCapLastThinkTime[i]); if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->InOvertime() ) { flDecrease *= 6; diff --git a/mp/src/game/client/c_team_objectiveresource.h b/mp/src/game/client/c_team_objectiveresource.h index ca75d8dc..588971c3 100644 --- a/mp/src/game/client/c_team_objectiveresource.h +++ b/mp/src/game/client/c_team_objectiveresource.h @@ -163,6 +163,7 @@ public: } const char *GetCapLayoutInHUD( void ) { return m_pszCapLayoutInHUD; } + void GetCapLayoutCustomPosition( float& flCustomPositionX, float& flCustomPositionY ) { flCustomPositionX = m_flCustomPositionX; flCustomPositionY = m_flCustomPositionY; } bool PlayingMiniRounds( void ){ return m_bPlayingMiniRounds; } bool IsInMiniRound( int index ) { return m_bInMiniRound[index]; } @@ -313,6 +314,7 @@ protected: int m_iTeamInZone[MAX_CONTROL_POINTS]; bool m_bBlocked[MAX_CONTROL_POINTS]; int m_iOwner[MAX_CONTROL_POINTS]; + bool m_bCPCapRateScalesWithPlayers[MAX_CONTROL_POINTS]; // client calculated state float m_flCapTimeLeft[MAX_CONTROL_POINTS]; @@ -321,6 +323,10 @@ protected: bool m_bWarnedOnFinalCap[MAX_CONTROL_POINTS]; float m_flLastCapWarningTime[MAX_CONTROL_POINTS]; char m_pszCapLayoutInHUD[MAX_CAPLAYOUT_LENGTH]; + float m_flOldCustomPositionX; + float m_flOldCustomPositionY; + float m_flCustomPositionX; + float m_flCustomPositionY; // hill data for multi-escort payload maps int m_nNumNodeHillData[TEAM_TRAIN_MAX_TEAMS]; diff --git a/mp/src/game/client/cdll_client_int.cpp b/mp/src/game/client/cdll_client_int.cpp index 0e96b11c..c8f7f40b 100644 --- a/mp/src/game/client/cdll_client_int.cpp +++ b/mp/src/game/client/cdll_client_int.cpp @@ -104,6 +104,7 @@ #include "replay/vgui/replayperformanceeditor.h" #endif #include "vgui/ILocalize.h" +#include "vgui/IVGui.h" #include "ixboxsystem.h" #include "ipresence.h" #include "engine/imatchmaking.h" @@ -982,6 +983,8 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi g_pSourceVR->GetViewportBounds( ISourceVirtualReality::VREye_Left, NULL, NULL, &nViewportWidth, &nViewportHeight ); vgui::surface()->SetFullscreenViewport( 0, 0, nViewportWidth, nViewportHeight ); + + vgui::ivgui()->SetVRMode( true ); } if (!Initializer::InitializeAllObjects()) diff --git a/mp/src/game/client/client_virtualreality.cpp b/mp/src/game/client/client_virtualreality.cpp index 69f6e63a..1eb59a59 100644 --- a/mp/src/game/client/client_virtualreality.cpp +++ b/mp/src/game/client/client_virtualreality.cpp @@ -635,34 +635,6 @@ bool CClientVirtualReality::OverrideStereoView( CViewSetup *pViewMiddle, CViewSe g_pSourceVR->GetEyeProjectionMatrix ( &pViewLeft->m_ViewToProjection, ISourceVirtualReality::VREye_Left, pViewMiddle->zNear, pViewMiddle->zFar, 1.0f/headtrackFovScale ); g_pSourceVR->GetEyeProjectionMatrix ( &pViewRight->m_ViewToProjection, ISourceVirtualReality::VREye_Right, pViewMiddle->zNear, pViewMiddle->zFar, 1.0f/headtrackFovScale ); - static ConVarRef vr_distortion_grow_outside( "vr_distortion_grow_outside" ); - static ConVarRef vr_distortion_grow_inside( "vr_distortion_grow_inside" ); - static ConVarRef vr_distortion_grow_above( "vr_distortion_grow_above" ); - static ConVarRef vr_distortion_grow_below( "vr_distortion_grow_below" ); - - float StereoDistortionGrowOutside = vr_distortion_grow_outside.GetFloat(); - float StereoDistortionGrowInside = vr_distortion_grow_inside.GetFloat(); - float StereoDistortionGrowAbove = vr_distortion_grow_above.GetFloat(); - float StereoDistortionGrowBelow = vr_distortion_grow_below.GetFloat(); - if ( ( StereoDistortionGrowOutside != 0.0f ) || (StereoDistortionGrowInside != 0.0f ) ) - { - float ScaleX = 2.0f / ( StereoDistortionGrowInside + StereoDistortionGrowOutside + 2.0f ); - float OffsetX = 0.5f * ScaleX * ( StereoDistortionGrowInside - StereoDistortionGrowOutside ); - pViewLeft ->m_ViewToProjection.m[0][0] *= ScaleX; - pViewLeft ->m_ViewToProjection.m[0][2] = ( pViewLeft ->m_ViewToProjection.m[0][2] * ScaleX ) + OffsetX; - pViewRight->m_ViewToProjection.m[0][0] *= ScaleX; - pViewRight->m_ViewToProjection.m[0][2] = ( pViewRight->m_ViewToProjection.m[0][2] * ScaleX ) - OffsetX; - } - if ( ( StereoDistortionGrowAbove != 0.0f ) || (StereoDistortionGrowBelow != 0.0f ) ) - { - float ScaleY = 2.0f / ( StereoDistortionGrowBelow + StereoDistortionGrowAbove + 2.0f ); - float OffsetY = -0.5f * ScaleY * ( StereoDistortionGrowBelow - StereoDistortionGrowAbove ); // Why is this -0.5 and not +0.5? I wish I knew. - pViewLeft ->m_ViewToProjection.m[1][1] *= ScaleY; - pViewLeft ->m_ViewToProjection.m[1][2] = ( pViewLeft ->m_ViewToProjection.m[1][2] * ScaleY ) + OffsetY; - pViewRight->m_ViewToProjection.m[1][1] *= ScaleY; - pViewRight->m_ViewToProjection.m[1][2] = ( pViewRight->m_ViewToProjection.m[1][2] * ScaleY ) + OffsetY; - } - // And bodge together some sort of average for our cyclops friends. pViewMiddle->m_bViewToProjectionOverride = true; for ( int i = 0; i < 4; i++ ) diff --git a/mp/src/game/client/glow_outline_effect.cpp b/mp/src/game/client/glow_outline_effect.cpp index 600b15d7..a6d80b7f 100644 --- a/mp/src/game/client/glow_outline_effect.cpp +++ b/mp/src/game/client/glow_outline_effect.cpp @@ -312,37 +312,20 @@ void CGlowObjectManager::ApplyEntityGlowEffects( const CViewSetup *pSetup, int n void CGlowObjectManager::GlowObjectDefinition_t::DrawModel() { - C_BaseEntity *pEntity = m_hEntity.Get(); - if ( !pEntity ) - return; - - if ( pEntity->GetMoveParent() != NULL ) + if ( m_hEntity.Get() ) { - C_BaseAnimating *pBaseAnimating = pEntity->GetBaseAnimating(); - if ( pBaseAnimating ) - { - pBaseAnimating->InvalidateBoneCache(); - } - } + m_hEntity->DrawModel( STUDIO_RENDER ); + C_BaseEntity *pAttachment = m_hEntity->FirstMoveChild(); - pEntity->DrawModel( STUDIO_RENDER ); - - C_BaseEntity *pAttachment = pEntity->FirstMoveChild(); - while ( pAttachment != NULL ) - { - if ( !g_GlowObjectManager.HasGlowEffect( pAttachment ) && pAttachment->ShouldDraw() ) + while ( pAttachment != NULL ) { - C_BaseAnimating *pBaseAnimating = pAttachment->GetBaseAnimating(); - if ( pBaseAnimating ) + if ( !g_GlowObjectManager.HasGlowEffect( pAttachment ) && pAttachment->ShouldDraw() ) { - pBaseAnimating->InvalidateBoneCache(); + pAttachment->DrawModel( STUDIO_RENDER ); } - - pAttachment->DrawModel( STUDIO_RENDER ); + pAttachment = pAttachment->NextMovePeer(); } - - pAttachment = pAttachment->NextMovePeer(); } } -#endif // GLOWS_ENABLE +#endif // GLOWS_ENABLE \ No newline at end of file diff --git a/mp/src/game/client/hud_controlpointicons.cpp b/mp/src/game/client/hud_controlpointicons.cpp index 20d6150b..a8c390ae 100644 --- a/mp/src/game/client/hud_controlpointicons.cpp +++ b/mp/src/game/client/hud_controlpointicons.cpp @@ -1107,7 +1107,23 @@ void CHudControlPointIcons::PerformLayout( void ) } // Setup the main panel - SetBounds( (ScreenWidth() - iWidest) * 0.5, ScreenHeight() - iTall - m_nHeightOffset, iWidest, iTall ); + float flPositionX = (ScreenWidth() - iWidest) * 0.5; + float flPositionY = ScreenHeight() - iTall - m_nHeightOffset; + if ( ObjectiveResource() ) + { + float flCustomPositionX = -1.f; + float flCustomPositionY = -1.f; + ObjectiveResource()->GetCapLayoutCustomPosition( flCustomPositionX, flCustomPositionY ); + if ( flCustomPositionX != -1.f ) + { + flPositionX = flCustomPositionX * ScreenWidth(); + } + if ( flCustomPositionY != -1.f ) + { + flPositionY = flCustomPositionY * ScreenHeight(); + } + } + SetBounds( flPositionX, flPositionY, iWidest, iTall ); // Now that we know how wide we are, and how many icons are in each line, // we can lay the icons out, centered in the lines. diff --git a/mp/src/game/client/in_mouse.cpp b/mp/src/game/client/in_mouse.cpp index 207e7508..16cdd15e 100644 --- a/mp/src/game/client/in_mouse.cpp +++ b/mp/src/game/client/in_mouse.cpp @@ -10,9 +10,6 @@ #define _WIN32_WINNT 0x0502 #include #endif -#ifdef OSX -#include -#endif #include "cbase.h" #include "hud.h" #include "cdll_int.h" @@ -105,12 +102,7 @@ static ConVar m_mousespeed( "m_mousespeed", "1", FCVAR_ARCHIVE, "Windows mouse a static ConVar m_mouseaccel1( "m_mouseaccel1", "0", FCVAR_ARCHIVE, "Windows mouse acceleration initial threshold (2x movement).", true, 0, false, 0.0f ); static ConVar m_mouseaccel2( "m_mouseaccel2", "0", FCVAR_ARCHIVE, "Windows mouse acceleration secondary threshold (4x movement).", true, 0, false, 0.0f ); -#if defined( OSX ) -// On OSX, this needs to stick at 0. -static ConVar m_rawinput( "m_rawinput", "0", FCVAR_ARCHIVE, "Raw Mouse input is unavailable on OSX", true, 0.0, true, 0.0); -#else static ConVar m_rawinput( "m_rawinput", "0", FCVAR_ARCHIVE, "Use Raw Input for mouse input."); -#endif #if DEBUG ConVar cl_mouselook( "cl_mouselook", "1", FCVAR_ARCHIVE, "Set to 1 to use mouse for look, 0 for keyboard look." ); @@ -604,7 +596,7 @@ void CInput::AccumulateMouse( void ) m_flAccumulatedMouseXMovement += current_posx - x; m_flAccumulatedMouseYMovement += current_posy - y; -#elif defined( USE_SDL ) || defined( OSX ) +#elif defined( USE_SDL ) int dx, dy; engine->GetMouseDelta( dx, dy ); m_flAccumulatedMouseXMovement += dx; diff --git a/mp/src/game/client/input.h b/mp/src/game/client/input.h index bd371c80..00bbb02f 100644 --- a/mp/src/game/client/input.h +++ b/mp/src/game/client/input.h @@ -18,7 +18,7 @@ #include "ehandle.h" #include "inputsystem/AnalogCode.h" -typedef unsigned long CRC32_t; +typedef unsigned int CRC32_t; //----------------------------------------------------------------------------- // Purpose: diff --git a/mp/src/game/server/ai_activity.cpp b/mp/src/game/server/ai_activity.cpp index ba9c8432..25e5c441 100644 --- a/mp/src/game/server/ai_activity.cpp +++ b/mp/src/game/server/ai_activity.cpp @@ -2147,4 +2147,10 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_PRIMARY3_END ); ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_PRIMARY3_END ); ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_PRIMARY3 ); + + ADD_ACTIVITY_TO_SR( ACT_MP_THROW ); + ADD_ACTIVITY_TO_SR( ACT_THROWABLE_VM_DRAW ); + ADD_ACTIVITY_TO_SR( ACT_THROWABLE_VM_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_THROWABLE_VM_FIRE ); + } diff --git a/mp/src/game/server/ai_networkmanager.cpp b/mp/src/game/server/ai_networkmanager.cpp index 953e2884..00826e02 100644 --- a/mp/src/game/server/ai_networkmanager.cpp +++ b/mp/src/game/server/ai_networkmanager.cpp @@ -2633,7 +2633,7 @@ void CAI_NetworkBuilder::InitVisibility(CAI_Network *pNetwork, CAI_Node *pNode) if ( DebuggingConnect( pNode->m_iID, testnode ) ) { - DevMsg( "" ); // break here.. + DevMsg( " " ); // break here.. } // We know we can view ourself @@ -2814,7 +2814,7 @@ void CAI_NetworkBuilder::InitNeighbors(CAI_Network *pNetwork, CAI_Node *pNode) { if ( DebuggingConnect( pNode->m_iID, checknode ) ) { - DevMsg( "" ); // break here.. + DevMsg( " " ); // break here.. } // I'm not a neighbor of myself @@ -3204,7 +3204,7 @@ void CAI_NetworkBuilder::InitLinks(CAI_Network *pNetwork, CAI_Node *pNode) if ( DebuggingConnect( pNode->m_iID, i ) ) { - DevMsg( "" ); // break here.. + DevMsg( " " ); // break here.. } if ( !(pNode->m_eNodeInfo & bits_NODE_FALLEN) && !(pDestNode->m_eNodeInfo & bits_NODE_FALLEN) ) diff --git a/mp/src/game/server/basecombatcharacter.cpp b/mp/src/game/server/basecombatcharacter.cpp index 58767184..7fb5cce1 100644 --- a/mp/src/game/server/basecombatcharacter.cpp +++ b/mp/src/game/server/basecombatcharacter.cpp @@ -3522,6 +3522,10 @@ void CBaseCombatCharacter::ChangeTeam( int iTeamNum ) // old team member no longer in the nav mesh ClearLastKnownArea(); +#ifdef GLOWS_ENABLE + RemoveGlowEffect(); +#endif // GLOWS_ENABLE + BaseClass::ChangeTeam( iTeamNum ); } diff --git a/mp/src/game/server/baseentity.h b/mp/src/game/server/baseentity.h index 26d81804..016915ca 100644 --- a/mp/src/game/server/baseentity.h +++ b/mp/src/game/server/baseentity.h @@ -948,6 +948,7 @@ public: bool IsBSPModel() const; bool IsCombatCharacter() { return MyCombatCharacterPointer() == NULL ? false : true; } bool IsInWorld( void ) const; + virtual bool IsCombatItem( void ) const { return false; } virtual bool IsBaseCombatWeapon( void ) const { return false; } virtual bool IsWearable( void ) const { return false; } diff --git a/mp/src/game/server/cbase.cpp b/mp/src/game/server/cbase.cpp index f1f9b0d6..944e6841 100644 --- a/mp/src/game/server/cbase.cpp +++ b/mp/src/game/server/cbase.cpp @@ -278,14 +278,32 @@ void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBa if ( ev->m_flDelay ) { char szBuffer[256]; - Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), ev->m_flDelay, STRING(ev->m_iParameter) ); + Q_snprintf( szBuffer, + sizeof(szBuffer), + "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n", + engine->GetServerTime(), + pCaller ? STRING(pCaller->m_iClassname) : "NULL", + pCaller ? STRING(pCaller->GetEntityName()) : "NULL", + STRING(ev->m_iTarget), + STRING(ev->m_iTargetInput), + ev->m_flDelay, + STRING(ev->m_iParameter) ); + DevMsg( 2, "%s", szBuffer ); ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); } else { char szBuffer[256]; - Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), STRING(ev->m_iParameter) ); + Q_snprintf( szBuffer, + sizeof(szBuffer), + "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n", + engine->GetServerTime(), + pCaller ? STRING(pCaller->m_iClassname) : "NULL", + pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), + STRING(ev->m_iTargetInput), + STRING(ev->m_iParameter) ); + DevMsg( 2, "%s", szBuffer ); ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); } @@ -749,7 +767,7 @@ void CEventQueue::Dump( void ) { EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; - Msg("Dumping event queue. Current time is: %.2f\n", gpGlobals->curtime ); + Msg( "Dumping event queue. Current time is: %.2f\n", engine->GetServerTime() ); while ( pe != NULL ) { @@ -777,7 +795,7 @@ void CEventQueue::AddEvent( const char *target, const char *targetInput, variant { // build the new event EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t; - newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // priority key in the priority queue + newEvent->m_flFireTime = engine->GetServerTime() + fireDelay; // priority key in the priority queue newEvent->m_iTarget = MAKE_STRING( target ); newEvent->m_pEntTarget = NULL; newEvent->m_iTargetInput = MAKE_STRING( targetInput ); @@ -796,7 +814,7 @@ void CEventQueue::AddEvent( CBaseEntity *target, const char *targetInput, varian { // build the new event EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t; - newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // primary priority key in the priority queue + newEvent->m_flFireTime = engine->GetServerTime() + fireDelay; // primary priority key in the priority queue newEvent->m_iTarget = NULL_STRING; newEvent->m_pEntTarget = target; newEvent->m_iTargetInput = MAKE_STRING( targetInput ); @@ -867,7 +885,7 @@ void CEventQueue::ServiceEvents( void ) EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; - while ( pe != NULL && pe->m_flFireTime <= gpGlobals->curtime ) + while ( pe != NULL && pe->m_flFireTime <= engine->GetServerTime() ) { MDLCACHE_CRITICAL_SECTION(); @@ -1150,11 +1168,23 @@ int CEventQueue::Restore( IRestore &restore ) // add the restored event into the list if ( tmpEvent.m_pEntTarget ) { - AddEvent( tmpEvent.m_pEntTarget, STRING(tmpEvent.m_iTargetInput), tmpEvent.m_VariantValue, tmpEvent.m_flFireTime - gpGlobals->curtime, tmpEvent.m_pActivator, tmpEvent.m_pCaller, tmpEvent.m_iOutputID ); + AddEvent( tmpEvent.m_pEntTarget, + STRING(tmpEvent.m_iTargetInput), + tmpEvent.m_VariantValue, + tmpEvent.m_flFireTime - engine->GetServerTime(), + tmpEvent.m_pActivator, + tmpEvent.m_pCaller, + tmpEvent.m_iOutputID ); } else { - AddEvent( STRING(tmpEvent.m_iTarget), STRING(tmpEvent.m_iTargetInput), tmpEvent.m_VariantValue, tmpEvent.m_flFireTime - gpGlobals->curtime, tmpEvent.m_pActivator, tmpEvent.m_pCaller, tmpEvent.m_iOutputID ); + AddEvent( STRING(tmpEvent.m_iTarget), + STRING(tmpEvent.m_iTargetInput), + tmpEvent.m_VariantValue, + tmpEvent.m_flFireTime - engine->GetServerTime(), + tmpEvent.m_pActivator, + tmpEvent.m_pCaller, + tmpEvent.m_iOutputID ); } } diff --git a/mp/src/game/server/doors.cpp b/mp/src/game/server/doors.cpp index d44d6632..53abb829 100644 --- a/mp/src/game/server/doors.cpp +++ b/mp/src/game/server/doors.cpp @@ -21,6 +21,10 @@ #include "KeyValues.h" #endif +#ifdef TF_DLL +#include "tf_gamerules.h" +#endif // TF_DLL + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -332,6 +336,17 @@ void CBaseDoor::Spawn() } CreateVPhysics(); + +#ifdef TF_DLL + if ( TFGameRules() && TFGameRules()->IsMultiplayer() ) + { + if ( !m_flBlockDamage ) + { + // Never block doors in TF2 - to prevent various exploits. + m_flBlockDamage = 10.f; + } + } +#endif // TF_DLL } void CBaseDoor::MovingSoundThink( void ) diff --git a/mp/src/game/server/functorutils.h b/mp/src/game/server/functorutils.h index 8b4657b2..d07f0597 100644 --- a/mp/src/game/server/functorutils.h +++ b/mp/src/game/server/functorutils.h @@ -5,8 +5,10 @@ #ifndef _FUNCTOR_UTILS_H_ #define _FUNCTOR_UTILS_H_ +#ifdef NEXT_BOT #include "NextBotInterface.h" #include "NextBotManager.h" +#endif // NEXT_BOT //-------------------------------------------------------------------------------------------------------- /** @@ -321,12 +323,14 @@ inline bool ForEachActor( Functor &func ) if ( !player->IsConnected() ) continue; +#ifdef NEXT_BOT // skip bots - ForEachCombatCharacter will catch them INextBot *bot = player->MyNextBotPointer(); if ( bot ) { continue; } +#endif // NEXT_BOT if ( func( player ) == false ) { @@ -334,8 +338,12 @@ inline bool ForEachActor( Functor &func ) } } +#ifdef NEXT_BOT // iterate all NextBots return TheNextBots().ForEachCombatCharacter( func ); +#else + return true; +#endif // NEXT_BOT } @@ -385,12 +393,14 @@ inline bool ForEachActor( IActorFunctor &func ) if ( !player->IsConnected() ) continue; +#ifdef NEXT_BOT // skip bots - ForEachCombatCharacter will catch them INextBot *bot = dynamic_cast< INextBot * >( player ); if ( bot ) { continue; } +#endif // NEXT_BOT if ( func( player ) == false ) { @@ -399,11 +409,13 @@ inline bool ForEachActor( IActorFunctor &func ) } } +#ifdef NEXT_BOT if ( !isComplete ) { // iterate all NextBots isComplete = TheNextBots().ForEachCombatCharacter( func ); } +#endif // NEXT_BOT func.OnEndIteration( isComplete ); diff --git a/mp/src/game/server/gameinterface.cpp b/mp/src/game/server/gameinterface.cpp index 9f707419..b4d09bae 100644 --- a/mp/src/game/server/gameinterface.cpp +++ b/mp/src/game/server/gameinterface.cpp @@ -98,14 +98,17 @@ #include "tf/tf_gc_server.h" #include "tf_gamerules.h" #include "tf_lobby.h" -#include "player_vs_environment/tf_populator.h" +#include "player_vs_environment/tf_population_manager.h" extern ConVar tf_mm_trusted; extern ConVar tf_mm_servermode; #endif -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH #include "nav_mesh.h" +#endif + +#ifdef NEXT_BOT #include "NextBotManager.h" #endif @@ -730,7 +733,7 @@ bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory, debugoverlay = (IVDebugOverlay *)appSystemFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL ); #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH // create the Navigation Mesh interface TheNavMesh = NavMeshFactory(); #endif @@ -776,7 +779,7 @@ void CServerGameDLL::DLLShutdown( void ) #endif #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH // destroy the Navigation Mesh interface if ( TheNavMesh ) { @@ -1125,7 +1128,7 @@ void CServerGameDLL::ServerActivate( edict_t *pEdictList, int edictCount, int cl } #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH // load the Navigation Mesh for this map TheNavMesh->Load(); TheNavMesh->OnServerActivate(); @@ -1220,9 +1223,11 @@ void CServerGameDLL::GameFrame( bool simulating ) GameStartFrame(); #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH TheNavMesh->Update(); +#endif +#ifdef NEXT_BOT TheNextBots().Update(); #endif @@ -1388,7 +1393,7 @@ void CServerGameDLL::LevelShutdown( void ) g_nCurrentChapterIndex = -1; #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH // reset the Navigation Mesh if ( TheNavMesh ) { diff --git a/mp/src/game/server/hl2/combine_mine.cpp b/mp/src/game/server/hl2/combine_mine.cpp index 6d49f94e..d3e40b56 100644 --- a/mp/src/game/server/hl2/combine_mine.cpp +++ b/mp/src/game/server/hl2/combine_mine.cpp @@ -244,7 +244,7 @@ int CBounceBomb::DrawDebugTextOverlays(void) if (m_debugOverlays & OVERLAY_TEXT_BIT) { char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr), pszMineStateNames[m_iMineState] ); + Q_snprintf(tempstr,sizeof(tempstr), "%s", pszMineStateNames[m_iMineState] ); EntityText(text_offset,tempstr,0); text_offset++; } diff --git a/mp/src/game/server/nav_area.h b/mp/src/game/server/nav_area.h index cbabe493..6eba5966 100644 --- a/mp/src/game/server/nav_area.h +++ b/mp/src/game/server/nav_area.h @@ -313,10 +313,12 @@ public: bool HasAvoidanceObstacle( float maxObstructionHeight = StepHeight ) const; // is there a large, immobile object obstructing this area float GetAvoidanceObstacleHeight( void ) const; // returns the maximum height of the obstruction above the ground +#ifdef NEXT_BOT bool HasPrerequisite( CBaseCombatCharacter *actor = NULL ) const; // return true if this area has a prerequisite that applies to the given actor const CUtlVector< CHandle< CFuncNavPrerequisite > > &GetPrerequisiteVector( void ) const; // return vector of prerequisites that must be met before this area can be traversed void RemoveAllPrerequisites( void ); void AddPrerequisite( CFuncNavPrerequisite *prereq ); +#endif void ClearAllNavCostEntities( void ); // clear set of func_nav_cost entities that affect this area void AddFuncNavCostEntity( CFuncNavCost *cost ); // add the given func_nav_cost entity to the cost of this area @@ -722,7 +724,9 @@ private: void CalcDebugID(); +#ifdef NEXT_BOT CUtlVector< CHandle< CFuncNavPrerequisite > > m_prerequisiteVector; // list of prerequisites that must be met before this area can be traversed +#endif CNavArea *m_prevHash, *m_nextHash; // for hash table in CNavMesh @@ -764,6 +768,8 @@ extern NavAreaVector TheNavAreas; // Inlines // +#ifdef NEXT_BOT + //-------------------------------------------------------------------------------------------------------------- inline bool CNavArea::HasPrerequisite( CBaseCombatCharacter *actor ) const { @@ -790,6 +796,7 @@ inline void CNavArea::AddPrerequisite( CFuncNavPrerequisite *prereq ) m_prerequisiteVector.AddToTail( prereq ); } } +#endif //-------------------------------------------------------------------------------------------------------------- inline float CNavArea::GetDangerDecayRate( void ) const diff --git a/mp/src/game/server/nav_colors.cpp b/mp/src/game/server/nav_colors.cpp index 8f2035be..50ba6cac 100644 --- a/mp/src/game/server/nav_colors.cpp +++ b/mp/src/game/server/nav_colors.cpp @@ -79,8 +79,8 @@ void NavDrawLine( const Vector& from, const Vector& to, NavEditColor navColor ) const Vector offset( 0, 0, 1 ); Color color = NavColors[navColor]; - NDebugOverlay::Line( from + offset, to + offset, color[0]/2, color[1]/2, color[2]/2, true, 0.1f ); - NDebugOverlay::Line( from + offset, to + offset, color[0], color[1], color[2], false, 0.15f ); + NDebugOverlay::Line( from + offset, to + offset, color[0], color[1], color[2], false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); + NDebugOverlay::Line( from + offset, to + offset, color[0]/2, color[1]/2, color[2]/2, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } @@ -113,8 +113,8 @@ void NavDrawHorizontalArrow( const Vector& from, const Vector& to, float width, const Vector offset( 0, 0, 1 ); Color color = NavColors[navColor]; - NDebugOverlay::HorzArrow( from + offset, to + offset, width, color[0]/2, color[1]/2, color[2]/2, 255, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); NDebugOverlay::HorzArrow( from + offset, to + offset, width, color[0], color[1], color[2], 255, false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); + NDebugOverlay::HorzArrow( from + offset, to + offset, width, color[0]/2, color[1]/2, color[2]/2, 255, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } @@ -142,8 +142,8 @@ void NavDrawDashedLine( const Vector& from, const Vector& to, NavEditColor navCo distance += solidLen + gapLen; - NDebugOverlay::Line( start + offset, end + offset, color[0]/2, color[1]/2, color[2]/2, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); NDebugOverlay::Line( start + offset, end + offset, color[0], color[1], color[2], false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); + NDebugOverlay::Line( start + offset, end + offset, color[0]/2, color[1]/2, color[2]/2, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } } diff --git a/mp/src/game/server/nav_edit.cpp b/mp/src/game/server/nav_edit.cpp index cea4e41d..512d5dda 100644 --- a/mp/src/game/server/nav_edit.cpp +++ b/mp/src/game/server/nav_edit.cpp @@ -732,9 +732,6 @@ void CNavMesh::DrawEditMode( void ) static ConVarRef host_thread_mode( "host_thread_mode" ); host_thread_mode.SetValue( 0 ); - static ConVarRef sb_perf_collect( "sb_perf_collect" ); - sb_perf_collect.SetValue( 0 ); - const float maxRange = 1000.0f; // 500 #if DEBUG_NAV_NODES @@ -908,7 +905,7 @@ void CNavMesh::DrawEditMode( void ) { V_snprintf( buffer, sizeof( buffer ), "Ladder #%d\n", m_selectedLadder->GetID() ); } - NDebugOverlay::ScreenText( 0.5, 0.53, buffer, 255, 255, 0, 128, nav_show_area_info.GetBool() ? 0.1 : 0.5 ); + NDebugOverlay::ScreenText( 0.5, 0.53, buffer, 255, 255, 0, 128, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } // draw the ladder we are pointing at and all connected areas diff --git a/mp/src/game/server/nav_entities.cpp b/mp/src/game/server/nav_entities.cpp index c7abe838..ef9366cc 100644 --- a/mp/src/game/server/nav_entities.cpp +++ b/mp/src/game/server/nav_entities.cpp @@ -96,7 +96,7 @@ void CFuncNavCost::Spawn( void ) for( char *token = strtok( buffer, " " ); token; token = strtok( NULL, " " ) ) { - m_tags.AddToTail( token ); + m_tags.AddToTail( CFmtStr( "%s", token ) ); } delete [] buffer; @@ -189,6 +189,19 @@ bool CFuncNavCost::IsApplicableTo( CBaseCombatCharacter *who ) const return true; } + // check custom bomb_carrier tags for this bot + for( int i=0; iHasTag( pszTag ) ) + { + return true; + } + } + } + // the bomb carrier only pays attention to bomb_carrier costs return false; } @@ -217,6 +230,11 @@ bool CFuncNavCost::IsApplicableTo( CBaseCombatCharacter *who ) const } } + if ( bot->HasMission( CTFBot::MISSION_REPROGRAMMED ) ) + { + return false; + } + if ( !bot->IsOnAnyMission() ) { if ( HasTag( "common" ) ) diff --git a/mp/src/game/server/nav_mesh.cpp b/mp/src/game/server/nav_mesh.cpp index 095fabb0..05cf7ff7 100644 --- a/mp/src/game/server/nav_mesh.cpp +++ b/mp/src/game/server/nav_mesh.cpp @@ -21,13 +21,15 @@ #endif #include "functorutils.h" +#ifdef NEXT_BOT #include "NextBot/NavMeshEntities/func_nav_prerequisite.h" +#endif // NOTE: This has to be the last file included! #include "tier0/memdbgon.h" -#define DrawLine( from, to, duration, red, green, blue ) NDebugOverlay::Line( from, to, red, green, blue, true, 0.1f ) +#define DrawLine( from, to, duration, red, green, blue ) NDebugOverlay::Line( from, to, red, green, blue, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ) /** @@ -42,6 +44,7 @@ ConVar nav_show_danger( "nav_show_danger", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Sh ConVar nav_show_player_counts( "nav_show_player_counts", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show current player counts in each area." ); ConVar nav_show_func_nav_avoid( "nav_show_func_nav_avoid", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show areas of designer-placed bot avoidance due to func_nav_avoid entities" ); ConVar nav_show_func_nav_prefer( "nav_show_func_nav_prefer", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show areas of designer-placed bot preference due to func_nav_prefer entities" ); +ConVar nav_show_func_nav_prerequisite( "nav_show_func_nav_prerequisite", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show areas of designer-placed bot preference due to func_nav_prerequisite entities" ); ConVar nav_max_vis_delta_list_length( "nav_max_vis_delta_list_length", "64", FCVAR_CHEAT ); extern ConVar nav_show_potentially_visible; @@ -302,6 +305,13 @@ void CNavMesh::Update( void ) DrawFuncNavPrefer(); } +#ifdef NEXT_BOT + if ( nav_show_func_nav_prerequisite.GetBool() ) + { + DrawFuncNavPrerequisite(); + } +#endif + if ( nav_show_potentially_visible.GetBool() ) { CBasePlayer *player = UTIL_GetListenServerHost(); @@ -569,6 +579,7 @@ void CNavMesh::OnServerActivate( void ) } } +#ifdef NEXT_BOT //-------------------------------------------------------------------------------------------------------------- class CRegisterPrerequisite @@ -588,6 +599,8 @@ public: CFuncNavPrerequisite *m_prereq; }; +#endif + //-------------------------------------------------------------------------------------------------------------- /** * Test all areas for blocked status @@ -609,6 +622,7 @@ void CNavMesh::OnRoundRestart( void ) { m_updateBlockedAreasTimer.Start( 1.0f ); +#ifdef NEXT_BOT FOR_EACH_VEC( TheNavAreas, pit ) { CNavArea *area = TheNavAreas[ pit ]; @@ -626,6 +640,7 @@ void CNavMesh::OnRoundRestart( void ) ForAllAreasOverlappingExtent( apply, prereqExtent ); } +#endif } @@ -1420,7 +1435,7 @@ void CNavMesh::DrawPlayerCounts( void ) const if (area->GetPlayerCount() > 0) { - NDebugOverlay::Text( area->GetCenter(), msg.sprintf( "%d (%d/%d)", area->GetPlayerCount(), area->GetPlayerCount(1), area->GetPlayerCount(2) ), false, 0.1f ); + NDebugOverlay::Text( area->GetCenter(), msg.sprintf( "%d (%d/%d)", area->GetPlayerCount(), area->GetPlayerCount(1), area->GetPlayerCount(2) ), false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } } } @@ -1462,6 +1477,26 @@ void CNavMesh::DrawFuncNavPrefer( void ) const } +#ifdef NEXT_BOT +//-------------------------------------------------------------------------------------------------------------- +/** + * Draw bot preference areas from func_nav_prerequisite entities + */ +void CNavMesh::DrawFuncNavPrerequisite( void ) const +{ + FOR_EACH_VEC( TheNavAreas, it ) + { + CNavArea *area = TheNavAreas[ it ]; + + if ( area->HasPrerequisite() ) + { + area->DrawFilled( 0, 0, 255, 255 ); + } + } +} +#endif + + //-------------------------------------------------------------------------------------------------------------- /** * Increase the danger of nav areas containing and near the given position diff --git a/mp/src/game/server/nav_mesh.h b/mp/src/game/server/nav_mesh.h index dd608792..21dc200b 100644 --- a/mp/src/game/server/nav_mesh.h +++ b/mp/src/game/server/nav_mesh.h @@ -340,7 +340,9 @@ public: void DrawPlayerCounts( void ) const; // draw the current player counts for each area void DrawFuncNavAvoid( void ) const; // draw bot avoidance areas from func_nav_avoid entities void DrawFuncNavPrefer( void ) const; // draw bot preference areas from func_nav_prefer entities - +#ifdef NEXT_BOT + void DrawFuncNavPrerequisite( void ) const; // draw bot prerequisite areas from func_nav_prerequisite entities +#endif //------------------------------------------------------------------------------------- // Auto-generation // diff --git a/mp/src/game/server/nav_mesh.vpc b/mp/src/game/server/nav_mesh.vpc new file mode 100644 index 00000000..a9af8574 --- /dev/null +++ b/mp/src/game/server/nav_mesh.vpc @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// NAV_MESH.VPC +// +// Project script for navigation mesh files (no NextBot files) +//----------------------------------------------------------------------------- + +$Configuration +{ + $Compiler + { + $PreprocessorDefinitions "$BASE;USE_NAV_MESH" + } +} + +$Project +{ + $Folder "Source Files" + { + $Folder "Navigation Mesh" + { + $File "nav.h" + $File "nav_area.cpp" + $File "nav_area.h" + $File "nav_colors.cpp" + $File "nav_colors.h" + $File "nav_edit.cpp" + $File "nav_entities.cpp" + $File "nav_entities.h" + $File "nav_file.cpp" + $File "nav_generate.cpp" + $File "nav_ladder.cpp" + $File "nav_ladder.h" + $File "nav_merge.cpp" + $File "nav_mesh.cpp" + $File "nav_mesh.h" + $File "nav_mesh_factory.cpp" + $File "nav_node.cpp" + $File "nav_node.h" + $File "nav_pathfind.h" + $File "nav_simplify.cpp" + } + } +} \ No newline at end of file diff --git a/mp/src/game/server/server_hl2mp.vpc b/mp/src/game/server/server_hl2mp.vpc index 1dfbdbc2..e4002760 100644 --- a/mp/src/game/server/server_hl2mp.vpc +++ b/mp/src/game/server/server_hl2mp.vpc @@ -9,6 +9,7 @@ $Macro GAMENAME "hl2mp" [!$SOURCESDK] $Macro GAMENAME "mod_hl2mp" [$SOURCESDK] $Include "$SRCDIR\game\server\server_base.vpc" +$Include "$SRCDIR\game\server\nav_mesh.vpc" [$SOURCESDK] $Configuration { diff --git a/mp/src/game/server/team_control_point_master.cpp b/mp/src/game/server/team_control_point_master.cpp index 6a579e01..662d8200 100644 --- a/mp/src/game/server/team_control_point_master.cpp +++ b/mp/src/game/server/team_control_point_master.cpp @@ -24,6 +24,9 @@ BEGIN_DATADESC( CTeamControlPointMaster ) DEFINE_KEYFIELD( m_flPartialCapturePointsRate, FIELD_FLOAT, "partial_cap_points_rate" ), + DEFINE_KEYFIELD( m_flCustomPositionX, FIELD_FLOAT, "custom_position_x" ), + DEFINE_KEYFIELD( m_flCustomPositionY, FIELD_FLOAT, "custom_position_y" ), + // DEFINE_FIELD( m_ControlPoints, CUtlMap < int , CTeamControlPoint * > ), // DEFINE_FIELD( m_bFoundPoints, FIELD_BOOLEAN ), // DEFINE_FIELD( m_ControlPointRounds, CUtlVector < CTeamControlPointRound * > ), @@ -40,6 +43,8 @@ BEGIN_DATADESC( CTeamControlPointMaster ) DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ), DEFINE_INPUTFUNC( FIELD_VOID, "RoundActivate", InputRoundActivate ), DEFINE_INPUTFUNC( FIELD_STRING, "SetCapLayout", InputSetCapLayout ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetCapLayoutCustomPositionX", InputSetCapLayoutCustomPositionX ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetCapLayoutCustomPositionY", InputSetCapLayoutCustomPositionY ), DEFINE_FUNCTION( CPMThink ), @@ -70,6 +75,8 @@ int ControlPointRoundSort( CTeamControlPointRound* const *p1, CTeamControlPointR CTeamControlPointMaster::CTeamControlPointMaster() { m_flPartialCapturePointsRate = 0.0f; + m_flCustomPositionX = -1.f; + m_flCustomPositionY = -1.f; } //----------------------------------------------------------------------------- @@ -329,6 +336,7 @@ bool CTeamControlPointMaster::FindControlPointRounds( void ) { g_pObjectiveResource->SetPlayingMiniRounds( bFoundRounds ); g_pObjectiveResource->SetCapLayoutInHUD( STRING(m_iszCapLayoutInHUD) ); + g_pObjectiveResource->SetCapLayoutCustomPosition( m_flCustomPositionX, m_flCustomPositionY ); } return bFoundRounds; @@ -837,15 +845,11 @@ void CTeamControlPointMaster::InputRoundSpawn( inputdata_t &input ) // init the ClientAreas int index = 0; - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, GetTriggerAreaCaptureName() ); - while( pEnt ) + for ( int i=0; i( ITriggerAreaCaptureAutoList::AutoList()[i] ); pArea->SetAreaIndex( index ); index++; - - pEnt = gEntList.FindEntityByClassname( pEnt, GetTriggerAreaCaptureName() ); } ObjectiveResource()->ResetControlPoints(); @@ -889,6 +893,24 @@ void CTeamControlPointMaster::InputSetCapLayout( inputdata_t &inputdata ) g_pObjectiveResource->SetCapLayoutInHUD( STRING(m_iszCapLayoutInHUD) ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTeamControlPointMaster::InputSetCapLayoutCustomPositionX( inputdata_t &inputdata ) +{ + m_flCustomPositionX = inputdata.value.Float(); + g_pObjectiveResource->SetCapLayoutCustomPosition( m_flCustomPositionX, m_flCustomPositionY ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTeamControlPointMaster::InputSetCapLayoutCustomPositionY( inputdata_t &inputdata ) +{ + m_flCustomPositionY = inputdata.value.Float(); + g_pObjectiveResource->SetCapLayoutCustomPosition( m_flCustomPositionX, m_flCustomPositionY ); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/team_control_point_master.h b/mp/src/game/server/team_control_point_master.h index 48265ba6..64b1e9b5 100644 --- a/mp/src/game/server/team_control_point_master.h +++ b/mp/src/game/server/team_control_point_master.h @@ -36,7 +36,6 @@ public: CTeamControlPointMaster(); // Used to find game specific entities - virtual const char *GetTriggerAreaCaptureName( void ) { return "trigger_capture_area"; } virtual const char *GetControlPointName( void ) { return "team_control_point"; } virtual const char *GetControlPointRoundName( void ) { return "team_control_point_round"; } @@ -182,6 +181,8 @@ private: void InputSetWinner( inputdata_t &inputdata ); void InputSetWinnerAndForceCaps( inputdata_t &inputdata ); void InputSetCapLayout( inputdata_t &inputdata ); + void InputSetCapLayoutCustomPositionX( inputdata_t &inputdata ); + void InputSetCapLayoutCustomPositionY( inputdata_t &inputdata ); void InternalSetWinner( int iTeam ); @@ -191,6 +192,9 @@ private: int m_iTeamBaseIcons[MAX_TEAMS]; string_t m_iszCapLayoutInHUD; + float m_flCustomPositionX; + float m_flCustomPositionY; + int m_iInvalidCapWinner; bool m_bSwitchTeamsOnWin; bool m_bScorePerCapture; diff --git a/mp/src/game/server/team_control_point_round.cpp b/mp/src/game/server/team_control_point_round.cpp index cc3d0cc7..c9e36bd7 100644 --- a/mp/src/game/server/team_control_point_round.cpp +++ b/mp/src/game/server/team_control_point_round.cpp @@ -365,33 +365,27 @@ bool CTeamControlPointRound::MakePlayable( void ) if ( !IsPlayable() ) { // we need to try switching the owners of the teams to make this round playable - for ( int i = FIRST_GAME_TEAM ; i < GetNumberOfTeams() ; i++ ) + for ( int iTeam = FIRST_GAME_TEAM ; iTeam < GetNumberOfTeams() ; iTeam++ ) { - for ( int j = 0 ; j < m_ControlPoints.Count() ; j++ ) + for ( int iControlPoint = 0 ; iControlPoint < m_ControlPoints.Count() ; iControlPoint++ ) { - if ( ( !pMaster->IsBaseControlPoint( m_ControlPoints[j]->GetPointIndex() ) ) && // this is NOT the base point for one of the teams (we don't want to assign the base to the wrong team) - ( !WouldNewCPOwnerWinGame( m_ControlPoints[j], i ) ) ) // making this change would make this round playable + if ( ( !pMaster->IsBaseControlPoint( m_ControlPoints[iControlPoint]->GetPointIndex() ) ) && // this is NOT the base point for one of the teams (we don't want to assign the base to the wrong team) + ( !WouldNewCPOwnerWinGame( m_ControlPoints[iControlPoint], iTeam ) ) ) // making this change would make this round playable { // need to find the trigger area associated with this point - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, pMaster->GetTriggerAreaCaptureName() ); - while( pEnt ) + for ( int iObj=0; iObj( pEnt ); - if ( pArea ) - { - if ( pArea->TeamCanCap( i ) ) + CTriggerAreaCapture *pArea = static_cast< CTriggerAreaCapture * >( ITriggerAreaCaptureAutoList::AutoList()[iObj] ); + if ( pArea->TeamCanCap( iTeam ) ) + { + CHandle hPoint = pArea->GetControlPoint(); + if ( hPoint == m_ControlPoints[iControlPoint] ) { - CHandle hPoint = pArea->GetControlPoint(); - if ( hPoint == m_ControlPoints[j] ) - { - // found! - pArea->ForceOwner( i ); // this updates the trigger_area *and* the control_point - return true; - } + // found! + pArea->ForceOwner( iTeam ); // this updates the trigger_area *and* the control_point + return true; } } - - pEnt = gEntList.FindEntityByClassname( pEnt, pMaster->GetTriggerAreaCaptureName() ); } } } diff --git a/mp/src/game/server/team_objectiveresource.cpp b/mp/src/game/server/team_objectiveresource.cpp index 9f8d0e7f..f7dd502e 100644 --- a/mp/src/game/server/team_objectiveresource.cpp +++ b/mp/src/game/server/team_objectiveresource.cpp @@ -61,7 +61,10 @@ IMPLEMENT_SERVERCLASS_ST_NOBASE(CBaseTeamObjectiveResource, DT_BaseTeamObjective SendPropArray3( SENDINFO_ARRAY3(m_iTeamInZone), SendPropInt( SENDINFO_ARRAY(m_iTeamInZone), 4, SPROP_UNSIGNED ) ), SendPropArray3( SENDINFO_ARRAY3(m_bBlocked), SendPropInt( SENDINFO_ARRAY(m_bBlocked), 1, SPROP_UNSIGNED ) ), SendPropArray3( SENDINFO_ARRAY3(m_iOwner), SendPropInt( SENDINFO_ARRAY(m_iOwner), 4, SPROP_UNSIGNED ) ), + SendPropArray3( SENDINFO_ARRAY3(m_bCPCapRateScalesWithPlayers), SendPropBool( SENDINFO_ARRAY(m_bCPCapRateScalesWithPlayers) ) ), SendPropString( SENDINFO(m_pszCapLayoutInHUD) ), + SendPropFloat( SENDINFO( m_flCustomPositionX ) ), + SendPropFloat( SENDINFO( m_flCustomPositionY ) ), END_SEND_TABLE() @@ -72,6 +75,8 @@ BEGIN_DATADESC( CBaseTeamObjectiveResource ) DEFINE_FIELD( m_bPlayingMiniRounds, FIELD_BOOLEAN ), DEFINE_FIELD( m_bControlPointsReset, FIELD_BOOLEAN ), DEFINE_FIELD( m_iUpdateCapHudParity, FIELD_INTEGER ), + DEFINE_FIELD( m_flCustomPositionX, FIELD_FLOAT ), + DEFINE_FIELD( m_flCustomPositionY, FIELD_FLOAT ), DEFINE_ARRAY( m_vCPPositions, FIELD_VECTOR, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_bCPIsVisible, FIELD_INTEGER, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_flLazyCapPerc, FIELD_FLOAT, MAX_CONTROL_POINTS ), @@ -91,6 +96,7 @@ BEGIN_DATADESC( CBaseTeamObjectiveResource ) DEFINE_ARRAY( m_iTeamInZone, FIELD_INTEGER, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_bBlocked, FIELD_BOOLEAN, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_iOwner, FIELD_INTEGER, MAX_CONTROL_POINTS ), + DEFINE_ARRAY( m_bCPCapRateScalesWithPlayers, FIELD_BOOLEAN, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_pszCapLayoutInHUD, FIELD_CHARACTER, MAX_CAPLAYOUT_LENGTH ), DEFINE_ARRAY( m_flCapPercentages, FIELD_FLOAT, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_iCPGroup, FIELD_INTEGER, MAX_CONTROL_POINTS ), @@ -114,6 +120,8 @@ CBaseTeamObjectiveResource::CBaseTeamObjectiveResource() m_bPlayingMiniRounds = false; m_iUpdateCapHudParity = 0; m_bControlPointsReset = false; + m_flCustomPositionX = -1.f; + m_flCustomPositionY = -1.f; } //----------------------------------------------------------------------------- @@ -153,6 +161,7 @@ void CBaseTeamObjectiveResource::Spawn( void ) m_bCPLocked.Set( i, false ); m_flUnlockTimes.Set( i, 0.0 ); m_flCPTimerTimes.Set( i, -1.0 ); + m_bCPCapRateScalesWithPlayers.Set( i, true ); for ( int team = 0; team < MAX_CONTROL_POINT_TEAMS; team++ ) { @@ -381,6 +390,15 @@ void CBaseTeamObjectiveResource::SetCPTimerTime( int index, float flTime ) m_flCPTimerTimes.Set( index, flTime ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseTeamObjectiveResource::SetCPCapTimeScalesWithPlayers( int index, bool bScales ) +{ + AssertValidIndex(index); + m_bCPCapRateScalesWithPlayers.Set( index, bScales ); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/team_objectiveresource.h b/mp/src/game/server/team_objectiveresource.h index 40d1920c..5cc42009 100644 --- a/mp/src/game/server/team_objectiveresource.h +++ b/mp/src/game/server/team_objectiveresource.h @@ -58,6 +58,7 @@ public: int GetPreviousPointForPoint( int index, int team, int iPrevIndex ); bool TeamCanCapPoint( int index, int team ); void SetCapLayoutInHUD( const char *pszLayout ) { Q_strncpy(m_pszCapLayoutInHUD.GetForModify(), pszLayout, MAX_CAPLAYOUT_LENGTH ); } + void SetCapLayoutCustomPosition( float flPositionX, float flPositionY ) { m_flCustomPositionX = flPositionX; m_flCustomPositionY = flPositionY; } void SetWarnOnCap( int index, int iWarnLevel ); void SetWarnSound( int index, string_t iszSound ); void SetCPGroup( int index, int iCPGroup ); @@ -65,6 +66,7 @@ public: void SetTrackAlarm( int index, bool bAlarm ); void SetCPUnlockTime( int index, float flTime ); void SetCPTimerTime( int index, float flTime ); + void SetCPCapTimeScalesWithPlayers( int index, bool bScales ); // State functions, called many times void SetNumPlayers( int index, int team, int iNumPlayers ); @@ -205,10 +207,15 @@ private: // changes when a point is successfully captured CNetworkArray( int, m_iOwner, MAX_CONTROL_POINTS ); + CNetworkArray( bool, m_bCPCapRateScalesWithPlayers, MAX_CONTROL_POINTS ); // describes how to lay out the cap points in the hud CNetworkString( m_pszCapLayoutInHUD, MAX_CAPLAYOUT_LENGTH ); + // custom screen position for the cap points in the hud + CNetworkVar( float, m_flCustomPositionX ); + CNetworkVar( float, m_flCustomPositionY ); + // the groups the points belong to CNetworkArray( int, m_iCPGroup, MAX_CONTROL_POINTS ); diff --git a/mp/src/game/server/team_train_watcher.cpp b/mp/src/game/server/team_train_watcher.cpp index 27d7a15c..cf6631fb 100644 --- a/mp/src/game/server/team_train_watcher.cpp +++ b/mp/src/game/server/team_train_watcher.cpp @@ -819,17 +819,15 @@ void CTeamTrainWatcher::WatcherActivate( void ) { if ( m_hTrain ) { - CTriggerAreaCapture *pArea = dynamic_cast( gEntList.FindEntityByClassname( NULL, "trigger_capture_area" ) ); - while( pArea ) + for ( int i=0; i( ITriggerAreaCaptureAutoList::AutoList()[i] ); if ( pArea->GetParent() == m_hTrain.Get() ) { // this is the capture area we care about, so let it know that we want updates on the capture numbers pArea->SetTrainWatcher( this ); break; } - - pArea = dynamic_cast( gEntList.FindEntityByClassname( pArea, "trigger_capture_area" ) ); } } diff --git a/mp/src/game/server/trigger_area_capture.cpp b/mp/src/game/server/trigger_area_capture.cpp index fcf3a868..665bd005 100644 --- a/mp/src/game/server/trigger_area_capture.cpp +++ b/mp/src/game/server/trigger_area_capture.cpp @@ -18,10 +18,12 @@ extern ConVar mp_capstyle; extern ConVar mp_blockstyle; extern ConVar mp_capdeteriorate_time; +IMPLEMENT_AUTO_LIST( ITriggerAreaCaptureAutoList ); + BEGIN_DATADESC(CTriggerAreaCapture) // Touch functions - DEFINE_FUNCTION( AreaTouch ), + DEFINE_FUNCTION( CTriggerAreaCaptureShim::Touch ), // Think functions DEFINE_THINKFUNC( CaptureThink ), @@ -96,7 +98,7 @@ void CTriggerAreaCapture::Spawn( void ) m_iAreaIndex = -1; - SetTouch ( &CTriggerAreaCapture::AreaTouch ); + SetTouch ( &CTriggerAreaCaptureShim::Touch ); SetThink( &CTriggerAreaCapture::CaptureThink ); SetNextThink( gpGlobals->curtime + AREA_THINK_TIME ); @@ -250,6 +252,14 @@ void CTriggerAreaCapture::EndTouch(CBaseEntity *pOther) BaseClass::EndTouch( pOther ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTriggerAreaCapture::CaptureModeScalesWithPlayers() const +{ + return mp_capstyle.GetBool(); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -469,7 +479,7 @@ void CTriggerAreaCapture::CaptureThink( void ) float flTimeDelta = gpGlobals->curtime - m_flLastReductionTime; float flReduction = flTimeDelta; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { // Diminishing returns for successive players. for ( int i = 1; i < m_TeamData[m_nTeamInZone].iNumTouching; i++ ) @@ -490,7 +500,7 @@ void CTriggerAreaCapture::CaptureThink( void ) // See if anyone gets credit for the block float flPercentToGo = m_fTimeRemaining / m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { flPercentToGo = m_fTimeRemaining / ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); } @@ -561,7 +571,7 @@ void CTriggerAreaCapture::CaptureThink( void ) } float flTotalTimeToCap = m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { flTotalTimeToCap = ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); } @@ -580,7 +590,8 @@ void CTriggerAreaCapture::CaptureThink( void ) // Caps deteriorate over time if ( TeamplayRoundBasedRules() && m_hPoint && TeamplayRoundBasedRules()->TeamMayCapturePoint(m_nCapturingTeam,m_hPoint->GetPointIndex()) ) { - float flDecrease = (flTotalTimeToCap / mp_capdeteriorate_time.GetFloat()) * flTimeDelta; + float flDecreaseScale = CaptureModeScalesWithPlayers() ? mp_capdeteriorate_time.GetFloat() : flTotalTimeToCap; + float flDecrease = (flTotalTimeToCap / flDecreaseScale) * flTimeDelta; if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->InOvertime() ) { flDecrease *= 6; @@ -649,7 +660,7 @@ void CTriggerAreaCapture::CaptureThink( void ) if ( m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToStartCap ) continue; - if ( mp_capstyle.GetInt() == 0 && m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToCap ) + if ( !CaptureModeScalesWithPlayers() && m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToCap ) continue; StartCapture( i, CAPTURE_NORMAL ); @@ -670,7 +681,7 @@ void CTriggerAreaCapture::SetCapTimeRemaining( float flTime ) if ( m_nCapturingTeam ) { flCapPercentage = m_fTimeRemaining / m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { flCapPercentage = m_fTimeRemaining / ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); } @@ -762,7 +773,7 @@ void CTriggerAreaCapture::StartCapture( int team, int capmode ) UpdateNumPlayers(); - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { SetCapTimeRemaining( ((m_flCapTime * 2) * m_TeamData[team].iNumRequiredToCap) ); } @@ -1017,7 +1028,7 @@ void CTriggerAreaCapture::InputRoundSpawn( inputdata_t &inputdata ) ObjectiveResource()->SetCPRequiredCappers( m_hPoint->GetPointIndex(), i, m_TeamData[i].iNumRequiredToCap ); ObjectiveResource()->SetTeamCanCap( m_hPoint->GetPointIndex(), i, m_TeamData[i].bCanCap ); - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { ObjectiveResource()->SetCPCapTime( m_hPoint->GetPointIndex(), i, (m_flCapTime * 2) * m_TeamData[i].iNumRequiredToCap ); } @@ -1025,6 +1036,8 @@ void CTriggerAreaCapture::InputRoundSpawn( inputdata_t &inputdata ) { ObjectiveResource()->SetCPCapTime( m_hPoint->GetPointIndex(), i, m_flCapTime ); } + + ObjectiveResource()->SetCPCapTimeScalesWithPlayers( m_hPoint->GetPointIndex(), CaptureModeScalesWithPlayers() ); } } } @@ -1125,7 +1138,7 @@ bool CTriggerAreaCapture::CheckIfDeathCausesBlock( CBaseMultiplayerPlayer *pVict // break early incase we kill multiple people in the same frame bool bBreakCap = false; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { bBreakCap = ( m_TeamData[m_nCapturingTeam].iBlockedTouching - 1 ) <= 0; } diff --git a/mp/src/game/server/trigger_area_capture.h b/mp/src/game/server/trigger_area_capture.h index e2e494c9..383f3fad 100644 --- a/mp/src/game/server/trigger_area_capture.h +++ b/mp/src/game/server/trigger_area_capture.h @@ -32,9 +32,19 @@ class CTeamTrainWatcher; // Can either be capped by both teams at once, or just by one // Time to capture and number of people required to capture are both passed by the mapper //----------------------------------------------------------------------------- -class CTriggerAreaCapture : public CBaseTrigger +// This class is to get around the fact that DEFINE_FUNCTION doesn't like multiple inheritance +class CTriggerAreaCaptureShim : public CBaseTrigger { - DECLARE_CLASS( CTriggerAreaCapture, CBaseTrigger ); + virtual void AreaTouch( CBaseEntity *pOther ) = 0; +public: + void Touch( CBaseEntity *pOther ) { return AreaTouch( pOther ) ; } +}; + +DECLARE_AUTO_LIST( ITriggerAreaCaptureAutoList ); + +class CTriggerAreaCapture : public CTriggerAreaCaptureShim, public ITriggerAreaCaptureAutoList +{ + DECLARE_CLASS( CTriggerAreaCapture, CTriggerAreaCaptureShim ); public: CTriggerAreaCapture(); @@ -73,10 +83,17 @@ public: void SetTrainWatcher( CTeamTrainWatcher *pTrainWatcher ){ m_hTrainWatcher = pTrainWatcher; } // used for train watchers that control train movement CTeamTrainWatcher *GetTrainWatcher( void ) const { return m_hTrainWatcher; } + virtual void StartTouch(CBaseEntity *pOther) OVERRIDE; + virtual void EndTouch(CBaseEntity *pOther) OVERRIDE; + + float GetCapTime() const { return m_flCapTime; } + +protected: + + virtual bool CaptureModeScalesWithPlayers() const; + private: - void StartTouch(CBaseEntity *pOther); - void EXPORT AreaTouch( CBaseEntity *pOther ); - void EndTouch(CBaseEntity *pOther); + virtual void AreaTouch( CBaseEntity *pOther ) OVERRIDE; void CaptureThink( void ); void StartCapture( int team, int capmode ); diff --git a/mp/src/game/server/vote_controller.cpp b/mp/src/game/server/vote_controller.cpp index f2c8e2f4..a2fcfd99 100644 --- a/mp/src/game/server/vote_controller.cpp +++ b/mp/src/game/server/vote_controller.cpp @@ -346,6 +346,19 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons Assert( nNumVoteOptions >= 2 ); } + // Have the issue start working on it + pCurrentIssue->OnVoteStarted(); + + // Now the vote handling and UI + m_nPotentialVotes = pCurrentIssue->CountPotentialVoters(); + m_acceptingVotesTimer.Start( sv_vote_timer_duration.GetFloat() ); + + // Force the vote holder to agree with a Yes/No vote + if ( m_bIsYesNoVote && !bDedicatedServer ) + { + TryCastVote( iEntIndex, "Option1" ); + } + // Get the data out to the client CBroadcastRecipientFilter filter; filter.MakeReliable(); @@ -357,16 +370,6 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons WRITE_BOOL( m_bIsYesNoVote ); MessageEnd(); - // Force the vote holder to agree with a Yes/No vote - if ( m_bIsYesNoVote && !bDedicatedServer ) - { - TryCastVote( iEntIndex, "Option1" ); - } - - m_nPotentialVotes = pCurrentIssue->CountPotentialVoters(); - m_acceptingVotesTimer.Start( sv_vote_timer_duration.GetFloat() ); - pCurrentIssue->OnVoteStarted(); - if ( !bDedicatedServer ) { TrackVoteCaller( pVoteCaller ); diff --git a/mp/src/game/shared/activitylist.cpp b/mp/src/game/shared/activitylist.cpp index 1b61fb64..a69933c9 100644 --- a/mp/src/game/shared/activitylist.cpp +++ b/mp/src/game/shared/activitylist.cpp @@ -2265,6 +2265,11 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_MP_RELOAD_AIRWALK_PRIMARY3_END ); REGISTER_SHARED_ACTIVITY( ACT_MP_RELOAD_SWIM_PRIMARY3 ); + REGISTER_SHARED_ACTIVITY( ACT_MP_THROW ); + REGISTER_SHARED_ACTIVITY( ACT_THROWABLE_VM_DRAW ); + REGISTER_SHARED_ACTIVITY( ACT_THROWABLE_VM_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_THROWABLE_VM_FIRE ); + AssertMsg( g_HighestActivity == LAST_SHARED_ACTIVITY - 1, "Not all activities from ai_activity.h registered in activitylist.cpp" ); } diff --git a/mp/src/game/shared/ai_activity.h b/mp/src/game/shared/ai_activity.h index 854da726..4e94fca8 100644 --- a/mp/src/game/shared/ai_activity.h +++ b/mp/src/game/shared/ai_activity.h @@ -2095,6 +2095,13 @@ typedef enum ACT_MP_RELOAD_AIRWALK_PRIMARY3_END, ACT_MP_RELOAD_SWIM_PRIMARY3, + // Throwable Animations + ACT_MP_THROW, + + ACT_THROWABLE_VM_DRAW, + ACT_THROWABLE_VM_IDLE, + ACT_THROWABLE_VM_FIRE, + // this is the end of the global activities, private per-monster activities start here. LAST_SHARED_ACTIVITY, } Activity; diff --git a/mp/src/game/shared/baseentity_shared.cpp b/mp/src/game/shared/baseentity_shared.cpp index 470b2d2e..949143b1 100644 --- a/mp/src/game/shared/baseentity_shared.cpp +++ b/mp/src/game/shared/baseentity_shared.cpp @@ -48,6 +48,11 @@ ConVar hl2_episodic( "hl2_episodic", "0", FCVAR_REPLICATED ); #include "prop_portal_shared.h" #endif +#ifdef TF_DLL +#include "tf_gamerules.h" +#include "tf_weaponbase.h" +#endif // TF_DLL + #include "rumble_shared.h" // memdbgon must be the last include file in a .cpp file!!! @@ -1746,6 +1751,17 @@ void CBaseEntity::FireBullets( const FireBulletsInfo_t &info ) { pShootThroughPortal = NULL; } +#elif TF_DLL + CTraceFilterIgnoreFriendlyCombatItems traceFilterCombatItem( this, COLLISION_GROUP_NONE, GetTeamNumber() ); + if ( TFGameRules() && TFGameRules()->GameModeUsesUpgrades() ) + { + CTraceFilterChain traceFilterChain( &traceFilter, &traceFilterCombatItem ); + AI_TraceLine(info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilterChain, &tr); + } + else + { + AI_TraceLine(info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilter, &tr); + } #else AI_TraceLine(info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilter, &tr); #endif //#ifdef PORTAL diff --git a/mp/src/game/shared/multiplay_gamerules.cpp b/mp/src/game/shared/multiplay_gamerules.cpp index f933634c..2cbb6f61 100644 --- a/mp/src/game/shared/multiplay_gamerules.cpp +++ b/mp/src/game/shared/multiplay_gamerules.cpp @@ -1223,7 +1223,7 @@ ConVarRef suitcharger( "sk_suitcharger" ); { if ( bForceSpew || V_stricmp( szLastResult, pszResult) ) { - Msg( "Using map cycle file %s.\n", pszResult ); + Msg( "Using map cycle file '%s'.\n", pszResult ); V_strcpy_safe( szLastResult, pszResult ); } return; diff --git a/mp/src/game/shared/particle_property.cpp b/mp/src/game/shared/particle_property.cpp index b1ae32a7..18d278ad 100644 --- a/mp/src/game/shared/particle_property.cpp +++ b/mp/src/game/shared/particle_property.cpp @@ -26,6 +26,12 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" +#ifdef STAGING_ONLY +#ifdef TF_CLIENT_DLL +extern ConVar tf_unusual_effect_offset; +#endif +#endif + //----------------------------------------------------------------------------- // Save/load //----------------------------------------------------------------------------- diff --git a/mp/src/game/shared/playernet_vars.h b/mp/src/game/shared/playernet_vars.h index abb49765..9fdeec0f 100644 --- a/mp/src/game/shared/playernet_vars.h +++ b/mp/src/game/shared/playernet_vars.h @@ -77,10 +77,10 @@ struct fogplayerparams_t { m_hCtrl.Set( NULL ); m_flTransitionTime = -1.0f; - m_OldColor.r = m_OldColor.g = m_OldColor.b = m_OldColor.a = 0; + m_OldColor.r = m_OldColor.g = m_OldColor.g = m_OldColor.a = 0.0f; m_flOldStart = 0.0f; m_flOldEnd = 0.0f; - m_NewColor.r = m_NewColor.g = m_NewColor.b = m_NewColor.a = 0; + m_NewColor.r = m_NewColor.g = m_NewColor.g = m_NewColor.a = 0.0f; m_flNewStart = 0.0f; m_flNewEnd = 0.0f; } diff --git a/mp/src/game/shared/teamplay_round_timer.h b/mp/src/game/shared/teamplay_round_timer.h index 7826cf5b..470a5f16 100644 --- a/mp/src/game/shared/teamplay_round_timer.h +++ b/mp/src/game/shared/teamplay_round_timer.h @@ -79,6 +79,7 @@ public: void SetStopWatch( bool bState ) { m_bStopWatchTimer = bState; } bool IsStopWatchTimer( void ) { return m_bStopWatchTimer; } float GetStopWatchTotalTime( void ) { return m_flTotalTime; } + bool IsRoundMaxTimerSet( void ) { return m_nTimerMaxLength > 0; } private: diff --git a/mp/src/game/shared/teamplayroundbased_gamerules.cpp b/mp/src/game/shared/teamplayroundbased_gamerules.cpp index f737aecf..a843d134 100644 --- a/mp/src/game/shared/teamplayroundbased_gamerules.cpp +++ b/mp/src/game/shared/teamplayroundbased_gamerules.cpp @@ -38,7 +38,7 @@ #if defined(TF_CLIENT_DLL) || defined(TF_DLL) #include "tf_lobby.h" #ifdef GAME_DLL - #include "player_vs_environment/tf_populator.h" + #include "player_vs_environment/tf_population_manager.h" #include "../server/tf/tf_gc_server.h" #include "../server/tf/tf_objective_resource.h" #else diff --git a/mp/src/game/shared/voice_status.cpp b/mp/src/game/shared/voice_status.cpp index 4d295713..ed6c0f2f 100644 --- a/mp/src/game/shared/voice_status.cpp +++ b/mp/src/game/shared/voice_status.cpp @@ -425,7 +425,7 @@ void CVoiceStatus::UpdateServerState(bool bForce) void CVoiceStatus::HandleVoiceMaskMsg(bf_read &msg) { - unsigned long dw; + unsigned int dw; for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) { m_AudiblePlayers.SetDWord(dw, (unsigned long)msg.ReadLong()); @@ -434,8 +434,8 @@ void CVoiceStatus::HandleVoiceMaskMsg(bf_read &msg) if( voice_clientdebug.GetInt()) { Msg("CVoiceStatus::HandleVoiceMaskMsg\n"); - Msg(" - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord(dw)); - Msg(" - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord(dw)); + Msg(" - m_AudiblePlayers[%d] = %u\n", dw, m_AudiblePlayers.GetDWord(dw)); + Msg(" - m_ServerBannedPlayers[%d] = %u\n", dw, m_ServerBannedPlayers.GetDWord(dw)); } } diff --git a/mp/src/lib/osx32/bitmap.a b/mp/src/lib/osx32/bitmap.a index 083bebc3..cfdb3754 100644 Binary files a/mp/src/lib/osx32/bitmap.a and b/mp/src/lib/osx32/bitmap.a differ diff --git a/mp/src/lib/osx32/choreoobjects.a b/mp/src/lib/osx32/choreoobjects.a index caa6d1cd..47431a06 100644 Binary files a/mp/src/lib/osx32/choreoobjects.a and b/mp/src/lib/osx32/choreoobjects.a differ diff --git a/mp/src/lib/osx32/dmxloader.a b/mp/src/lib/osx32/dmxloader.a index 5ace7439..bdbf0211 100644 Binary files a/mp/src/lib/osx32/dmxloader.a and b/mp/src/lib/osx32/dmxloader.a differ diff --git a/mp/src/lib/osx32/libtier0.dylib b/mp/src/lib/osx32/libtier0.dylib index e217d299..af6b5c58 100644 Binary files a/mp/src/lib/osx32/libtier0.dylib and b/mp/src/lib/osx32/libtier0.dylib differ diff --git a/mp/src/lib/osx32/libvstdlib.dylib b/mp/src/lib/osx32/libvstdlib.dylib index 99e9495a..4a7a32a6 100644 Binary files a/mp/src/lib/osx32/libvstdlib.dylib and b/mp/src/lib/osx32/libvstdlib.dylib differ diff --git a/mp/src/lib/osx32/matsys_controls.a b/mp/src/lib/osx32/matsys_controls.a index 84c5ed52..75d6fc9e 100644 Binary files a/mp/src/lib/osx32/matsys_controls.a and b/mp/src/lib/osx32/matsys_controls.a differ diff --git a/mp/src/lib/osx32/particles.a b/mp/src/lib/osx32/particles.a index fe4c9efd..7808c3f8 100644 Binary files a/mp/src/lib/osx32/particles.a and b/mp/src/lib/osx32/particles.a differ diff --git a/mp/src/lib/osx32/tier2.a b/mp/src/lib/osx32/tier2.a index 503e2663..5b374e52 100644 Binary files a/mp/src/lib/osx32/tier2.a and b/mp/src/lib/osx32/tier2.a differ diff --git a/mp/src/lib/osx32/tier3.a b/mp/src/lib/osx32/tier3.a index 33a789ec..2bc80e46 100644 Binary files a/mp/src/lib/osx32/tier3.a and b/mp/src/lib/osx32/tier3.a differ diff --git a/mp/src/lib/osx32/vtf.a b/mp/src/lib/osx32/vtf.a index 66baf6f2..c0ef3476 100644 Binary files a/mp/src/lib/osx32/vtf.a and b/mp/src/lib/osx32/vtf.a differ diff --git a/mp/src/lib/public/appframework.lib b/mp/src/lib/public/appframework.lib index a32303f1..c69838ca 100644 Binary files a/mp/src/lib/public/appframework.lib and b/mp/src/lib/public/appframework.lib differ diff --git a/mp/src/lib/public/bitmap.lib b/mp/src/lib/public/bitmap.lib index a467de69..cf3530fc 100644 Binary files a/mp/src/lib/public/bitmap.lib and b/mp/src/lib/public/bitmap.lib differ diff --git a/mp/src/lib/public/choreoobjects.lib b/mp/src/lib/public/choreoobjects.lib index 40e42d7f..eb31ddd4 100644 Binary files a/mp/src/lib/public/choreoobjects.lib and b/mp/src/lib/public/choreoobjects.lib differ diff --git a/mp/src/lib/public/dmxloader.lib b/mp/src/lib/public/dmxloader.lib index 4f25a567..18edcba5 100644 Binary files a/mp/src/lib/public/dmxloader.lib and b/mp/src/lib/public/dmxloader.lib differ diff --git a/mp/src/lib/public/fgdlib.lib b/mp/src/lib/public/fgdlib.lib index 4f3de80e..fb1aafd9 100644 Binary files a/mp/src/lib/public/fgdlib.lib and b/mp/src/lib/public/fgdlib.lib differ diff --git a/mp/src/lib/public/linux32/bitmap.a b/mp/src/lib/public/linux32/bitmap.a index 39a1dc3e..bbd65285 100644 Binary files a/mp/src/lib/public/linux32/bitmap.a and b/mp/src/lib/public/linux32/bitmap.a differ diff --git a/mp/src/lib/public/linux32/choreoobjects.a b/mp/src/lib/public/linux32/choreoobjects.a index 96a9ba79..bbeb2ef3 100644 Binary files a/mp/src/lib/public/linux32/choreoobjects.a and b/mp/src/lib/public/linux32/choreoobjects.a differ diff --git a/mp/src/lib/public/linux32/dmxloader.a b/mp/src/lib/public/linux32/dmxloader.a index 6c3bf0ac..71d39e95 100644 Binary files a/mp/src/lib/public/linux32/dmxloader.a and b/mp/src/lib/public/linux32/dmxloader.a differ diff --git a/mp/src/lib/public/linux32/libSDL2-2.0.so.0 b/mp/src/lib/public/linux32/libSDL2-2.0.so.0 new file mode 100644 index 00000000..5908adb7 Binary files /dev/null and b/mp/src/lib/public/linux32/libSDL2-2.0.so.0 differ diff --git a/mp/src/lib/public/linux32/libSDL2.so b/mp/src/lib/public/linux32/libSDL2.so new file mode 100644 index 00000000..d58bb41c --- /dev/null +++ b/mp/src/lib/public/linux32/libSDL2.so @@ -0,0 +1 @@ +libSDL2-2.0.so.0 diff --git a/mp/src/lib/public/linux32/libtier0.so b/mp/src/lib/public/linux32/libtier0.so index 365d88bd..cd02bc3b 100644 Binary files a/mp/src/lib/public/linux32/libtier0.so and b/mp/src/lib/public/linux32/libtier0.so differ diff --git a/mp/src/lib/public/linux32/libvstdlib.so b/mp/src/lib/public/linux32/libvstdlib.so index fa19b46c..f6aea107 100644 Binary files a/mp/src/lib/public/linux32/libvstdlib.so and b/mp/src/lib/public/linux32/libvstdlib.so differ diff --git a/mp/src/lib/public/linux32/matsys_controls.a b/mp/src/lib/public/linux32/matsys_controls.a index d758fa8e..1a284e03 100644 Binary files a/mp/src/lib/public/linux32/matsys_controls.a and b/mp/src/lib/public/linux32/matsys_controls.a differ diff --git a/mp/src/lib/public/linux32/particles.a b/mp/src/lib/public/linux32/particles.a index e788bdb4..626fecaf 100644 Binary files a/mp/src/lib/public/linux32/particles.a and b/mp/src/lib/public/linux32/particles.a differ diff --git a/mp/src/lib/public/linux32/tier2.a b/mp/src/lib/public/linux32/tier2.a index a9c78bb8..a440a0b7 100644 Binary files a/mp/src/lib/public/linux32/tier2.a and b/mp/src/lib/public/linux32/tier2.a differ diff --git a/mp/src/lib/public/linux32/tier3.a b/mp/src/lib/public/linux32/tier3.a index 98d6839d..77f98b2b 100644 Binary files a/mp/src/lib/public/linux32/tier3.a and b/mp/src/lib/public/linux32/tier3.a differ diff --git a/mp/src/lib/public/linux32/vtf.a b/mp/src/lib/public/linux32/vtf.a index cb4e892e..4d7f1f26 100644 Binary files a/mp/src/lib/public/linux32/vtf.a and b/mp/src/lib/public/linux32/vtf.a differ diff --git a/mp/src/lib/public/mathlib.lib b/mp/src/lib/public/mathlib.lib index 56985a5c..d581b673 100644 Binary files a/mp/src/lib/public/mathlib.lib and b/mp/src/lib/public/mathlib.lib differ diff --git a/mp/src/lib/public/matsys_controls.lib b/mp/src/lib/public/matsys_controls.lib index 803f997f..bf1da093 100644 Binary files a/mp/src/lib/public/matsys_controls.lib and b/mp/src/lib/public/matsys_controls.lib differ diff --git a/mp/src/lib/public/nvtristrip.lib b/mp/src/lib/public/nvtristrip.lib index 12f88e14..21185355 100644 Binary files a/mp/src/lib/public/nvtristrip.lib and b/mp/src/lib/public/nvtristrip.lib differ diff --git a/mp/src/lib/public/osx32/libSDL2-2.0.0.dylib b/mp/src/lib/public/osx32/libSDL2-2.0.0.dylib new file mode 100644 index 00000000..3fd8c749 Binary files /dev/null and b/mp/src/lib/public/osx32/libSDL2-2.0.0.dylib differ diff --git a/mp/src/lib/public/osx32/libSDL2.dylib b/mp/src/lib/public/osx32/libSDL2.dylib new file mode 100644 index 00000000..4122f22f --- /dev/null +++ b/mp/src/lib/public/osx32/libSDL2.dylib @@ -0,0 +1 @@ +libSDL2-2.0.0.dylib diff --git a/mp/src/lib/public/particles.lib b/mp/src/lib/public/particles.lib index 2d5d6f0b..4f78b611 100644 Binary files a/mp/src/lib/public/particles.lib and b/mp/src/lib/public/particles.lib differ diff --git a/mp/src/lib/public/raytrace.lib b/mp/src/lib/public/raytrace.lib index 6b470314..2b9ad265 100644 Binary files a/mp/src/lib/public/raytrace.lib and b/mp/src/lib/public/raytrace.lib differ diff --git a/mp/src/lib/public/shaderlib.lib b/mp/src/lib/public/shaderlib.lib new file mode 100644 index 00000000..53a7744d Binary files /dev/null and b/mp/src/lib/public/shaderlib.lib differ diff --git a/mp/src/lib/public/tier0.lib b/mp/src/lib/public/tier0.lib index 7c85b7f1..da3ed75c 100644 Binary files a/mp/src/lib/public/tier0.lib and b/mp/src/lib/public/tier0.lib differ diff --git a/mp/src/lib/public/tier1.lib b/mp/src/lib/public/tier1.lib index aedd4b28..d9293e4a 100644 Binary files a/mp/src/lib/public/tier1.lib and b/mp/src/lib/public/tier1.lib differ diff --git a/mp/src/lib/public/tier2.lib b/mp/src/lib/public/tier2.lib index d071c271..6600cb7f 100644 Binary files a/mp/src/lib/public/tier2.lib and b/mp/src/lib/public/tier2.lib differ diff --git a/mp/src/lib/public/tier3.lib b/mp/src/lib/public/tier3.lib index 1ba407a2..a549f07e 100644 Binary files a/mp/src/lib/public/tier3.lib and b/mp/src/lib/public/tier3.lib differ diff --git a/mp/src/lib/public/vgui_controls.lib b/mp/src/lib/public/vgui_controls.lib index ddb284cf..d05d0bcb 100644 Binary files a/mp/src/lib/public/vgui_controls.lib and b/mp/src/lib/public/vgui_controls.lib differ diff --git a/mp/src/lib/public/vmpi.lib b/mp/src/lib/public/vmpi.lib index f2a5682c..b16b57ae 100644 Binary files a/mp/src/lib/public/vmpi.lib and b/mp/src/lib/public/vmpi.lib differ diff --git a/mp/src/lib/public/vstdlib.lib b/mp/src/lib/public/vstdlib.lib index 2b43846f..80035b6a 100644 Binary files a/mp/src/lib/public/vstdlib.lib and b/mp/src/lib/public/vstdlib.lib differ diff --git a/mp/src/lib/public/vtf.lib b/mp/src/lib/public/vtf.lib index d1adfa8a..32a90207 100644 Binary files a/mp/src/lib/public/vtf.lib and b/mp/src/lib/public/vtf.lib differ diff --git a/mp/src/materialsystem/shaderapidx9/locald3dtypes.h b/mp/src/materialsystem/shaderapidx9/locald3dtypes.h new file mode 100644 index 00000000..31854816 --- /dev/null +++ b/mp/src/materialsystem/shaderapidx9/locald3dtypes.h @@ -0,0 +1,191 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef LOCALD3DTYPES_H +#define LOCALD3DTYPES_H + +#ifdef _WIN32 +#pragma once +#endif + +#if defined( DX10 ) && !defined( DX_TO_GL_ABSTRACTION ) + +#include +#include + +struct IDirect3D10BaseTexture +{ + ID3D10Resource *m_pBaseTexture; + ID3D10ShaderResourceView *m_pSRView; + ID3D10RenderTargetView *m_pRTView; +}; + +class CDx10Types +{ +public: + typedef struct IDirect3D10BaseTexture IDirect3DTexture; + // FIXME: What is this called now ? + // typedef ID3D10TextureCube IDirect3DCubeTexture; + typedef ID3D10Texture3D IDirect3DVolumeTexture; + typedef ID3D10Device IDirect3DDevice; + typedef D3D10_VIEWPORT D3DVIEWPORT; + typedef ID3D10Buffer IDirect3DIndexBuffer; + typedef ID3D10Buffer IDirect3DVertexBuffer; + typedef ID3D10VertexShader IDirect3DVertexShader; + typedef ID3D10PixelShader IDirect3DPixelShader; + typedef ID3D10ShaderResourceView IDirect3DSurface; + typedef ID3DX10Font ID3DXFont; + typedef ID3D10Query ID3DQuery; + + typedef ID3D10Device *LPDIRECT3DDEVICE; + typedef ID3D10Buffer *LPDIRECT3DINDEXBUFFER; + typedef ID3D10Buffer *LPDIRECT3DVERTEXBUFFER; +}; + +#endif // defined( DX10 ) && !defined( DX_TO_GL_ABSTRACTION ) + + +#if !defined( _X360 ) && !defined( DX_TO_GL_ABSTRACTION ) +#ifdef _DEBUG +#define D3D_DEBUG_INFO 1 +#endif +#endif + +struct IDirect3DTexture9; +struct IDirect3DBaseTexture9; +struct IDirect3DCubeTexture9; +struct IDirect3D9; +struct IDirect3DDevice9; +struct IDirect3DSurface9; +struct IDirect3DIndexBuffer9; +struct IDirect3DVertexBuffer9; +struct IDirect3DVertexShader9; +struct IDirect3DPixelShader9; +struct IDirect3DVolumeTexture9; + +typedef struct _D3DLIGHT9 D3DLIGHT9; +typedef struct _D3DADAPTER_IDENTIFIER9 D3DADAPTER_IDENTIFIER9; +typedef struct _D3DCAPS9 D3DCAPS9; +typedef struct _D3DVIEWPORT9 D3DVIEWPORT9; +typedef struct _D3DMATERIAL9 D3DMATERIAL9; +typedef IDirect3DTexture9 IDirect3DTexture; +typedef IDirect3DBaseTexture9 IDirect3DBaseTexture; +typedef IDirect3DCubeTexture9 IDirect3DCubeTexture; +typedef IDirect3DVolumeTexture9 IDirect3DVolumeTexture; +typedef IDirect3DDevice9 IDirect3DDevice; +typedef D3DMATERIAL9 D3DMATERIAL; +typedef D3DLIGHT9 D3DLIGHT; +typedef IDirect3DSurface9 IDirect3DSurface; +typedef D3DCAPS9 D3DCAPS; +typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer; +typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer; +typedef IDirect3DPixelShader9 IDirect3DPixelShader; +typedef IDirect3DDevice *LPDIRECT3DDEVICE; +typedef IDirect3DIndexBuffer *LPDIRECT3DINDEXBUFFER; +typedef IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER; + +class CDx9Types +{ +public: + typedef IDirect3DTexture9 IDirect3DTexture; + typedef IDirect3DBaseTexture9 IDirect3DBaseTexture; + typedef IDirect3DCubeTexture9 IDirect3DCubeTexture; + typedef IDirect3DVolumeTexture9 IDirect3DVolumeTexture; + typedef IDirect3DDevice9 IDirect3DDevice; + typedef D3DMATERIAL9 D3DMATERIAL; + typedef D3DLIGHT9 D3DLIGHT; + typedef IDirect3DSurface9 IDirect3DSurface; + typedef D3DCAPS9 D3DCAPS; + typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer; + typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer; + typedef IDirect3DPixelShader9 IDirect3DPixelShader; + typedef IDirect3DDevice *LPDIRECT3DDEVICE; + typedef IDirect3DIndexBuffer *LPDIRECT3DINDEXBUFFER; + typedef IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER; +}; + +typedef void *HardwareShader_t; + +//----------------------------------------------------------------------------- +// The vertex and pixel shader type +//----------------------------------------------------------------------------- +typedef int VertexShader_t; +typedef int PixelShader_t; + +//----------------------------------------------------------------------------- +// Bitpattern for an invalid shader +//----------------------------------------------------------------------------- +#define INVALID_SHADER ( 0xFFFFFFFF ) +#define INVALID_HARDWARE_SHADER ( NULL ) + +#define D3DSAMP_NOTSUPPORTED D3DSAMP_FORCE_DWORD +#define D3DRS_NOTSUPPORTED D3DRS_FORCE_DWORD + +#include "togl/rendermechanism.h" + +#if defined( _X360 ) + +// not supported, keeping for port ease +#define D3DSAMP_SRGBTEXTURE D3DSAMP_NOTSUPPORTED +#define D3DRS_LIGHTING D3DRS_NOTSUPPORTED +#define D3DRS_DIFFUSEMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_SPECULARENABLE D3DRS_NOTSUPPORTED +#define D3DRS_SHADEMODE D3DRS_NOTSUPPORTED +#define D3DRS_LASTPIXEL D3DRS_NOTSUPPORTED +#define D3DRS_DITHERENABLE D3DRS_NOTSUPPORTED +#define D3DRS_FOGENABLE D3DRS_NOTSUPPORTED +#define D3DRS_FOGCOLOR D3DRS_NOTSUPPORTED +#define D3DRS_FOGTABLEMODE D3DRS_NOTSUPPORTED +#define D3DRS_FOGSTART D3DRS_NOTSUPPORTED +#define D3DRS_FOGEND D3DRS_NOTSUPPORTED +#define D3DRS_FOGDENSITY D3DRS_NOTSUPPORTED +#define D3DRS_RANGEFOGENABLE D3DRS_NOTSUPPORTED +#define D3DRS_TEXTUREFACTOR D3DRS_NOTSUPPORTED +#define D3DRS_CLIPPING D3DRS_NOTSUPPORTED +#define D3DRS_AMBIENT D3DRS_NOTSUPPORTED +#define D3DRS_FOGVERTEXMODE D3DRS_NOTSUPPORTED +#define D3DRS_COLORVERTEX D3DRS_NOTSUPPORTED +#define D3DRS_LOCALVIEWER D3DRS_NOTSUPPORTED +#define D3DRS_NORMALIZENORMALS D3DRS_NOTSUPPORTED +#define D3DRS_SPECULARMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_AMBIENTMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_EMISSIVEMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_VERTEXBLEND D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALEENABLE D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_A D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_B D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_C D3DRS_NOTSUPPORTED +#define D3DRS_PATCHEDGESTYLE D3DRS_NOTSUPPORTED +#define D3DRS_DEBUGMONITORTOKEN D3DRS_NOTSUPPORTED +#define D3DRS_INDEXEDVERTEXBLENDENABLE D3DRS_NOTSUPPORTED +#define D3DRS_TWEENFACTOR D3DRS_NOTSUPPORTED +#define D3DRS_POSITIONDEGREE D3DRS_NOTSUPPORTED +#define D3DRS_NORMALDEGREE D3DRS_NOTSUPPORTED +#define D3DRS_ANTIALIASEDLINEENABLE D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_X D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_Y D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_Z D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_W D3DRS_NOTSUPPORTED +#define D3DRS_ENABLEADAPTIVETESSELLATION D3DRS_NOTSUPPORTED +#define D3DRS_SRGBWRITEENABLE D3DRS_NOTSUPPORTED +#define D3DLOCK_DISCARD 0 +#define D3DUSAGE_DYNAMIC 0 +#define D3DUSAGE_AUTOGENMIPMAP 0 +#define D3DDEVTYPE_REF D3DDEVTYPE_HAL +#define D3DENUM_WHQL_LEVEL 0 +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING D3DCREATE_HARDWARE_VERTEXPROCESSING +#define D3DDMT_ENABLE 0 + +typedef enum D3DSHADEMODE +{ + D3DSHADE_FLAT = 0, + D3DSHADE_GOURAUD = 0, +}; + +#endif // _X360 + +#endif // LOCALD3DTYPES_H diff --git a/mp/src/materialsystem/stdshaders/BaseVSShader.cpp b/mp/src/materialsystem/stdshaders/BaseVSShader.cpp new file mode 100644 index 00000000..ba1f6e15 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BaseVSShader.cpp @@ -0,0 +1,2234 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// This is what all vs/ps (dx8+) shaders inherit from. +//===========================================================================// +#if !defined(_STATIC_LINKED) || defined(STDSHADER_DX8_DLL_EXPORT) || defined(STDSHADER_DX9_DLL_EXPORT) + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "mathlib/bumpvects.h" +#include "cpp_shader_constant_register_map.h" +#include "convar.h" + +#ifndef GAME_SHADER_DLL +#ifdef HDR +#include "vertexlit_and_unlit_generic_hdr_ps20.inc" +#include "vertexlit_and_unlit_generic_hdr_ps20b.inc" +#endif + +#if SUPPORT_DX8 +#include "lightmappedgeneric_flashlight_vs11.inc" +#include "flashlight_ps11.inc" +#endif + +#ifdef STDSHADER_DX9_DLL_EXPORT +#include "lightmappedgeneric_flashlight_vs20.inc" +#endif +#ifdef STDSHADER_DX9_DLL_EXPORT +#include "flashlight_ps20.inc" +#include "flashlight_ps20b.inc" +#endif +#include "unlitgeneric_vs11.inc" +#include "VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14.inc" +#include "VertexLitGeneric_EnvmappedBumpmap_NoLighting.inc" +#include "vertexlitgeneric_flashlight_vs11.inc" +#include "LightmappedGeneric_BaseTexture.inc" +#include "LightmappedGeneric_BumpmappedLightmap_Base_ps14.inc" +#include "LightmappedGeneric_BumpmappedLightmap_Blend_ps14.inc" +#include "lightmappedgeneric_bumpmappedenvmap_ps14.inc" +#include "lightmappedgeneric_bumpmappedenvmap.inc" +#include "lightmappedgeneric_basetextureblend.inc" +#include "lightmappedgeneric_bumpmappedlightmap.inc" +#endif // GAME_SHADER_DLL + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +// These functions are to be called from the shaders. + +//----------------------------------------------------------------------------- +// Pixel and vertex shader constants.... +//----------------------------------------------------------------------------- +void CBaseVSShader::SetPixelShaderConstant( int pixelReg, int constantVar, int constantVar2 ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1) || (constantVar2 == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + IMaterialVar* pPixelVar2 = s_ppParams[constantVar2]; + Assert( pPixelVar2 ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 3 ); + } + else + { + val[0] = val[1] = val[2] = pPixelVar->GetFloatValue(); + } + + val[3] = pPixelVar2->GetFloatValue(); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar, int constantVar2 ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1) || (constantVar2 == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + IMaterialVar* pPixelVar2 = s_ppParams[constantVar2]; + Assert( pPixelVar2 ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 3 ); + } + else + { + val[0] = val[1] = val[2] = pPixelVar->GetFloatValue(); + } + + val[3] = pPixelVar2->GetFloatValue(); + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + val[3]=fWValue; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstant( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetVertexShaderConstantGammaToLinear( int var, float const* pVec, int numConst, bool bForce ) +{ + int i; + for( i = 0; i < numConst; i++ ) + { + float vec[4]; + vec[0] = pVec[i*4+0] > 1.0f ? pVec[i*4+0] : GammaToLinear( pVec[i*4+0] ); + vec[1] = pVec[i*4+1] > 1.0f ? pVec[i*4+1] : GammaToLinear( pVec[i*4+1] ); + vec[2] = pVec[i*4+2] > 1.0f ? pVec[i*4+2] : GammaToLinear( pVec[i*4+2] ); + vec[3] = pVec[i*4+3]; + + s_pShaderAPI->SetVertexShaderConstant( var + i, vec, 1, bForce ); + } +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int var, float const* pVec, int numConst, bool bForce ) +{ + int i; + for( i = 0; i < numConst; i++ ) + { + float vec[4]; + vec[0] = pVec[i*4+0] > 1.0f ? pVec[i*4+0] : GammaToLinear( pVec[i*4+0] ); + vec[1] = pVec[i*4+1] > 1.0f ? pVec[i*4+1] : GammaToLinear( pVec[i*4+1] ); + vec[2] = pVec[i*4+2] > 1.0f ? pVec[i*4+2] : GammaToLinear( pVec[i*4+2] ); + + vec[3] = pVec[i*4+3]; + + s_pShaderAPI->SetPixelShaderConstant( var + i, vec, 1, bForce ); + } +} + +// GR - special version with fix for const/lerp issue +void CBaseVSShader::SetPixelShaderConstantFudge( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 4 ); + val[0] = val[0] * 0.992f + 0.0078f; + val[1] = val[1] * 0.992f + 0.0078f; + val[2] = val[2] * 0.992f + 0.0078f; + val[3] = val[3] * 0.992f + 0.0078f; + } + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue() * 0.992f + 0.0078f; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetVertexShaderConstant( int vertexReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pVertexVar = s_ppParams[constantVar]; + Assert( pVertexVar ); + + float val[4]; + if (pVertexVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pVertexVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pVertexVar->GetFloatValue(); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, val ); +} + +//----------------------------------------------------------------------------- +// Sets normalized light color for pixel shaders. +//----------------------------------------------------------------------------- +void CBaseVSShader::SetPixelShaderLightColors( int pixelReg ) +{ + int i; + int maxLights = s_pShaderAPI->GetMaxLights(); + for( i = 0; i < maxLights; i++ ) + { + const LightDesc_t & lightDesc = s_pShaderAPI->GetLight( i ); + if( lightDesc.m_Type != MATERIAL_LIGHT_DISABLE ) + { + Vector color( lightDesc.m_Color[0], lightDesc.m_Color[1], lightDesc.m_Color[2] ); + VectorNormalize( color ); + float val[4] = { color[0], color[1], color[2], 1.0f }; + s_pShaderAPI->SetPixelShaderConstant( pixelReg + i, val, 1 ); + } + else + { + float zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + s_pShaderAPI->SetPixelShaderConstant( pixelReg + i, zero, 1 ); + } + } +} + + +//----------------------------------------------------------------------------- +// Sets vertex shader texture transforms +//----------------------------------------------------------------------------- +void CBaseVSShader::SetVertexShaderTextureTranslation( int vertexReg, int translationVar ) +{ + float offset[2] = {0, 0}; + + IMaterialVar* pTranslationVar = s_ppParams[translationVar]; + if (pTranslationVar) + { + if (pTranslationVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pTranslationVar->GetVecValue( offset, 2 ); + else + offset[0] = offset[1] = pTranslationVar->GetFloatValue(); + } + + Vector4D translation[2]; + translation[0].Init( 1.0f, 0.0f, 0.0f, offset[0] ); + translation[1].Init( 0.0f, 1.0f, 0.0f, offset[1] ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, translation[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureScale( int vertexReg, int scaleVar ) +{ + float scale[2] = {1, 1}; + + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale, 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + Vector4D scaleMatrix[2]; + scaleMatrix[0].Init( scale[0], 0.0f, 0.0f, 0.0f ); + scaleMatrix[1].Init( 0.0f, scale[1], 0.0f, 0.0f ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, scaleMatrix[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureTransform( int vertexReg, int transformVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureScaledTransform( int vertexReg, int transformVar, int scaleVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); +} + + +//----------------------------------------------------------------------------- +// Sets pixel shader texture transforms +//----------------------------------------------------------------------------- +void CBaseVSShader::SetPixelShaderTextureTranslation( int pixelReg, int translationVar ) +{ + float offset[2] = {0, 0}; + + IMaterialVar* pTranslationVar = s_ppParams[translationVar]; + if (pTranslationVar) + { + if (pTranslationVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pTranslationVar->GetVecValue( offset, 2 ); + else + offset[0] = offset[1] = pTranslationVar->GetFloatValue(); + } + + Vector4D translation[2]; + translation[0].Init( 1.0f, 0.0f, 0.0f, offset[0] ); + translation[1].Init( 0.0f, 1.0f, 0.0f, offset[1] ); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, translation[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureScale( int pixelReg, int scaleVar ) +{ + float scale[2] = {1, 1}; + + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale, 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + Vector4D scaleMatrix[2]; + scaleMatrix[0].Init( scale[0], 0.0f, 0.0f, 0.0f ); + scaleMatrix[1].Init( 0.0f, scale[1], 0.0f, 0.0f ); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, scaleMatrix[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureTransform( int pixelReg, int transformVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, transformation[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureScaledTransform( int pixelReg, int transformVar, int scaleVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, transformation[0].Base(), 2 ); +} + + +//----------------------------------------------------------------------------- +// Moves a matrix into vertex shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::SetVertexShaderMatrix3x4( int vertexReg, int matrixVar ) +{ + IMaterialVar* pTranslationVar = s_ppParams[matrixVar]; + if (pTranslationVar) + { + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &pTranslationVar->GetMatrixValue( )[0][0], 3 ); + } + else + { + VMatrix matrix; + MatrixSetIdentity( matrix ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &matrix[0][0], 3 ); + } +} + +void CBaseVSShader::SetVertexShaderMatrix4x4( int vertexReg, int matrixVar ) +{ + IMaterialVar* pTranslationVar = s_ppParams[matrixVar]; + if (pTranslationVar) + { + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &pTranslationVar->GetMatrixValue( )[0][0], 4 ); + } + else + { + VMatrix matrix; + MatrixSetIdentity( matrix ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &matrix[0][0], 4 ); + } +} + + +//----------------------------------------------------------------------------- +// Loads the view matrix into pixel shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadViewMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix mat, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_VIEW, mat.m[0] ); + + MatrixTranspose( mat, transpose ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transpose.m[0], 3 ); +} + + +//----------------------------------------------------------------------------- +// Loads the projection matrix into pixel shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadProjectionMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix mat, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_PROJECTION, mat.m[0] ); + + MatrixTranspose( mat, transpose ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transpose.m[0], 4 ); +} + + +//----------------------------------------------------------------------------- +// Loads the projection matrix into pixel shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadModelViewMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix view, model, modelView, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_MODEL, model.m[0] ); + MatrixTranspose( model, model ); + s_pShaderAPI->GetMatrix( MATERIAL_VIEW, view.m[0] ); + MatrixTranspose( view, view ); + + MatrixMultiply( view, model, modelView ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, modelView.m[0], 3 ); +} + +//----------------------------------------------------------------------------- +// Loads a scale/offset version of the viewport transform into the specified constant. +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadViewportTransformScaledIntoVertexShaderConstant( int vertexReg ) +{ + ShaderViewport_t viewport; + + s_pShaderAPI->GetViewports( &viewport, 1 ); + + int bbWidth = 0, + bbHeight = 0; + + s_pShaderAPI->GetBackBufferDimensions( bbWidth, bbHeight ); + + // (x, y, z, w) = (Width / bbWidth, Height / bbHeight, MinX / bbWidth, MinY / bbHeight) + Vector4D viewportTransform( + 1.0f * viewport.m_nWidth / bbWidth, + 1.0f * viewport.m_nHeight / bbHeight, + 1.0f * viewport.m_nTopLeftX / bbWidth, + 1.0f * viewport.m_nTopLeftY / bbHeight + ); + + s_pShaderAPI->SetVertexShaderConstant( vertexReg, viewportTransform.Base() ); +} + + + +//----------------------------------------------------------------------------- +// Loads bump lightmap coordinates into the pixel shader +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadBumpLightmapCoordinateAxes_PixelShader( int pixelReg ) +{ + Vector4D basis[3]; + for (int i = 0; i < 3; ++i) + { + memcpy( &basis[i], &g_localBumpBasis[i], 3 * sizeof(float) ); + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, (float*)basis, 3 ); +} + + +//----------------------------------------------------------------------------- +// Loads bump lightmap coordinates into the pixel shader +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadBumpLightmapCoordinateAxes_VertexShader( int vertexReg ) +{ + Vector4D basis[3]; + + // transpose + int i; + for (i = 0; i < 3; ++i) + { + basis[i][0] = g_localBumpBasis[0][i]; + basis[i][1] = g_localBumpBasis[1][i]; + basis[i][2] = g_localBumpBasis[2][i]; + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg, (float*)basis, 3 ); + for (i = 0; i < 3; ++i) + { + memcpy( &basis[i], &g_localBumpBasis[i], 3 * sizeof(float) ); + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg + 3, (float*)basis, 3 ); +} + + +//----------------------------------------------------------------------------- +// Helper methods for pixel shader overbrighting +//----------------------------------------------------------------------------- +void CBaseVSShader::EnablePixelShaderOverbright( int reg, bool bEnable, bool bDivideByTwo ) +{ + // can't have other overbright values with pixel shaders as it stands. + float v[4]; + if( bEnable ) + { + v[0] = v[1] = v[2] = v[3] = bDivideByTwo ? OVERBRIGHT / 2.0f : OVERBRIGHT; + } + else + { + v[0] = v[1] = v[2] = v[3] = bDivideByTwo ? 1.0f / 2.0f : 1.0f; + } + s_pShaderAPI->SetPixelShaderConstant( reg, v, 1 ); +} + + +//----------------------------------------------------------------------------- +// Helper for dealing with modulation +//----------------------------------------------------------------------------- +void CBaseVSShader::SetModulationVertexShaderDynamicState() +{ + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); +} + +void CBaseVSShader::SetModulationPixelShaderDynamicState( int modulationVar ) +{ + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + s_pShaderAPI->SetPixelShaderConstant( modulationVar, color ); +} + +void CBaseVSShader::SetModulationPixelShaderDynamicState_LinearColorSpace( int modulationVar ) +{ + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + color[0] = color[0] > 1.0f ? color[0] : GammaToLinear( color[0] ); + color[1] = color[1] > 1.0f ? color[1] : GammaToLinear( color[1] ); + color[2] = color[2] > 1.0f ? color[2] : GammaToLinear( color[2] ); + + s_pShaderAPI->SetPixelShaderConstant( modulationVar, color ); +} + +void CBaseVSShader::SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int modulationVar, float flScale ) +{ + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + color[0] = ( color[0] > 1.0f ? color[0] : GammaToLinear( color[0] ) ) * flScale; + color[1] = ( color[1] > 1.0f ? color[1] : GammaToLinear( color[1] ) ) * flScale; + color[2] = ( color[2] > 1.0f ? color[2] : GammaToLinear( color[2] ) ) * flScale; + + s_pShaderAPI->SetPixelShaderConstant( modulationVar, color ); +} + + +//----------------------------------------------------------------------------- +// Converts a color + alpha into a vector4 +//----------------------------------------------------------------------------- +void CBaseVSShader::ColorVarsToVector( int colorVar, int alphaVar, Vector4D &color ) +{ + color.Init( 1.0, 1.0, 1.0, 1.0 ); + if ( colorVar != -1 ) + { + IMaterialVar* pColorVar = s_ppParams[colorVar]; + if ( pColorVar->GetType() == MATERIAL_VAR_TYPE_VECTOR ) + { + pColorVar->GetVecValue( color.Base(), 3 ); + } + else + { + color[0] = color[1] = color[2] = pColorVar->GetFloatValue(); + } + } + if ( alphaVar != -1 ) + { + float flAlpha = s_ppParams[alphaVar]->GetFloatValue(); + color[3] = clamp( flAlpha, 0.0f, 1.0f ); + } +} + + +//----------------------------------------------------------------------------- +// Sets a color + alpha into shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::SetColorVertexShaderConstant( int nVertexReg, int colorVar, int alphaVar ) +{ + Vector4D color; + ColorVarsToVector( colorVar, alphaVar, color ); + s_pShaderAPI->SetVertexShaderConstant( nVertexReg, color.Base() ); +} + +void CBaseVSShader::SetColorPixelShaderConstant( int nPixelReg, int colorVar, int alphaVar ) +{ + Vector4D color; + ColorVarsToVector( colorVar, alphaVar, color ); + s_pShaderAPI->SetPixelShaderConstant( nPixelReg, color.Base() ); +} + +#ifdef _DEBUG +ConVar mat_envmaptintoverride( "mat_envmaptintoverride", "-1" ); +ConVar mat_envmaptintscale( "mat_envmaptintscale", "-1" ); +#endif + +//----------------------------------------------------------------------------- +// Helpers for dealing with envmap tint +//----------------------------------------------------------------------------- +// set alphaVar to -1 to ignore it. +void CBaseVSShader::SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar, int alphaVar, bool bConvertFromGammaToLinear ) +{ + float color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + if( g_pConfig->bShowSpecular && mat_fullbright.GetInt() != 2 ) + { + IMaterialVar* pAlphaVar = NULL; + if( alphaVar >= 0 ) + { + pAlphaVar = s_ppParams[alphaVar]; + } + if( pAlphaVar ) + { + color[3] = pAlphaVar->GetFloatValue(); + } + + IMaterialVar* pTintVar = s_ppParams[tintVar]; +#ifdef _DEBUG + pTintVar->GetVecValue( color, 3 ); + + float envmapTintOverride = mat_envmaptintoverride.GetFloat(); + float envmapTintScaleOverride = mat_envmaptintscale.GetFloat(); + + if( envmapTintOverride != -1.0f ) + { + color[0] = color[1] = color[2] = envmapTintOverride; + } + if( envmapTintScaleOverride != -1.0f ) + { + color[0] *= envmapTintScaleOverride; + color[1] *= envmapTintScaleOverride; + color[2] *= envmapTintScaleOverride; + } + + if( bConvertFromGammaToLinear ) + { + color[0] = color[0] > 1.0f ? color[0] : GammaToLinear( color[0] ); + color[1] = color[1] > 1.0f ? color[1] : GammaToLinear( color[1] ); + color[2] = color[2] > 1.0f ? color[2] : GammaToLinear( color[2] ); + } +#else + if( bConvertFromGammaToLinear ) + { + pTintVar->GetLinearVecValue( color, 3 ); + } + else + { + pTintVar->GetVecValue( color, 3 ); + } +#endif + } + else + { + color[0] = color[1] = color[2] = color[3] = 0.0f; + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, color, 1 ); +} + +void CBaseVSShader::SetAmbientCubeDynamicStateVertexShader( ) +{ + s_pShaderAPI->SetVertexShaderStateAmbientLightCube(); +} + +float CBaseVSShader::GetAmbientLightCubeLuminance( ) +{ + return s_pShaderAPI->GetAmbientLightCubeLuminance(); +} + +#ifndef GAME_SHADER_DLL +const char *CBaseVSShader::UnlitGeneric_ComputePixelShaderName( bool bMask, + bool bEnvmap, + bool bBaseTexture, + bool bBaseAlphaEnvmapMask, + bool bDetail, + bool bDetailMultiplyMode, + bool bMaskBaseByDetailAlpha ) +{ + static char const* s_pPixelShaders[] = + { + "UnlitGeneric_NoTexture", + "UnlitGeneric", + "UnlitGeneric_EnvMapNoTexture", + "UnlitGeneric_EnvMap", + "UnlitGeneric_NoTexture", + "UnlitGeneric", + "UnlitGeneric_EnvMapMaskNoTexture", + "UnlitGeneric_EnvMapMask", + + // Detail texture + // The other commented-out versions are used if we want to + // apply the detail *after* the environment map is added + "UnlitGeneric_DetailNoTexture", + "UnlitGeneric_Detail", + "UnlitGeneric_EnvMapNoTexture", //"UnlitGeneric_DetailEnvMapNoTexture", + "UnlitGeneric_DetailEnvMap", + "UnlitGeneric_DetailNoTexture", + "UnlitGeneric_Detail", + "UnlitGeneric_EnvMapMaskNoTexture", //"UnlitGeneric_DetailEnvMapMaskNoTexture", + "UnlitGeneric_DetailEnvMapMask", + }; + + // handle hud elements + if ( bDetail & bDetailMultiplyMode ) + return "alphadist_ps11"; + + if ( bDetail & bMaskBaseByDetailAlpha ) + return "UnlitGeneric_MaskBaseByDetailAlpha_ps11"; + + if (!bMask && bEnvmap && bBaseTexture && bBaseAlphaEnvmapMask) + { + if (!bDetail) + return "UnlitGeneric_BaseAlphaMaskedEnvMap"; + else + return "UnlitGeneric_DetailBaseAlphaMaskedEnvMap"; + } + else + { + int pshIndex = 0; + if (bBaseTexture) + pshIndex |= 0x1; + if (bEnvmap) + pshIndex |= 0x2; + if (bMask) + pshIndex |= 0x4; + if (bDetail) + pshIndex |= 0x8; + return s_pPixelShaders[pshIndex]; + } +} + + +//----------------------------------------------------------------------------- +// Sets up hw morphing state for the vertex shader +//----------------------------------------------------------------------------- +void CBaseVSShader::SetHWMorphVertexShaderState( int nDimConst, int nSubrectConst, VertexTextureSampler_t morphSampler ) +{ +#ifndef _X360 + if ( !s_pShaderAPI->IsHWMorphingEnabled() ) + return; + + int nMorphWidth, nMorphHeight; + s_pShaderAPI->GetStandardTextureDimensions( &nMorphWidth, &nMorphHeight, TEXTURE_MORPH_ACCUMULATOR ); + + int nDim = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_4TUPLE_COUNT ); + float pMorphAccumSize[4] = { nMorphWidth, nMorphHeight, nDim, 0.0f }; + s_pShaderAPI->SetVertexShaderConstant( nDimConst, pMorphAccumSize ); + + int nXOffset = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_X_OFFSET ); + int nYOffset = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_Y_OFFSET ); + int nWidth = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_SUBRECT_WIDTH ); + int nHeight = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_SUBRECT_HEIGHT ); + float pMorphAccumSubrect[4] = { nXOffset, nYOffset, nWidth, nHeight }; + s_pShaderAPI->SetVertexShaderConstant( nSubrectConst, pMorphAccumSubrect ); + + s_pShaderAPI->BindStandardVertexTexture( morphSampler, TEXTURE_MORPH_ACCUMULATOR ); +#endif +} + + +//----------------------------------------------------------------------------- +// Vertex shader unlit generic pass +//----------------------------------------------------------------------------- +void CBaseVSShader::VertexShaderUnlitGenericPass( int baseTextureVar, int frameVar, + int baseTextureTransformVar, + int detailVar, int detailTransform, + bool bDetailTransformIsScale, + int envmapVar, int envMapFrameVar, + int envmapMaskVar, int envmapMaskFrameVar, + int envmapMaskScaleVar, int envmapTintVar, + int alphaTestReferenceVar, + int nDetailBlendModeVar, + int nOutlineVar, + int nOutlineColorVar, + int nOutlineStartVar, + int nOutlineEndVar, + int nSeparateDetailUVsVar ) +{ + IMaterialVar** params = s_ppParams; + + bool bBaseAlphaEnvmapMask = IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK); + bool bEnvmap = (envmapVar >= 0) && params[envmapVar]->IsTexture(); + bool bMask = false; + if (bEnvmap && (envmapMaskVar >= 0)) + { + bMask = params[envmapMaskVar]->IsTexture(); + } + bool bDetail = (detailVar >= 0) && params[detailVar]->IsTexture(); + bool bBaseTexture = (baseTextureVar >= 0) && params[baseTextureVar]->IsTexture(); + bool bVertexColor = IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR); + bool bEnvmapCameraSpace = IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE); + bool bEnvmapSphere = IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE); + + bool bDetailMultiply = ( nDetailBlendModeVar >= 0 ) && ( params[nDetailBlendModeVar]->GetIntValue() == 8 ); + bool bMaskBaseByDetailAlpha = ( nDetailBlendModeVar >= 0 ) && ( params[nDetailBlendModeVar]->GetIntValue() == 9 ); + bool bSeparateDetailUVs = ( nSeparateDetailUVsVar >= 0 ) && ( params[nSeparateDetailUVsVar]->GetIntValue() != 0 ); + + if (IsSnapshotting()) + { + // Alpha test + s_pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + if( alphaTestReferenceVar != -1 && params[alphaTestReferenceVar]->GetFloatValue() > 0.0f ) + { + s_pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[alphaTestReferenceVar]->GetFloatValue() ); + } + + // Base texture on stage 0 + if (bBaseTexture) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + } + + if (bDetail) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + + if (bEnvmap) + { + // envmap on stage 1 + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // envmapmask on stage 2 + if (bMask || bBaseAlphaEnvmapMask ) + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + if (bBaseTexture) + SetDefaultBlendingShadowState( baseTextureVar, true ); + else if (bMask) + SetDefaultBlendingShadowState( envmapMaskVar, false ); + else + SetDefaultBlendingShadowState(); + + int fmt = VERTEX_POSITION; + if( bEnvmap ) + fmt |= VERTEX_NORMAL; + if ( bVertexColor ) + fmt |= VERTEX_COLOR; + + int numTexCoords = 1; + if( bSeparateDetailUVs ) + { + numTexCoords = 2; + } + + s_pShaderShadow->VertexShaderVertexFormat( fmt, numTexCoords, 0, 0 ); + const char *pshName = UnlitGeneric_ComputePixelShaderName( + bMask, + bEnvmap, + bBaseTexture, + bBaseAlphaEnvmapMask, + bDetail, + bDetailMultiply, + bMaskBaseByDetailAlpha ); + s_pShaderShadow->SetPixelShader( pshName ); + + // Compute the vertex shader index. + unlitgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( bDetail ); + vshIndex.SetENVMAP( bEnvmap ); + vshIndex.SetENVMAPCAMERASPACE( bEnvmap && bEnvmapCameraSpace ); + vshIndex.SetENVMAPSPHERE( bEnvmap && bEnvmapSphere ); + vshIndex.SetVERTEXCOLOR( bVertexColor ); + vshIndex.SetSEPARATEDETAILUVS( bSeparateDetailUVs ); + s_pShaderShadow->SetVertexShader( "unlitgeneric_vs11", vshIndex.GetIndex() ); + + DefaultFog(); + } + else + { + if ( s_pShaderAPI->InFlashlightMode() ) // Not snapshotting && flashlight pass + { + Draw( false ); + return; + } + + if (bBaseTexture) + { + BindTexture( SHADER_SAMPLER0, baseTextureVar, frameVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, baseTextureTransformVar ); + } + + if (bDetail) + { + BindTexture( SHADER_SAMPLER3, detailVar, frameVar ); + + if (bDetailTransformIsScale) + { + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, baseTextureTransformVar, detailTransform ); + } + else + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, detailTransform ); + } + } + + if (bEnvmap) + { + BindTexture( SHADER_SAMPLER1, envmapVar, envMapFrameVar ); + + if (bMask || bBaseAlphaEnvmapMask) + { + if (bMask) + BindTexture( SHADER_SAMPLER2, envmapMaskVar, envmapMaskFrameVar ); + else + BindTexture( SHADER_SAMPLER2, baseTextureVar, frameVar ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, baseTextureTransformVar, envmapMaskScaleVar ); + } + + SetEnvMapTintPixelShaderDynamicState( 2, envmapTintVar, -1 ); + + if (bEnvmapSphere || IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + } + + SetModulationVertexShaderDynamicState(); + + float flConsts[12]={ 0, 0, 0, 1, // color + 0, 0, 0, 0, // max + 0, 0, 0, .5, // min + }; + + // set up outline pixel shader constants + if ( bDetailMultiply && ( nOutlineVar != -1 ) && ( params[nOutlineVar]->GetIntValue() ) ) + { + if ( nOutlineColorVar != -1 ) + params[nOutlineColorVar]->GetVecValue( flConsts, 3 ); + if ( nOutlineEndVar != -1 ) + flConsts[7] = params[nOutlineEndVar]->GetFloatValue(); + if ( nOutlineStartVar != -1 ) + flConsts[11] = params[nOutlineStartVar]->GetFloatValue(); + } + + s_pShaderAPI->SetPixelShaderConstant( 0, flConsts, 3 ); + + // Compute the vertex shader index. + unlitgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( s_pShaderAPI->GetCurrentNumBones() > 0 ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + Draw(); +} + + +void CBaseVSShader::DrawWorldBaseTexture( int baseTextureVar, int baseTextureTransformVar, + int frameVar, int colorVar, int alphaVar ) +{ + if( IsSnapshotting() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION, 1, 0, 0 ); + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BaseTexture" ); + SetNormalBlendingShadowState(); + lightmappedgeneric_basetexture_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BaseTexture", vshIndex.GetIndex() ); + + FogToOOOverbright(); + } + else + { + IMaterialVar** params = s_ppParams; + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, baseTextureVar, frameVar ); + } + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, baseTextureTransformVar ); + SetColorPixelShaderConstant( 0, colorVar, alphaVar ); + lightmappedgeneric_basetexture_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +void CBaseVSShader::DrawWorldBumpedDiffuseLighting( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, bool bMultiply, + bool bSSBump ) +{ + if( IsSnapshotting() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( bMultiply ) + { + s_pShaderShadow->EnableBlending( true ); + SingleTextureLightmapBlendMode(); + } + s_pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, 0, 0 ); + + lightmappedgeneric_bumpmappedlightmap_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedLightmap", vshIndex.GetIndex() ); + + if ( bSSBump ) + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_SSBumpmappedLightmap" ); + else + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedLightmap" ); + FogToFogColor(); + } + else + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER0, bumpmapVar, bumpFrameVar ); + } + else + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + LoadBumpLightmapCoordinateAxes_PixelShader( 0 ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, bumpTransformVar ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_bumpmappedlightmap_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +void CBaseVSShader::DrawWorldBumpedDiffuseLighting_Base_ps14( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, + int baseTextureVar, int baseTextureTransformVar, int frameVar ) +{ + if( IsSnapshotting() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + s_pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, 0, 0 ); + + lightmappedgeneric_bumpmappedlightmap_base_ps14_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedLightmap_Base_ps14", vshIndex.GetIndex() ); + + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedLightmap_Base_ps14" ); + FogToFogColor(); + } + else + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER0, bumpmapVar, bumpFrameVar ); + } + else + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + LoadBumpLightmapCoordinateAxes_PixelShader( 0 ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + BindTexture( SHADER_SAMPLER4, baseTextureVar, frameVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, bumpTransformVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, baseTextureTransformVar ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_bumpmappedlightmap_base_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +void CBaseVSShader::DrawWorldBumpedDiffuseLighting_Blend_ps14( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, + int baseTextureVar, int baseTextureTransformVar, + int baseTextureFrameVar, + int baseTexture2Var, int baseTextureTransform2Var, + int baseTextureFrame2Var) +{ + if( IsSnapshotting() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + s_pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, 0, 0 ); + + lightmappedgeneric_bumpmappedlightmap_blend_ps14_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedLightmap_Blend_ps14", vshIndex.GetIndex() ); + + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedLightmap_Blend_ps14" ); + FogToFogColor(); + } + else + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER0, bumpmapVar, bumpFrameVar ); + } + else + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + LoadBumpLightmapCoordinateAxes_PixelShader( 0 ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + BindTexture( SHADER_SAMPLER4, baseTextureVar, baseTextureFrameVar ); + BindTexture( SHADER_SAMPLER5, baseTexture2Var, baseTextureFrame2Var ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, bumpTransformVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, baseTextureTransformVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, baseTextureTransform2Var ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_bumpmappedlightmap_blend_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +//#define USE_DEST_ALPHA +#define USE_NORMALMAP_ALPHA + +void CBaseVSShader::DrawWorldBumpedSpecularLighting( int bumpmapVar, int envmapVar, + int bumpFrameVar, int envmapFrameVar, + int envmapTintVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, + int bumpTransformVar, int fresnelReflectionVar, + bool bBlend, bool bNoWriteZ ) +{ + // + BUMPED CUBEMAP + if( IsSnapshotting() ) + { + SetInitialShadowState( ); + if ( bNoWriteZ ) + { + s_pShaderShadow->EnableDepthWrites( false ); + } + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + if( bBlend ) + { + s_pShaderShadow->EnableBlending( true ); + s_pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + // FIXME: Remove the normal (needed for tangent space gen) + s_pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | + VERTEX_TANGENT_T, 1, 0, 0 ); + + IMaterialVar** params = s_ppParams; + bool bHasNormalMapAlphaEnvMapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + lightmappedgeneric_bumpmappedenvmap_ps14_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedEnvmap_ps14", vshIndex.GetIndex() ); + + int nPshIndex = bHasNormalMapAlphaEnvMapMask ? 1 : 0; + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedEnvmap_ps14", nPshIndex ); + } + else + { + lightmappedgeneric_bumpmappedenvmap_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedEnvmap", vshIndex.GetIndex() ); + + int nPshIndex = bHasNormalMapAlphaEnvMapMask ? 1 : 0; + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedEnvmap", nPshIndex ); + } + FogToBlack(); + } + else + { + IMaterialVar** params = s_ppParams; + s_pShaderAPI->SetDefaultState(); + BindTexture( SHADER_SAMPLER0, bumpmapVar, bumpFrameVar ); + BindTexture( SHADER_SAMPLER3, envmapVar, envmapFrameVar ); + + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALIZATION_CUBEMAP ); + + lightmappedgeneric_bumpmappedenvmap_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + lightmappedgeneric_bumpmappedenvmap_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + SetEnvMapTintPixelShaderDynamicState( 0, envmapTintVar, alphaVar ); + // GR - fudge consts a bit to fix const/lerp issues + SetPixelShaderConstantFudge( 1, envmapContrastVar ); + SetPixelShaderConstantFudge( 2, envmapSaturationVar ); + float greyWeights[4] = { 0.299f, 0.587f, 0.114f, 0.0f }; + s_pShaderAPI->SetPixelShaderConstant( 3, greyWeights ); + + // [ 0, 0 ,0, R(0) ] + float fresnel[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + fresnel[3] = params[fresnelReflectionVar]->GetFloatValue(); + s_pShaderAPI->SetPixelShaderConstant( 4, fresnel ); + // [ 0, 0 ,0, 1-R(0) ] + fresnel[3] = 1.0f - fresnel[3]; + s_pShaderAPI->SetPixelShaderConstant( 6, fresnel ); + + float one[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + s_pShaderAPI->SetPixelShaderConstant( 5, one ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, bumpTransformVar ); + } + Draw(); +} + +void CBaseVSShader::DrawModelBumpedSpecularLighting( int bumpMapVar, int bumpMapFrameVar, + int envMapVar, int envMapVarFrame, + int envMapTintVar, int alphaVar, + int envMapContrastVar, int envMapSaturationVar, + int bumpTransformVar, + bool bBlendSpecular, bool bNoWriteZ ) +{ + IMaterialVar** params = s_ppParams; + + if( IsSnapshotting() ) + { + SetInitialShadowState( ); + if ( bNoWriteZ ) + { + s_pShaderShadow->EnableDepthWrites( false ); + } + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + s_pShaderShadow->EnableAlphaTest( false ); + if( bBlendSpecular ) + { + s_pShaderShadow->EnableBlending( true ); + SetAdditiveBlendingShadowState( -1, false ); + } + else + { + s_pShaderShadow->EnableBlending( false ); + SetNormalBlendingShadowState( -1, false ); + } + + s_pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL, 1, 0, 4 /* userDataSize */ ); + + bool bHasNormalMapAlphaEnvMapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + vertexlitgeneric_envmappedbumpmap_nolighting_ps14_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14", vshIndex.GetIndex() ); + if( bHasNormalMapAlphaEnvMapMask ) + { + s_pShaderShadow->SetPixelShader( "VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha_ps14" ); + } + else + { + s_pShaderShadow->SetPixelShader( "VertexLitGeneric_EnvmappedBumpmapV2_ps14" ); + } + } + else + { + vertexlitgeneric_envmappedbumpmap_nolighting_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "VertexLitGeneric_EnvmappedBumpmap_NoLighting", vshIndex.GetIndex() ); + // This version does not multiply by lighting + // NOTE: We don't support multiplying by lighting for bumped specular stuff. + if( bHasNormalMapAlphaEnvMapMask ) + { + s_pShaderShadow->SetPixelShader( "VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha" ); + } + else + { + s_pShaderShadow->SetPixelShader( "VertexLitGeneric_EnvmappedBumpmapV2" ); + } + } + FogToBlack(); + } + else + { + s_pShaderAPI->SetDefaultState(); + BindTexture( SHADER_SAMPLER0, bumpMapVar, bumpMapFrameVar ); + BindTexture( SHADER_SAMPLER3, envMapVar, envMapVarFrame ); + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALIZATION_CUBEMAP ); + } + + if( bBlendSpecular ) + { + SetEnvMapTintPixelShaderDynamicState( 0, envMapTintVar, -1 ); + } + else + { + SetEnvMapTintPixelShaderDynamicState( 0, envMapTintVar, alphaVar ); + } + // GR - fudge consts a bit to fix const/lerp issues + SetPixelShaderConstantFudge( 1, envMapContrastVar ); + SetPixelShaderConstantFudge( 2, envMapSaturationVar ); + float greyWeights[4] = { 0.299f, 0.587f, 0.114f, 0.0f }; + s_pShaderAPI->SetPixelShaderConstant( 3, greyWeights ); + + // handle scrolling of bump texture + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, bumpTransformVar ); + + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + vertexlitgeneric_envmappedbumpmap_nolighting_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( s_pShaderAPI->GetCurrentNumBones() > 0 ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + vertexlitgeneric_envmappedbumpmap_nolighting_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( s_pShaderAPI->GetCurrentNumBones() > 0 ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + Draw(); +} + +void CBaseVSShader::DrawBaseTextureBlend( int baseTextureVar, int baseTextureTransformVar, + int baseTextureFrameVar, + int baseTexture2Var, int baseTextureTransform2Var, + int baseTextureFrame2Var, int colorVar, int alphaVar ) +{ + if( IsSnapshotting() ) + { + SetInitialShadowState(); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + s_pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | + SHADER_DRAW_LIGHTMAP_TEXCOORD1 ); + // FIXME: Remove the normal (needed for tangent space gen) + s_pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION, 2, 0, 0 ); + + lightmappedgeneric_basetextureblend_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "lightmappedgeneric_basetextureblend", vshIndex.GetIndex() ); + + s_pShaderShadow->SetPixelShader( "lightmappedgeneric_basetextureblend", 0 ); + FogToOOOverbright(); + } + else + { + IMaterialVar** params = s_ppParams; + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + + s_pShaderAPI->SetDefaultState(); + if( bLightingOnly ) + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, baseTextureVar, baseTextureFrameVar ); + BindTexture( SHADER_SAMPLER1, baseTexture2Var, baseTextureFrame2Var ); + } + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_LIGHTMAP ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, baseTextureTransformVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, baseTextureTransform2Var ); + SetColorPixelShaderConstant( 0, colorVar, alphaVar ); + lightmappedgeneric_basetextureblend_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +void CBaseVSShader::DrawWorldBumpedUsingVertexShader( int baseTextureVar, int baseTextureTransformVar, + int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, + int envmapMaskVar, int envmapMaskFrame, + int envmapVar, + int envmapFrameVar, + int envmapTintVar, int colorVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, + int frameVar, int fresnelReflectionVar, + bool doBaseTexture2, + int baseTexture2Var, int baseTextureTransform2Var, + int baseTextureFrame2Var, + bool bSSBump + ) +{ + IMaterialVar** params = s_ppParams; + // Draw base texture + bool bMultiplyDiffuseLighting = false; + bool bBlendSpecular = false; + + // Draw base texture(s) + if( doBaseTexture2 && params[baseTexture2Var]->IsTexture() && params[baseTextureVar]->IsTexture() ) + { + DrawBaseTextureBlend( baseTextureVar, baseTextureTransformVar, frameVar, + baseTexture2Var, baseTextureTransform2Var, baseTextureFrame2Var, colorVar, alphaVar ); + bMultiplyDiffuseLighting = true; + bBlendSpecular = true; + } + else if( params[baseTextureVar]->IsTexture() ) + { + DrawWorldBaseTexture( baseTextureVar, baseTextureTransformVar, frameVar, colorVar, alphaVar ); + bMultiplyDiffuseLighting = true; + bBlendSpecular = true; + } + else + { + // Just use color here + } + + // Draw diffuse lighting + if( params[baseTextureVar]->IsTexture() || !params[envmapVar]->IsTexture() ) + { + DrawWorldBumpedDiffuseLighting( bumpmapVar, bumpFrameVar, bumpTransformVar, + bMultiplyDiffuseLighting, bSSBump ); + bBlendSpecular = true; + } + + // Add specular lighting + if( params[envmapVar]->IsTexture() ) + { + DrawWorldBumpedSpecularLighting( + bumpmapVar, envmapVar, + bumpFrameVar, envmapFrameVar, + envmapTintVar, alphaVar, + envmapContrastVar, envmapSaturationVar, + bumpTransformVar, fresnelReflectionVar, + bBlendSpecular ); + } +} +#endif // GAME_SHADER_DLL + + +//----------------------------------------------------------------------------- +// GR - translucency query +//----------------------------------------------------------------------------- +BlendType_t CBaseVSShader::EvaluateBlendRequirements( int textureVar, bool isBaseTexture, + int detailTextureVar ) +{ + // Either we've got a constant modulation + bool isTranslucent = IsAlphaModulating(); + + // Or we've got a vertex alpha + isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA); + + // Or we've got a texture alpha (for blending or alpha test) + isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) && + !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) ); + + if ( ( detailTextureVar != -1 ) && ( ! isTranslucent ) ) + { + isTranslucent = TextureIsTranslucent( detailTextureVar, isBaseTexture ); + } + + if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE ) + { + return isTranslucent ? BT_BLENDADD : BT_ADD; // Additive + } + else + { + return isTranslucent ? BT_BLEND : BT_NONE; // Normal blending + } +} + +#ifndef GAME_SHADER_DLL + +void CBaseVSShader::SetFlashlightVertexShaderConstants( bool bBump, int bumpTransformVar, bool bDetail, int detailScaleVar, bool bSetTextureTransforms ) +{ + Assert( !IsSnapshotting() ); + + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = s_pShaderAPI->GetFlashlightState( worldToTexture ); + + // Set the flashlight origin + float pos[4]; + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = 1.0f / ( ( 0.6f * flashlightState.m_FarZ ) - flashlightState.m_FarZ ); // DX8 needs this + + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, pos, 1 ); + + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, worldToTexture.Base(), 4 ); + + // Set the flashlight attenuation factors + float atten[4]; + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, atten, 1 ); + + if ( bDetail ) + { + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, BASETEXTURETRANSFORM, detailScaleVar ); + } + + if( bSetTextureTransforms ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, BASETEXTURETRANSFORM ); + if( !bDetail && bBump && bumpTransformVar != -1 ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, bumpTransformVar ); // aliased on top of detail transform + } + } +} + +#if SUPPORT_DX8 +void CBaseVSShader::DrawFlashlight_dx80( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBump, + int bumpmapVar, int bumpmapFrame, int bumpTransform, int flashlightTextureVar, int flashlightTextureFrameVar, + bool bLightmappedGeneric, bool bWorldVertexTransition, int nWorldVertexTransitionPassID, int baseTexture2Var, + int baseTexture2FrameVar, bool bTeeth, int nTeethForwardVar, int nTeethIllumFactorVar ) +{ + // FLASHLIGHTFIXME: hack . . need to fix the vertex shader so that it can deal with and without bumps for vertexlitgeneric + if( !bLightmappedGeneric ) + { + bBump = false; + } + if( pShaderShadow ) + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + // Never alpha test the flashlight pass + pShaderShadow->EnableAlphaTest( false ); + + if ( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) ) + { + // use zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + + // Alpha blend + if( bWorldVertexTransition ) + { + // use separate alpha blend to make sure that we aren't adding alpha from source + if( nWorldVertexTransitionPassID == 0 ) + { + EnableAlphaBlending( SHADER_BLEND_DST_ALPHA, SHADER_BLEND_ONE ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_DST_ALPHA, SHADER_BLEND_ONE ); + } + } + else + { + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + if( bLightmappedGeneric ) + { + bool bUsingVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + lightmappedgeneric_flashlight_vs11_Static_Index vshIndex; + vshIndex.SetNORMALMAP( bBump ); + vshIndex.SetWORLDVERTEXTRANSITION( bWorldVertexTransition ); + vshIndex.SetVERTEXCOLOR( bUsingVertexColor ); + pShaderShadow->SetVertexShader( "lightmappedgeneric_flashlight_vs11", vshIndex.GetIndex() ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + if( bBump ) + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + if ( bWorldVertexTransition || bUsingVertexColor ) + { + flags |= VERTEX_COLOR; + } + pShaderShadow->VertexShaderVertexFormat( flags, 1, 0, 0 ); + } + else + { + vertexlitgeneric_flashlight_vs11_Static_Index vshIndex; + vshIndex.SetTEETH( bTeeth ); + pShaderShadow->SetVertexShader( "vertexlitgeneric_flashlight_vs11", vshIndex.GetIndex() ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( flags, 1, 0, bBump ? 4 : 0 ); + } + + bool bNoCull = IS_FLAG_SET( MATERIAL_VAR_NOCULL ); + + flashlight_ps11_Static_Index pshIndex; + pshIndex.SetNORMALMAP( bBump ); + pshIndex.SetNOCULL( bNoCull ); + pShaderShadow->SetPixelShader( "flashlight_ps11", pshIndex.GetIndex() ); + + FogToBlack(); + } + else + { + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 0, true ); + BindTexture( SHADER_SAMPLER0, flashlightTextureVar, flashlightTextureFrameVar ); + + if( bWorldVertexTransition && ( nWorldVertexTransitionPassID == 1 ) ) + { + BindTexture( SHADER_SAMPLER1, baseTexture2Var, baseTexture2FrameVar ); + } + else + { + if( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP ); + if( bBump ) + { + BindTexture( SHADER_SAMPLER3, bumpmapVar, bumpmapFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + } + + if( bLightmappedGeneric ) + { + lightmappedgeneric_flashlight_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + vertexlitgeneric_flashlight_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + + if( bTeeth ) + { + Assert( nTeethForwardVar >= 0 ); + Assert( nTeethIllumFactorVar >= 0 ); + Vector4D lighting; + params[nTeethForwardVar]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[nTeethIllumFactorVar]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, lighting.Base() ); + } + + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + flashlight_ps11_Dynamic_Index pshIndex; + pShaderAPI->SetPixelShaderIndex( pshIndex.GetIndex() ); + + SetFlashlightVertexShaderConstants( bBump, bumpTransform, false, -1, true ); + } + Draw(); +} +#endif // support_dx8 + +#ifdef STDSHADER_DX9_DLL_EXPORT +void CBaseVSShader::DrawFlashlight_dx90( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, DrawFlashlight_dx90_Vars_t &vars ) +{ + // FLASHLIGHTFIXME: hack . . need to fix the vertex shader so that it can deal with and without bumps for vertexlitgeneric + if( !vars.m_bLightmappedGeneric ) + { + vars.m_bBump = false; + } + bool bBump2 = vars.m_bWorldVertexTransition && vars.m_bBump && vars.m_nBumpmap2Var != -1 && params[vars.m_nBumpmap2Var]->IsTexture(); + bool bSeamless = vars.m_fSeamlessScale != 0.0; + bool bDetail = vars.m_bLightmappedGeneric && (vars.m_nDetailVar != -1) && params[vars.m_nDetailVar]->IsDefined() && (vars.m_nDetailScale != -1); + + int nDetailBlendMode = 0; + if ( bDetail ) + { + nDetailBlendMode = GetIntParam( vars.m_nDetailTextureCombineMode, params ); + nDetailBlendMode = nDetailBlendMode > 1 ? 1 : nDetailBlendMode; + } + + if( pShaderShadow ) + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + // Alpha blend + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) ); + if ( vars.m_nAlphaTestReference != -1 && params[vars.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[vars.m_nAlphaTestReference]->GetFloatValue() ); + } + + // Spot sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + // Base sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + + // Normalizing cubemap sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // Normalizing cubemap sampler2 or normal map sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + // RandomRotation sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + + // Flashlight depth sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 ); + + if( vars.m_bWorldVertexTransition ) + { + // $basetexture2 + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + } + if( bBump2 ) + { + // Normalmap2 sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + } + if( bDetail ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // detail sampler + if ( nDetailBlendMode != 0 ) //Not Mod2X + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + if( vars.m_bLightmappedGeneric ) + { + lightmappedgeneric_flashlight_vs20_Static_Index vshIndex; + vshIndex.SetWORLDVERTEXTRANSITION( vars.m_bWorldVertexTransition ); + vshIndex.SetNORMALMAP( vars.m_bBump ); + vshIndex.SetSEAMLESS( bSeamless ); + vshIndex.SetDETAIL( bDetail ); + pShaderShadow->SetVertexShader( "lightmappedgeneric_flashlight_vs20", vshIndex.GetIndex() ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + if( vars.m_bBump ) + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + int numTexCoords = 1; + if( vars.m_bWorldVertexTransition ) + { + flags |= VERTEX_COLOR; + numTexCoords = 2; // need lightmap texcoords to get alpha. + } + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + } + else + { + vertexlitgeneric_flashlight_vs11_Static_Index vshIndex; + vshIndex.SetTEETH( vars.m_bTeeth ); + pShaderShadow->SetVertexShader( "vertexlitgeneric_flashlight_vs11", vshIndex.GetIndex() ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int numTexCoords = 1; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, vars.m_bBump ? 4 : 0 ); + } + + int nBumpMapVariant = 0; + if ( vars.m_bBump ) + { + nBumpMapVariant = ( vars.m_bSSBump ) ? 2 : 1; + } + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); + + flashlight_ps20b_Static_Index pshIndex; + pshIndex.SetNORMALMAP( nBumpMapVariant ); + pshIndex.SetNORMALMAP2( bBump2 ); + pshIndex.SetWORLDVERTEXTRANSITION( vars.m_bWorldVertexTransition ); + pshIndex.SetSEAMLESS( bSeamless ); + pshIndex.SetDETAILTEXTURE( bDetail ); + pshIndex.SetDETAIL_BLEND_MODE( nDetailBlendMode ); + pshIndex.SetFLASHLIGHTDEPTHFILTERMODE( nShadowFilterMode ); + pShaderShadow->SetPixelShader( "flashlight_ps20b", pshIndex.GetIndex() ); + } + else + { + flashlight_ps20_Static_Index pshIndex; + pshIndex.SetNORMALMAP( nBumpMapVariant ); + pshIndex.SetNORMALMAP2( bBump2 ); + pshIndex.SetWORLDVERTEXTRANSITION( vars.m_bWorldVertexTransition ); + pshIndex.SetSEAMLESS( bSeamless ); + pshIndex.SetDETAILTEXTURE( bDetail ); + pshIndex.SetDETAIL_BLEND_MODE( nDetailBlendMode ); + pShaderShadow->SetPixelShader( "flashlight_ps20", pshIndex.GetIndex() ); + } + FogToBlack(); + } + else + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + SetFlashLightColorFromState( flashlightState, pShaderAPI ); + + BindTexture( SHADER_SAMPLER0, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + BindTexture( SHADER_SAMPLER7, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + + // Tweaks associated with a given flashlight + float tweaks[4]; + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + } + + if( params[BASETEXTURE]->IsTexture() && mat_fullbright.GetInt() != 2 ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + if( vars.m_bWorldVertexTransition ) + { + Assert( vars.m_nBaseTexture2Var >= 0 && vars.m_nBaseTexture2FrameVar >= 0 ); + BindTexture( SHADER_SAMPLER4, vars.m_nBaseTexture2Var, vars.m_nBaseTexture2FrameVar ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP ); + if( vars.m_bBump ) + { + BindTexture( SHADER_SAMPLER3, vars.m_nBumpmapVar, vars.m_nBumpmapFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + } + + if( bDetail ) + { + BindTexture( SHADER_SAMPLER8, vars.m_nDetailVar ); + } + + if( vars.m_bWorldVertexTransition ) + { + if( bBump2 ) + { + BindTexture( SHADER_SAMPLER6, vars.m_nBumpmap2Var, vars.m_nBumpmap2Frame ); + } + } + + if( vars.m_bLightmappedGeneric ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 ); + if ( bSeamless ) + { + float const0[4]={ vars.m_fSeamlessScale,0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, const0 ); + } + + if ( bDetail ) + { + float vDetailConstants[4] = {1,1,1,1}; + + if ( vars.m_nDetailTint != -1 ) + { + params[vars.m_nDetailTint]->GetVecValue( vDetailConstants, 3 ); + } + + if ( vars.m_nDetailTextureBlendFactor != -1 ) + { + vDetailConstants[3] = params[vars.m_nDetailTextureBlendFactor]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vDetailConstants, 1 ); + } + } + else + { + vertexlitgeneric_flashlight_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( vars.m_bTeeth ) + { + Assert( vars.m_nTeethForwardVar >= 0 ); + Assert( vars.m_nTeethIllumFactorVar >= 0 ); + Vector4D lighting; + params[vars.m_nTeethForwardVar]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[vars.m_nTeethIllumFactorVar]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() ); + } + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ) ); + SET_DYNAMIC_PIXEL_SHADER( flashlight_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( flashlight_ps20 ); + } + + float atten[4]; // Set the flashlight attenuation factors + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + s_pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + SetFlashlightVertexShaderConstants( vars.m_bBump, vars.m_nBumpTransform, bDetail, vars.m_nDetailScale, bSeamless ? false : true ); + } + Draw(); +} + +#endif + +void CBaseVSShader::InitParamsUnlitGeneric_DX8( + int baseTextureVar, + int detailScaleVar, + int envmapOptionalVar, + int envmapVar, + int envmapTintVar, + int envmapMaskScaleVar, + int nDetailBlendMode ) +{ + IMaterialVar** params = s_ppParams; + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( envmapTintVar >= 0 && !params[envmapTintVar]->IsDefined() ) + { + params[envmapTintVar]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( envmapMaskScaleVar >= 0 && !params[envmapMaskScaleVar]->IsDefined() ) + { + params[envmapMaskScaleVar]->SetFloatValue( 1.0f ); + } + + if( detailScaleVar >= 0 && !params[detailScaleVar]->IsDefined() ) + { + params[detailScaleVar]->SetFloatValue( 4.0f ); + } + + // No texture means no self-illum or env mask in base alpha + if ( baseTextureVar >= 0 && !params[baseTextureVar]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + // Get rid of the envmap if it's optional for this dx level. + if( envmapOptionalVar >= 0 && params[envmapOptionalVar]->IsDefined() && params[envmapOptionalVar]->GetIntValue() ) + { + if (envmapVar >= 0) + { + params[envmapVar]->SetUndefined(); + } + } + + // If mat_specular 0, then get rid of envmap + if( envmapVar >= 0 && baseTextureVar >= 0 && !g_pConfig->UseSpecular() && params[envmapVar]->IsDefined() && params[baseTextureVar]->IsDefined() ) + { + params[envmapVar]->SetUndefined(); + } +} + +void CBaseVSShader::InitUnlitGeneric_DX8( + int baseTextureVar, + int detailVar, + int envmapVar, + int envmapMaskVar ) +{ + IMaterialVar** params = s_ppParams; + + if (baseTextureVar >= 0 && params[baseTextureVar]->IsDefined()) + { + LoadTexture( baseTextureVar ); + + if (!params[baseTextureVar]->GetTextureValue()->IsTranslucent()) + { + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if ( IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + // the second texture (if there is one) + if (detailVar >= 0 && params[detailVar]->IsDefined()) + { + LoadTexture( detailVar ); + } + + if (envmapVar >= 0 && params[envmapVar]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( envmapVar ); + else + LoadTexture( envmapVar ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + SET_FLAGS(MATERIAL_VAR_ENVMAPSPHERE); + + if (envmapMaskVar >= 0 && params[envmapMaskVar]->IsDefined()) + LoadTexture( envmapMaskVar ); + } +} +#endif // GAME_SHADER_DLL + +#endif // !_STATIC_LINKED || STDSHADER_DX8_DLL_EXPORT + + +// Take 0..1 seed and map to (u, v) coordinate to be used in shadow filter jittering... +void CBaseVSShader::HashShadow2DJitter( const float fJitterSeed, float *fU, float* fV ) +{ + const int nTexRes = 32; + int nSeed = fmod (fJitterSeed, 1.0f) * nTexRes * nTexRes; + + int nRow = nSeed / nTexRes; + int nCol = nSeed % nTexRes; + + // Div and mod to get an individual texel in the fTexRes x fTexRes grid + *fU = nRow / (float) nTexRes; // Row + *fV = nCol / (float) nTexRes; // Column +} + + +void CBaseVSShader::DrawEqualDepthToDestAlpha( void ) +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + bool bMakeActualDrawCall = false; + if( s_pShaderShadow ) + { + s_pShaderShadow->EnableColorWrites( false ); + s_pShaderShadow->EnableAlphaWrites( true ); + s_pShaderShadow->EnableDepthWrites( false ); + s_pShaderShadow->EnableAlphaTest( false ); + s_pShaderShadow->EnableBlending( false ); + + s_pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + + s_pShaderShadow->SetVertexShader( "depthtodestalpha_vs20", 0 ); + s_pShaderShadow->SetPixelShader( "depthtodestalpha_ps20b", 0 ); + } + if( s_pShaderAPI ) + { + s_pShaderAPI->SetVertexShaderIndex( 0 ); + s_pShaderAPI->SetPixelShaderIndex( 0 ); + + bMakeActualDrawCall = s_pShaderAPI->ShouldWriteDepthToDestAlpha(); + } + Draw( bMakeActualDrawCall ); + } +#else + Assert( 0 ); //probably just needs a shader update to the latest +#endif +} diff --git a/mp/src/materialsystem/stdshaders/BaseVSShader.h b/mp/src/materialsystem/stdshaders/BaseVSShader.h new file mode 100644 index 00000000..2a38afb1 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BaseVSShader.h @@ -0,0 +1,439 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// This is what all vs/ps (dx8+) shaders inherit from. +//===========================================================================// + +#ifndef BASEVSSHADER_H +#define BASEVSSHADER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "shaderlib/cshader.h" +#include "shaderlib/BaseShader.h" +#include "convar.h" +#include + +#ifdef _X360 +#define SUPPORT_DX8 0 +#define SUPPORT_DX7 0 +#else +#define SUPPORT_DX8 1 +#define SUPPORT_DX7 1 +#endif +//----------------------------------------------------------------------------- +// Helper macro for vertex shaders +//----------------------------------------------------------------------------- +#define BEGIN_VS_SHADER_FLAGS(_name, _help, _flags) __BEGIN_SHADER_INTERNAL( CBaseVSShader, _name, _help, _flags ) +#define BEGIN_VS_SHADER(_name,_help) __BEGIN_SHADER_INTERNAL( CBaseVSShader, _name, _help, 0 ) + + +// useful parameter initialization macro +#define INIT_FLOAT_PARM( parm, value ) \ + if ( !params[(parm)]->IsDefined() ) \ + { \ + params[(parm)]->SetFloatValue( (value) ); \ + } + +// useful pixel shader declaration macro for ps20/20b c++ code +#define SET_STATIC_PS2X_PIXEL_SHADER_NO_COMBOS( basename ) \ + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) \ + { \ + DECLARE_STATIC_PIXEL_SHADER( basename##_ps20b ); \ + SET_STATIC_PIXEL_SHADER( basename##_ps20b ); \ + } \ + else \ + { \ + DECLARE_STATIC_PIXEL_SHADER( basename##_ps20 ); \ + SET_STATIC_PIXEL_SHADER( basename##_ps20 ); \ + } + +#define SET_DYNAMIC_PS2X_PIXEL_SHADER_NO_COMBOS( basename ) \ + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) \ + { \ + DECLARE_DYNAMIC_PIXEL_SHADER( basename##_ps20b ); \ + SET_DYNAMIC_PIXEL_SHADER( basename##_ps20b ); \ + } \ + else \ + { \ + DECLARE_DYNAMIC_PIXEL_SHADER( basename##_ps20 ); \ + SET_DYNAMIC_PIXEL_SHADER( basename##_ps20 ); \ + } + + +//----------------------------------------------------------------------------- +// Base class for shaders, contains helper methods. +//----------------------------------------------------------------------------- +class CBaseVSShader : public CBaseShader +{ +public: + + // Loads bump lightmap coordinates into the pixel shader + void LoadBumpLightmapCoordinateAxes_PixelShader( int pixelReg ); + + // Loads bump lightmap coordinates into the vertex shader + void LoadBumpLightmapCoordinateAxes_VertexShader( int vertexReg ); + + // Pixel and vertex shader constants.... + void SetPixelShaderConstant( int pixelReg, int constantVar ); + + // Pixel and vertex shader constants.... + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ); + + // This version will put constantVar into x,y,z, and constantVar2 into the w + void SetPixelShaderConstant( int pixelReg, int constantVar, int constantVar2 ); + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar, int constantVar2 ); + + // Helpers for setting constants that need to be converted to linear space (from gamma space). + void SetVertexShaderConstantGammaToLinear( int var, float const* pVec, int numConst = 1, bool bForce = false ); + void SetPixelShaderConstantGammaToLinear( int var, float const* pVec, int numConst = 1, bool bForce = false ); + + void SetVertexShaderConstant( int vertexReg, int constantVar ); + + // set rgb components of constant from a color parm and give an explicit w value + void SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ); + + // GR - fix for const/lerp issues + void SetPixelShaderConstantFudge( int pixelReg, int constantVar ); + + // Sets light direction for pixel shaders. + void SetPixelShaderLightColors( int pixelReg ); + + // Sets vertex shader texture transforms + void SetVertexShaderTextureTranslation( int vertexReg, int translationVar ); + void SetVertexShaderTextureScale( int vertexReg, int scaleVar ); + void SetVertexShaderTextureTransform( int vertexReg, int transformVar ); + void SetVertexShaderTextureScaledTransform( int vertexReg, + int transformVar, int scaleVar ); + + // Set pixel shader texture transforms + void SetPixelShaderTextureTranslation( int pixelReg, int translationVar ); + void SetPixelShaderTextureScale( int pixelReg, int scaleVar ); + void SetPixelShaderTextureTransform( int pixelReg, int transformVar ); + void SetPixelShaderTextureScaledTransform( int pixelReg, + int transformVar, int scaleVar ); + + // Moves a matrix into vertex shader constants + void SetVertexShaderMatrix3x4( int vertexReg, int matrixVar ); + void SetVertexShaderMatrix4x4( int vertexReg, int matrixVar ); + + // Loads the view matrix into vertex shader constants + void LoadViewMatrixIntoVertexShaderConstant( int vertexReg ); + + // Loads the projection matrix into vertex shader constants + void LoadProjectionMatrixIntoVertexShaderConstant( int vertexReg ); + + // Loads the model->view matrix into vertex shader constants + void LoadModelViewMatrixIntoVertexShaderConstant( int vertexReg ); + + // Loads a scale/offset version of the viewport transform into the specified constant. + void LoadViewportTransformScaledIntoVertexShaderConstant( int vertexReg ); + + // Sets up ambient light cube... + void SetAmbientCubeDynamicStateVertexShader( ); + float GetAmbientLightCubeLuminance( ); + + // Helpers for dealing with envmaptint + void SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar, int alphaVar, bool bConvertFromGammaToLinear = false ); + + // Helper methods for pixel shader overbrighting + void EnablePixelShaderOverbright( int reg, bool bEnable, bool bDivideByTwo ); + + // Helper for dealing with modulation + void SetModulationVertexShaderDynamicState(); + void SetModulationPixelShaderDynamicState( int modulationVar ); + void SetModulationPixelShaderDynamicState_LinearColorSpace( int modulationVar ); + void SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int modulationVar, float flScale ); + + // Sets a color + alpha into shader constants + void SetColorVertexShaderConstant( int nVertexReg, int colorVar, int alphaVar ); + void SetColorPixelShaderConstant( int nPixelReg, int colorVar, int alphaVar ); + + +#ifndef GAME_SHADER_DLL + // + // Standard shader passes! + // + + void InitParamsUnlitGeneric_DX8( + int baseTextureVar, + int detailScaleVar, + int envmapOptionalVar, + int envmapVar, + int envmapTintVar, + int envmapMaskScaleVar, + int nDetailBlendMode ); + + void InitUnlitGeneric_DX8( + int baseTextureVar, + int detailVar, + int envmapVar, + int envmapMaskVar ); + + // Dx8 Unlit Generic pass + void VertexShaderUnlitGenericPass( int baseTextureVar, int frameVar, + int baseTextureTransformVar, + int detailVar, int detailTransform, bool bDetailTransformIsScale, + int envmapVar, int envMapFrameVar, int envmapMaskVar, + int envmapMaskFrameVar, int envmapMaskScaleVar, int envmapTintVar, + int alphaTestReferenceVar, + int nDetailBlendModeVar, + int nOutlineVar, + int nOutlineColorVar, + int nOutlineStartVar, + int nOutlineEndVar, + int nSeparateDetailUVsVar + ); + + // Helpers for drawing world bump mapped stuff. + void DrawModelBumpedSpecularLighting( int bumpMapVar, int bumpMapFrameVar, + int envMapVar, int envMapVarFrame, + int envMapTintVar, int alphaVar, + int envMapContrastVar, int envMapSaturationVar, + int bumpTransformVar, + bool bBlendSpecular, bool bNoWriteZ = false ); + void DrawWorldBumpedSpecularLighting( int bumpmapVar, int envmapVar, + int bumpFrameVar, int envmapFrameVar, + int envmapTintVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, + int bumpTransformVar, int fresnelReflectionVar, + bool bBlend, bool bNoWriteZ = false ); + + const char *UnlitGeneric_ComputeVertexShaderName( bool bMask, + bool bEnvmap, + bool bBaseTexture, + bool bBaseAlphaEnvmapMask, + bool bDetail, + bool bVertexColor, + bool bEnvmapCameraSpace, + bool bEnvmapSphere ); + + const char *UnlitGeneric_ComputePixelShaderName( bool bMask, + bool bEnvmap, + bool bBaseTexture, + bool bBaseAlphaEnvmapMask, + bool bDetail, + bool bMultiplyDetail, + bool bMaskBaseByDetailAlpha ); + + void DrawWorldBaseTexture( int baseTextureVar, int baseTextureTransformVar, int frameVar, int colorVar, int alphaVar ); + void DrawWorldBumpedDiffuseLighting( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, bool bMultiply, bool bSSBump ); + void DrawWorldBumpedSpecularLighting( int envmapMaskVar, int envmapMaskFrame, + int bumpmapVar, int envmapVar, + int bumpFrameVar, int envmapFrameVar, + int envmapTintVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, + int bumpTransformVar, int fresnelReflectionVar, + bool bBlend ); + void DrawBaseTextureBlend( int baseTextureVar, int baseTextureTransformVar, + int baseTextureFrameVar, + int baseTexture2Var, int baseTextureTransform2Var, + int baseTextureFrame2Var, int colorVar, int alphaVar ); + void DrawWorldBumpedDiffuseLighting_Base_ps14( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, int baseTextureVar, int baseTextureTransformVar, int frameVar ); + void DrawWorldBumpedDiffuseLighting_Blend_ps14( int bumpmapVar, int bumpFrameVar, int bumpTransformVar, + int baseTextureVar, int baseTextureTransformVar, int baseTextureFrameVar, + int baseTexture2Var, int baseTextureTransform2Var, int baseTextureFrame2Var); + void DrawWorldBumpedUsingVertexShader( int baseTextureVar, int baseTextureTransformVar, + int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, + int envmapMaskVar, int envmapMaskFrame, + int envmapVar, + int envmapFrameVar, + int envmapTintVar, int colorVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, int frameVar, int fresnelReflectionVar, + bool doBaseTexture2, + int baseTexture2Var, + int baseTextureTransform2Var, + int baseTextureFrame2Var, + bool bSSBump + ); + + // Sets up hw morphing state for the vertex shader + void SetHWMorphVertexShaderState( int nDimConst, int nSubrectConst, VertexTextureSampler_t morphSampler ); + + // Computes the shader index for vertex lit materials + int ComputeVertexLitShaderIndex( bool bVertexLitGeneric, bool hasBump, bool hasEnvmap, bool hasVertexColor, bool bHasNormal ) const; + + // Helper for setting up flashlight constants + void SetFlashlightVertexShaderConstants( bool bBump, int bumpTransformVar, bool bDetail, int detailScaleVar, bool bSetTextureTransforms ); + +#if SUPPORT_DX8 + void DrawFlashlight_dx80( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bBump, int bumpmapVar, int bumpmapFrame, int bumpTransform, int flashlightTextureVar, + int flashlightTextureFrameVar, bool bLightmappedGeneric, bool bWorldVertexTransition, + int nWorldVertexTransitionPassID, int baseTexture2Var, int baseTexture2FrameVar, + bool bTeeth=false, int nTeethForwardVar=0, int nTeethIllumFactorVar=0 ); +#endif + + struct DrawFlashlight_dx90_Vars_t + { + DrawFlashlight_dx90_Vars_t() + { + // set all ints to -1 + memset( this, 0xFF, sizeof(DrawFlashlight_dx90_Vars_t) ); + // set all bools to a default value. + m_bBump = false; + m_bLightmappedGeneric = false; + m_bWorldVertexTransition = false; + m_bTeeth = false; + m_bSSBump = false; + m_fSeamlessScale = 0.0; + } + bool m_bBump; + bool m_bLightmappedGeneric; + bool m_bWorldVertexTransition; + bool m_bTeeth; + int m_nBumpmapVar; + int m_nBumpmapFrame; + int m_nBumpTransform; + int m_nFlashlightTextureVar; + int m_nFlashlightTextureFrameVar; + int m_nBaseTexture2Var; + int m_nBaseTexture2FrameVar; + int m_nBumpmap2Var; + int m_nBumpmap2Frame; + int m_nBump2Transform; + int m_nDetailVar; + int m_nDetailScale; + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + int m_nDetailTint; + int m_nTeethForwardVar; + int m_nTeethIllumFactorVar; + int m_nAlphaTestReference; + bool m_bSSBump; + float m_fSeamlessScale; // 0.0 = not seamless + }; + void DrawFlashlight_dx90( IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, DrawFlashlight_dx90_Vars_t &vars ); +#endif // GAME_SHADER_DLL + + BlendType_t EvaluateBlendRequirements( int textureVar, bool isBaseTexture, int detailTextureVar = -1 ); + + void HashShadow2DJitter( const float fJitterSeed, float *fU, float* fV ); + + //Alpha tested materials can end up leaving garbage in the dest alpha buffer if they write depth. + //This pass fills in the areas that passed the alpha test with depth in dest alpha + //by writing only equal depth pixels and only if we should be writing depth to dest alpha + void DrawEqualDepthToDestAlpha( void ); + +private: + // Helper methods for VertexLitGenericPass +// void UnlitGenericShadowState( int baseTextureVar, int detailVar, int envmapVar, int envmapMaskVar, bool doSkin ); + void UnlitGenericDynamicState( int baseTextureVar, int frameVar, int baseTextureTransformVar, + int detailVar, int detailTransform, bool bDetailTransformIsScale, int envmapVar, + int envMapFrameVar, int envmapMaskVar, int envmapMaskFrameVar, + int envmapMaskScaleVar, int envmapTintVar ); + + // Converts a color + alpha into a vector4 + void ColorVarsToVector( int colorVar, int alphaVar, Vector4D &color ); + +}; + +FORCEINLINE void SetFlashLightColorFromState( FlashlightState_t const &state, IShaderDynamicAPI *pShaderAPI, int nPSRegister=28, bool bFlashlightNoLambert=false ) +{ + // Old code + //float flToneMapScale = ( pShaderAPI->GetToneMappingScaleLinear() ).x; + //float flFlashlightScale = 1.0f / flToneMapScale; + + // Fix to old code to keep flashlight from ever getting brighter than 1.0 + //float flToneMapScale = ( pShaderAPI->GetToneMappingScaleLinear() ).x; + //if ( flToneMapScale < 1.0f ) + // flToneMapScale = 1.0f; + //float flFlashlightScale = 1.0f / flToneMapScale; + + // Force flashlight to 25% bright always + float flFlashlightScale = 0.25f; + + if ( !g_pHardwareConfig->GetHDREnabled() ) + { + // Non-HDR path requires 2.0 flashlight + flFlashlightScale = 2.0f; + } + + // DX10 requires some hackery due to sRGB/blend ordering change from DX9 + if ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) + { + flFlashlightScale *= 2.5f; // Magic number that works well on the NVIDIA 8800 + } + + // Generate pixel shader constant + float const *pFlashlightColor = state.m_Color; + float vPsConst[4] = { flFlashlightScale * pFlashlightColor[0], flFlashlightScale * pFlashlightColor[1], flFlashlightScale * pFlashlightColor[2], pFlashlightColor[3] }; + vPsConst[3] = bFlashlightNoLambert ? 2.0f : 0.0f; // This will be added to N.L before saturate to force a 1.0 N.L term + + // Red flashlight for testing + //vPsConst[0] = 0.5f; vPsConst[1] = 0.0f; vPsConst[2] = 0.0f; + + pShaderAPI->SetPixelShaderConstant( nPSRegister, ( float * )vPsConst ); +} + +FORCEINLINE float ShadowAttenFromState( FlashlightState_t const &state ) +{ + // DX10 requires some hackery due to sRGB/blend ordering change from DX9, which makes the shadows too light + if ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) + return state.m_flShadowAtten * 0.1f; // magic number + + return state.m_flShadowAtten; +} + +FORCEINLINE float ShadowFilterFromState( FlashlightState_t const &state ) +{ + // We developed shadow maps at 1024, so we expect the penumbra size to have been tuned relative to that + return state.m_flShadowFilterSize / 1024.0f; +} + + +// convenient material variable access functions for helpers to use. +FORCEINLINE bool IsTextureSet( int nVar, IMaterialVar **params ) +{ + return ( nVar != -1 ) && ( params[nVar]->IsTexture() ); +} + +FORCEINLINE bool IsBoolSet( int nVar, IMaterialVar **params ) +{ + return ( nVar != -1 ) && ( params[nVar]->GetIntValue() ); +} + +FORCEINLINE int GetIntParam( int nVar, IMaterialVar **params, int nDefaultValue = 0 ) +{ + return ( nVar != -1 ) ? ( params[nVar]->GetIntValue() ) : nDefaultValue; +} + +FORCEINLINE float GetFloatParam( int nVar, IMaterialVar **params, float flDefaultValue = 0.0 ) +{ + return ( nVar != -1 ) ? ( params[nVar]->GetFloatValue() ) : flDefaultValue; +} + +FORCEINLINE void InitFloatParam( int nIndex, IMaterialVar **params, float flValue ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetFloatValue( flValue ); + } +} + +FORCEINLINE void InitIntParam( int nIndex, IMaterialVar **params, int nValue ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetIntValue( nValue ); + } +} + + +class ConVar; + +#ifdef _DEBUG +extern ConVar mat_envmaptintoverride; +extern ConVar mat_envmaptintscale; +#endif + + +#endif // BASEVSSHADER_H diff --git a/mp/src/materialsystem/stdshaders/buildhl2mpshaders.bat b/mp/src/materialsystem/stdshaders/buildhl2mpshaders.bat new file mode 100644 index 00000000..58b0cd26 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/buildhl2mpshaders.bat @@ -0,0 +1,21 @@ +@echo off +setlocal + +rem ================================ +rem ==== MOD PATH CONFIGURATIONS === + +rem == Set the absolute path to your mod's game directory here == +set GAMEDIR=%cd%\..\..\..\game\mod_hl2mp + +rem == Set the relative or absolute path to Source SDK Base 2013 Singleplayer\bin == +set SDKBINDIR=C:\SteamBetaLibrary\SteamApps\common\Source SDK Base 2013 Singleplayer\bin + +rem == Set the Path to your mod's root source code == +rem This should already be correct, accepts relative paths only! +set SOURCEDIR=..\.. + +rem ==== MOD PATH CONFIGURATIONS END === +rem ==================================== + + +call buildsdkshaders.bat diff --git a/mp/src/materialsystem/stdshaders/buildsdkshaders.bat b/mp/src/materialsystem/stdshaders/buildsdkshaders.bat new file mode 100644 index 00000000..eeaa5b8c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/buildsdkshaders.bat @@ -0,0 +1,40 @@ +@echo off +setlocal + +rem Use dynamic shaders to build .inc files only +rem set dynamic_shaders=1 +rem == Setup path to nmake.exe, from vc 2005 common tools directory == +call "%VS100COMNTOOLS%vsvars32.bat" + + +set TTEXE=..\..\devtools\bin\timeprecise.exe +if not exist %TTEXE% goto no_ttexe +goto no_ttexe_end + +:no_ttexe +set TTEXE=time /t +:no_ttexe_end + + +rem echo. +rem echo ~~~~~~ buildsdkshaders %* ~~~~~~ +%TTEXE% -cur-Q +set tt_all_start=%ERRORLEVEL% +set tt_all_chkpt=%tt_start% + +set BUILD_SHADER=call buildshaders.bat +set ARG_EXTRA= + +%BUILD_SHADER% stdshader_dx9_20b -game %GAMEDIR% -source %SOURCEDIR% +%BUILD_SHADER% stdshader_dx9_30 -game %GAMEDIR% -source %SOURCEDIR% -dx9_30 -force30 + + +rem echo. +if not "%dynamic_shaders%" == "1" ( + rem echo Finished full buildallshaders %* +) else ( + rem echo Finished dynamic buildallshaders %* +) + +rem %TTEXE% -diff %tt_all_start% -cur +rem echo. diff --git a/mp/src/materialsystem/stdshaders/buildshaders.bat b/mp/src/materialsystem/stdshaders/buildshaders.bat new file mode 100644 index 00000000..64859912 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/buildshaders.bat @@ -0,0 +1,209 @@ +@echo off + +set TTEXE=..\..\devtools\bin\timeprecise.exe +if not exist %TTEXE% goto no_ttexe +goto no_ttexe_end + +:no_ttexe +set TTEXE=time /t +:no_ttexe_end + +echo. +echo ==================== buildshaders %* ================== +%TTEXE% -cur-Q +set tt_start=%ERRORLEVEL% +set tt_chkpt=%tt_start% + + +REM **************** +REM usage: buildshaders +REM **************** + +setlocal +set arg_filename=%1 +set shadercompilecommand=shadercompile.exe +set targetdir=shaders +set SrcDirBase=..\.. +set shaderDir=shaders +set SDKArgs= +set SHADERINCPATH=vshtmp9/... fxctmp9/... + + +if "%1" == "" goto usage +set inputbase=%1 + +set DIRECTX_SDK_VER=pc09.00 +set DIRECTX_SDK_BIN_DIR=dx9sdk\utilities + +if /i "%6" == "-dx9_30" goto dx_sdk_dx9_30 +goto dx_sdk_end +:dx_sdk_dx9_30 + set DIRECTX_SDK_VER=pc09.30 + set DIRECTX_SDK_BIN_DIR=dx10sdk\utilities\dx9_30 + goto dx_sdk_end +:dx_sdk_end + +if /i "%7" == "-force30" goto set_force30_arg +goto set_force_end +:set_force30_arg + set DIRECTX_FORCE_MODEL=30 + goto set_force_end +:set_force_end + +if /i "%2" == "-game" goto set_mod_args +goto build_shaders + +REM **************** +REM USAGE +REM **************** +:usage +echo. +echo "usage: buildshaders [-game] [gameDir if -game was specified] [-source sourceDir]" +echo " gameDir is where gameinfo.txt is (where it will store the compiled shaders)." +echo " sourceDir is where the source code is (where it will find scripts and compilers)." +echo "ex : buildshaders myshaders" +echo "ex : buildshaders myshaders -game c:\steam\steamapps\sourcemods\mymod -source c:\mymod\src" +goto :end + +REM **************** +REM MOD ARGS - look for -game or the vproject environment variable +REM **************** +:set_mod_args + +if not exist "%SDKBINDIR%\shadercompile.exe" goto NoShaderCompile +set ChangeToDir=%SDKBINDIR% + +if /i "%4" NEQ "-source" goto NoSourceDirSpecified +set SrcDirBase=%~5 + +REM ** use the -game parameter to tell us where to put the files +set targetdir=%~3\shaders +set SDKArgs=-nompi -nop4 -game "%~3" + +if not exist "%~3\gameinfo.txt" goto InvalidGameDirectory +goto build_shaders + +REM **************** +REM ERRORS +REM **************** +:InvalidGameDirectory +echo - +echo Error: "%~3" is not a valid game directory. +echo (The -game directory must have a gameinfo.txt file) +echo - +goto end + +:NoSourceDirSpecified +echo ERROR: If you specify -game on the command line, you must specify -source. +goto usage +goto end + +:NoShaderCompile +echo - +echo - ERROR: shadercompile.exe doesn't exist in %SDKBINDIR% +echo - +goto end + +REM **************** +REM BUILD SHADERS +REM **************** +:build_shaders + +rem echo -------------------------------- +rem echo %inputbase% +rem echo -------------------------------- +REM make sure that target dirs exist +REM files will be built in these targets and copied to their final destination +if not exist %shaderDir% mkdir %shaderDir% +if not exist %shaderDir%\fxc mkdir %shaderDir%\fxc +if not exist %shaderDir%\vsh mkdir %shaderDir%\vsh +if not exist %shaderDir%\psh mkdir %shaderDir%\psh +REM Nuke some files that we will add to later. +if exist filelist.txt del /f /q filelist.txt +if exist filestocopy.txt del /f /q filestocopy.txt +if exist filelistgen.txt del /f /q filelistgen.txt +if exist inclist.txt del /f /q inclist.txt +if exist vcslist.txt del /f /q vcslist.txt + +REM **************** +REM Generate a makefile for the shader project +REM **************** +perl "%SrcDirBase%\devtools\bin\updateshaders.pl" -source "%SrcDirBase%" %inputbase% + + +REM **************** +REM Run the makefile, generating minimal work/build list for fxc files, go ahead and compile vsh and psh files. +REM **************** +rem nmake /S /C -f makefile.%inputbase% clean > clean.txt 2>&1 +echo Building inc files, asm vcs files, and VMPI worklist for %inputbase%... +nmake /S /C -f makefile.%inputbase% + +REM **************** +REM Copy the inc files to their target +REM **************** +if exist "inclist.txt" ( + echo Publishing shader inc files to target... + perl %SrcDirBase%\devtools\bin\copyshaderincfiles.pl inclist.txt +) + +REM **************** +REM Add the executables to the worklist. +REM **************** +if /i "%DIRECTX_SDK_VER%" == "pc09.00" ( + rem echo "Copy extra files for dx 9 std +) +if /i "%DIRECTX_SDK_VER%" == "pc09.30" ( + echo %SrcDirBase%\devtools\bin\d3dx9_33.dll >> filestocopy.txt +) + +echo %SrcDirBase%\%DIRECTX_SDK_BIN_DIR%\dx_proxy.dll >> filestocopy.txt + +echo %SDKBINDIR%\shadercompile.exe >> filestocopy.txt +echo %SDKBINDIR%\shadercompile_dll.dll >> filestocopy.txt +echo %SDKBINDIR%\vstdlib.dll >> filestocopy.txt +echo %SDKBINDIR%\tier0.dll >> filestocopy.txt + +REM **************** +REM Cull duplicate entries in work/build list +REM **************** +if exist filestocopy.txt type filestocopy.txt | perl "%SrcDirBase%\devtools\bin\uniqifylist.pl" > uniquefilestocopy.txt +if exist filelistgen.txt if not "%dynamic_shaders%" == "1" ( + echo Generating action list... + copy filelistgen.txt filelist.txt >nul +) + +REM **************** +REM Execute distributed process on work/build list +REM **************** + +set shader_path_cd=%cd% +if exist "filelist.txt" if exist "uniquefilestocopy.txt" if not "%dynamic_shaders%" == "1" ( + echo Running distributed shader compilation... + + cd /D %ChangeToDir% + echo %shadercompilecommand% %SDKArgs% -shaderpath "%shader_path_cd:/=\%" -allowdebug + %shadercompilecommand% %SDKArgs% -shaderpath "%shader_path_cd:/=\%" -allowdebug + cd /D %shader_path_cd% +) + +REM **************** +REM PC Shader copy +REM Publish the generated files to the output dir using XCOPY +REM This batch file may have been invoked standalone or slaved (master does final smart mirror copy) +REM **************** +:DoXCopy +if not "%dynamic_shaders%" == "1" ( +if not exist "%targetdir%" md "%targetdir%" +if not "%targetdir%"=="%shaderDir%" xcopy %shaderDir%\*.* "%targetdir%" /e /y +) +goto end + +REM **************** +REM END +REM **************** +:end + + +%TTEXE% -diff %tt_start% +echo. + diff --git a/mp/src/materialsystem/stdshaders/clean.bat b/mp/src/materialsystem/stdshaders/clean.bat new file mode 100644 index 00000000..eec63804 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/clean.bat @@ -0,0 +1,33 @@ +@echo off +setlocal + +if /i "%1" == "-game" goto CleanGameDir + +rem Clean out hl2 +if exist ..\..\..\game\hl2\shaders rd /s /q ..\..\..\game\hl2\shaders +goto CleanOtherStuff + +:CleanGameDir +set __GameDir=%~2 +if not exist "%__GameDir%\gameinfo.txt" goto MissingGameInfo +if exist "%__GameDir%\shaders" rd /s /q "%2\shaders" +goto CleanOtherStuff + +:CleanOtherStuff +if exist debug_dx9 rd /s /q debug_dx9 + +if exist fxctmp9 rd /s /q fxctmp9 +if exist vshtmp9 rd /s /q vshtmp9 +if exist pshtmp9 rd /s /q pshtmp9 +if exist fxctmp9_tmp rd /s /q fxctmp9_tmp +if exist vshtmp9_tmp rd /s /q vshtmp9_tmp +if exist pshtmp9_tmp rd /s /q pshtmp9_tmp +if exist shaders rd /s /q shaders +goto end + +:MissingGameInfo +echo Invalid -game parameter specified (no "%__GameDir%\gameinfo.txt" exists). +goto end + + +:end \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/cleantemps.bat b/mp/src/materialsystem/stdshaders/cleantemps.bat new file mode 100644 index 00000000..51478ee4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cleantemps.bat @@ -0,0 +1,12 @@ +@echo off +setlocal + +if exist fxctmp9_tmp rd /s /q fxctmp9_tmp +if exist vshtmp9_tmp rd /s /q vshtmp9_tmp +if exist pshtmp9_tmp rd /s /q pshtmp9_tmp + +if exist fxctmp9_360_tmp rd /s /q fxctmp9_360_tmp +if exist vshtmp9_360_tmp rd /s /q vshtmp9_360_tmp +if exist pshtmp9_360_tmp rd /s /q pshtmp9_360_tmp + +if exist shaders rd /s /q shaders diff --git a/mp/src/materialsystem/stdshaders/commandbuilder.h b/mp/src/materialsystem/stdshaders/commandbuilder.h new file mode 100644 index 00000000..13a68ede --- /dev/null +++ b/mp/src/materialsystem/stdshaders/commandbuilder.h @@ -0,0 +1,407 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// Utility class for building command buffers into memory +//===========================================================================// + +#ifndef COMMANDBUILDER_H +#define COMMANDBUILDER_H + +#ifndef COMMANDBUFFER_H +#include "shaderapi/commandbuffer.h" +#endif + +#include "BaseVSShader.h" +#include "shaderapi/ishaderapi.h" + +#ifdef _WIN32 +#pragma once +#endif + +extern ConVar my_mat_fullbright; + +template class CFixedCommandStorageBuffer +{ +public: + uint8 m_Data[N]; + + uint8 *m_pDataOut; +#ifdef DBGFLAG_ASSERT + size_t m_nNumBytesRemaining; +#endif + + FORCEINLINE CFixedCommandStorageBuffer( void ) + { + m_pDataOut = m_Data; +#ifdef DBGFLAG_ASSERT + m_nNumBytesRemaining = N; +#endif + + } + + FORCEINLINE void EnsureCapacity( size_t sz ) + { + Assert( m_nNumBytesRemaining >= sz ); + } + + template FORCEINLINE void Put( T const &nValue ) + { + EnsureCapacity( sizeof( T ) ); + *( reinterpret_cast( m_pDataOut ) ) = nValue; + m_pDataOut += sizeof( nValue ); +#ifdef DBGFLAG_ASSERT + m_nNumBytesRemaining -= sizeof( nValue ); +#endif + } + + FORCEINLINE void PutInt( int nValue ) + { + Put( nValue ); + } + + FORCEINLINE void PutFloat( float nValue ) + { + Put( nValue ); + } + + FORCEINLINE void PutPtr( void * pPtr ) + { + Put( pPtr ); + } + + FORCEINLINE void PutMemory( const void *pMemory, size_t nBytes ) + { + EnsureCapacity( nBytes ); + memcpy( m_pDataOut, pMemory, nBytes ); + m_pDataOut += nBytes; + } + + FORCEINLINE uint8 *Base( void ) + { + return m_Data; + } + + FORCEINLINE void Reset( void ) + { + m_pDataOut = m_Data; +#ifdef DBGFLAG_ASSERT + m_nNumBytesRemaining = N; +#endif + } + + FORCEINLINE size_t Size( void ) const + { + return m_pDataOut - m_Data; + } + +}; + +template class CCommandBufferBuilder +{ +public: + S m_Storage; + + FORCEINLINE void End( void ) + { + m_Storage.PutInt( CBCMD_END ); + } + + + FORCEINLINE IMaterialVar *Param( int nVar ) const + { + return CBaseShader::s_ppParams[nVar]; + } + + FORCEINLINE void SetPixelShaderConstants( int nFirstConstant, int nConstants ) + { + m_Storage.PutInt( CBCMD_SET_PIXEL_SHADER_FLOAT_CONST ); + m_Storage.PutInt( nFirstConstant ); + m_Storage.PutInt( nConstants ); + } + + FORCEINLINE void OutputConstantData( float const *pSrcData ) + { + m_Storage.PutFloat( pSrcData[0] ); + m_Storage.PutFloat( pSrcData[1] ); + m_Storage.PutFloat( pSrcData[2] ); + m_Storage.PutFloat( pSrcData[3] ); + } + + FORCEINLINE void OutputConstantData4( float flVal0, float flVal1, float flVal2, float flVal3 ) + { + m_Storage.PutFloat( flVal0 ); + m_Storage.PutFloat( flVal1 ); + m_Storage.PutFloat( flVal2 ); + m_Storage.PutFloat( flVal3 ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, float const *pSrcData, int nNumConstantsToSet ) + { + SetPixelShaderConstants( nFirstConstant, nNumConstantsToSet ); + m_Storage.PutMemory( pSrcData, 4 * sizeof( float ) * nNumConstantsToSet ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, int nVar ) + { + SetPixelShaderConstant( nFirstConstant, Param( nVar )->GetVecValue() ); + } + + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ) + { + float val[4]; + Param(constantVar)->GetVecValue( val, 3 ); + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + val[3] = 1.0; + SetPixelShaderConstant( pixelReg, val ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, float const *pSrcData ) + { + SetPixelShaderConstants( nFirstConstant, 1 ); + OutputConstantData( pSrcData ); + } + + FORCEINLINE void SetPixelShaderConstant4( int nFirstConstant, float flVal0, float flVal1, float flVal2, float flVal3 ) + { + SetPixelShaderConstants( nFirstConstant, 1 ); + OutputConstantData4( flVal0, flVal1, flVal2, flVal3 ); + } + + FORCEINLINE void SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ) + { + if ( constantVar != -1 ) + { + float val[3]; + Param(constantVar)->GetVecValue( val, 3); + SetPixelShaderConstant4( pixelReg, val[0], val[1], val[2], fWValue ); + } + } + + FORCEINLINE void SetVertexShaderConstant( int nFirstConstant, float const *pSrcData ) + { + m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + m_Storage.PutInt( nFirstConstant ); + m_Storage.PutInt( 1 ); + OutputConstantData( pSrcData ); + } + + FORCEINLINE void SetVertexShaderConstant( int nFirstConstant, float const *pSrcData, int nConsts ) + { + m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + m_Storage.PutInt( nFirstConstant ); + m_Storage.PutInt( nConsts ); + m_Storage.PutMemory( pSrcData, 4 * nConsts * sizeof( float ) ); + } + + + FORCEINLINE void SetVertexShaderConstant4( int nFirstConstant, float flVal0, float flVal1, float flVal2, float flVal3 ) + { + m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + m_Storage.PutInt( nFirstConstant ); + m_Storage.PutInt( 1 ); + m_Storage.PutFloat( flVal0 ); + m_Storage.PutFloat( flVal1 ); + m_Storage.PutFloat( flVal2 ); + m_Storage.PutFloat( flVal3 ); + } + + void SetVertexShaderTextureTransform( int vertexReg, int transformVar ) + { + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = Param( transformVar ); + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); + } + + + void SetVertexShaderTextureScaledTransform( int vertexReg, int transformVar, int scaleVar ) + { + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = Param( transformVar ); + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = Param( scaleVar ); + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); + } + + FORCEINLINE void SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar ) + { + if( g_pConfig->bShowSpecular && my_mat_fullbright.GetInt() != 2 ) + { + SetPixelShaderConstant( pixelReg, Param( tintVar)->GetVecValue() ); + } + else + { + SetPixelShaderConstant4( pixelReg, 0.0, 0.0, 0.0, 0.0 ); + } + } + + FORCEINLINE void SetEnvMapTintPixelShaderDynamicStateGammaToLinear( int pixelReg, int tintVar, float flAlphaValue = 1.0 ) + { + if( ( tintVar != -1 ) && g_pConfig->bShowSpecular && my_mat_fullbright.GetInt() != 2 ) + { + float color[4]; + color[3] = flAlphaValue; + Param( tintVar)->GetLinearVecValue( color, 3 ); + SetPixelShaderConstant( pixelReg, color ); + } + else + { + SetPixelShaderConstant4( pixelReg, 0.0, 0.0, 0.0, flAlphaValue ); + } + } + + FORCEINLINE void StoreEyePosInPixelShaderConstant( int nConst ) + { + m_Storage.PutInt( CBCMD_STORE_EYE_POS_IN_PSCONST ); + m_Storage.PutInt( nConst ); + } + + FORCEINLINE void CommitPixelShaderLighting( int nConst ) + { + m_Storage.PutInt( CBCMD_COMMITPIXELSHADERLIGHTING ); + m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetPixelShaderStateAmbientLightCube( int nConst ) + { + m_Storage.PutInt( CBCMD_SETPIXELSHADERSTATEAMBIENTLIGHTCUBE ); + m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetAmbientCubeDynamicStateVertexShader( void ) + { + m_Storage.PutInt( CBCMD_SETAMBIENTCUBEDYNAMICSTATEVERTEXSHADER ); + } + + FORCEINLINE void SetPixelShaderFogParams( int nReg ) + { + m_Storage.PutInt( CBCMD_SETPIXELSHADERFOGPARAMS ); + m_Storage.PutInt( nReg ); + } + + FORCEINLINE void BindStandardTexture( Sampler_t nSampler, StandardTextureId_t nTextureId ) + { + m_Storage.PutInt( CBCMD_BIND_STANDARD_TEXTURE ); + m_Storage.PutInt( nSampler ); + m_Storage.PutInt( nTextureId ); + } + + + FORCEINLINE void BindTexture( Sampler_t nSampler, ShaderAPITextureHandle_t hTexture ) + { + Assert( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE ); + if ( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE ) + { + m_Storage.PutInt( CBCMD_BIND_SHADERAPI_TEXTURE_HANDLE ); + m_Storage.PutInt( nSampler ); + m_Storage.PutInt( hTexture ); + } + } + + FORCEINLINE void BindTexture( CBaseVSShader *pShader, Sampler_t nSampler, int nTextureVar, int nFrameVar ) + { + ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar ); + BindTexture( nSampler, hTexture ); + } + + FORCEINLINE void BindMultiTexture( CBaseVSShader *pShader, Sampler_t nSampler1, Sampler_t nSampler2, int nTextureVar, int nFrameVar ) + { + ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar, 0 ); + BindTexture( nSampler1, hTexture ); + hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar, 1 ); + BindTexture( nSampler2, hTexture ); + } + + FORCEINLINE void SetPixelShaderIndex( int nIndex ) + { + m_Storage.PutInt( CBCMD_SET_PSHINDEX ); + m_Storage.PutInt( nIndex ); + } + + FORCEINLINE void SetVertexShaderIndex( int nIndex ) + { + m_Storage.PutInt( CBCMD_SET_VSHINDEX ); + m_Storage.PutInt( nIndex ); + } + + FORCEINLINE void SetDepthFeatheringPixelShaderConstant( int iConstant, float fDepthBlendScale ) + { + m_Storage.PutInt( CBCMD_SET_DEPTH_FEATHERING_CONST ); + m_Storage.PutInt( iConstant ); + m_Storage.PutFloat( fDepthBlendScale ); + } + + FORCEINLINE void Goto( uint8 *pCmdBuf ) + { + m_Storage.PutInt( CBCMD_JUMP ); + m_Storage.PutPtr( pCmdBuf ); + } + + FORCEINLINE void Call( uint8 *pCmdBuf ) + { + m_Storage.PutInt( CBCMD_JSR ); + m_Storage.PutPtr( pCmdBuf ); + } + + FORCEINLINE void Reset( void ) + { + m_Storage.Reset(); + } + + FORCEINLINE size_t Size( void ) const + { + return m_Storage.Size(); + } + + FORCEINLINE uint8 *Base( void ) + { + return m_Storage.Base(); + } + + + +}; + + +#endif // commandbuilder_h diff --git a/mp/src/materialsystem/stdshaders/common_flashlight_fxc.h b/mp/src/materialsystem/stdshaders/common_flashlight_fxc.h new file mode 100644 index 00000000..f9256a59 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_flashlight_fxc.h @@ -0,0 +1,821 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Common pixel shader code specific to flashlights +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_FLASHLIGHT_FXC_H_ +#define COMMON_FLASHLIGHT_FXC_H_ + +#include "common_ps_fxc.h" + + +// JasonM - TODO: remove this simpleton version +float DoShadow( sampler DepthSampler, float4 texCoord ) +{ + const float g_flShadowBias = 0.0005f; + float2 uoffset = float2( 0.5f/512.f, 0.0f ); + float2 voffset = float2( 0.0f, 0.5f/512.f ); + float3 projTexCoord = texCoord.xyz / texCoord.w; + float4 flashlightDepth = float4( tex2D( DepthSampler, projTexCoord + uoffset + voffset ).x, + tex2D( DepthSampler, projTexCoord + uoffset - voffset ).x, + tex2D( DepthSampler, projTexCoord - uoffset + voffset ).x, + tex2D( DepthSampler, projTexCoord - uoffset - voffset ).x ); + +# if ( defined( REVERSE_DEPTH_ON_X360 ) ) + { + flashlightDepth = 1.0f - flashlightDepth; + } +# endif + + float shadowed = 0.0f; + float z = texCoord.z/texCoord.w; + float4 dz = float4(z,z,z,z) - (flashlightDepth + float4( g_flShadowBias, g_flShadowBias, g_flShadowBias, g_flShadowBias)); + float4 shadow = float4(0.25f,0.25f,0.25f,0.25f); + + if( dz.x <= 0.0f ) + shadowed += shadow.x; + if( dz.y <= 0.0f ) + shadowed += shadow.y; + if( dz.z <= 0.0f ) + shadowed += shadow.z; + if( dz.w <= 0.0f ) + shadowed += shadow.w; + + return shadowed; +} + + +float DoShadowNvidiaRAWZOneTap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float fDepth = dot(tex2D(DepthSampler, shadowMapCenter).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + + return fDepth > objDepth; +} + + +float DoShadowNvidiaRAWZ( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fE = 1.0f / 512.0f; // Epsilon + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vDepths; + vDepths.x = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.y = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.z = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.w = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + + return dot(vDepths > objDepth.xxxx, float4(0.25, 0.25, 0.25, 0.25)); +} + + +float DoShadowNvidiaCheap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fTexelEpsilon = 1.0f / 1024.0f; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vTaps; + vTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x; + + return dot(vTaps, float4(0.25, 0.25, 0.25, 0.25)); +} + +float DoShadowNvidiaPCF3x3Box( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fTexelEpsilon = 1.0f / 1024.0f; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vOneTaps; + vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x; + float flOneTaps = dot( vOneTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f)); + + float4 vTwoTaps; + vTwoTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, 0 ), objDepth, 1 ) ).x; + vTwoTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, 0 ), objDepth, 1 ) ).x; + vTwoTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x; + vTwoTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x; + float flTwoTaps = dot( vTwoTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f)); + + float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (1.0f / 9.0f); + + // Sum all 9 Taps + return flOneTaps + flTwoTaps + flCenterTap; +} + + +// +// 1 4 7 4 1 +// 4 20 33 20 4 +// 7 33 55 33 7 +// 4 20 33 20 4 +// 1 4 7 4 1 +// +float DoShadowNvidiaPCF5x5Gaussian( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fEpsilon = 1.0f / 512.0f; + float fTwoEpsilon = 2.0f * fEpsilon; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vOneTaps; + vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + float flOneTaps = dot( vOneTaps, float4(1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f)); + + float4 vSevenTaps; + vSevenTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, 0 ), objDepth, 1 ) ).x; + vSevenTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, 0 ), objDepth, 1 ) ).x; + vSevenTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x; + vSevenTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x; + float flSevenTaps = dot( vSevenTaps, float4( 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f ) ); + + float4 vFourTapsA, vFourTapsB; + vFourTapsA.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + float flFourTapsA = dot( vFourTapsA, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) ); + float flFourTapsB = dot( vFourTapsB, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) ); + + float4 v20Taps; + v20Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fEpsilon ), objDepth, 1 ) ).x; + v20Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fEpsilon ), objDepth, 1 ) ).x; + v20Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + v20Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + float fl20Taps = dot( v20Taps, float4(20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f)); + + float4 v33Taps; + v33Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, 0 ), objDepth, 1 ) ).x; + v33Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, 0 ), objDepth, 1 ) ).x; + v33Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x; + v33Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x; + float fl33Taps = dot( v33Taps, float4(33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f)); + + float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (55.0f / 331.0f); + + // Sum all 25 Taps + return flOneTaps + flSevenTaps + +flFourTapsA + flFourTapsB + fl20Taps + fl33Taps + flCenterTap; +} + + +float DoShadowATICheap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float2 shadowMapCenter = shadowMapPos.xy/shadowMapPos.w; + float objDepth = shadowMapPos.z / shadowMapPos.w; + float fSampleDepth = tex2D( DepthSampler, shadowMapCenter ).x; + + objDepth = min( objDepth, 0.99999 ); //HACKHACK: On 360, surfaces at or past the far flashlight plane have an abrupt cutoff. This is temp until a smooth falloff is implemented + + return fSampleDepth > objDepth; +} + + +// Poisson disc, randomly rotated at different UVs +float DoShadowPoisson16Sample( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks, bool bNvidiaHardwarePCF, bool bFetch4 ) +{ + float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), + float2( 0.8806f, 0.3430f ), + float2( -0.0041f, -0.6197f ), + float2( 0.0472f, 0.4964f ), + float2( -0.3730f, 0.0874f ), + float2( -0.9217f, -0.3177f ), + float2( -0.6289f, 0.7388f ), + float2( 0.5744f, -0.7741f ) }; + + float flScaleOverMapSize = vShadowTweaks.x * 2; // Tweak parameters to shader + float2 vNoiseOffset = vShadowTweaks.zw; + float4 vLightDepths = 0, accum = 0.0f; + float2 rotOffset = 0; + + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + + // 2D Rotation Matrix setup + float3 RMatTop = 0, RMatBottom = 0; +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5) + vNoiseOffset) * 2.0 - 1.0; + RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple +#endif + + RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution + RMatBottom *= flScaleOverMapSize; + + RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below + RMatBottom.z = shadowMapCenter.y; + + float fResult = 0.0f; + + if ( bNvidiaHardwarePCF ) + { + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z; + vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z; + vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z; + vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z; + vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z; + vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z; + vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z; + vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z; + vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + fResult = dot( vLightDepths, float4( 0.25, 0.25, 0.25, 0.25) ); + } + else if ( bFetch4 ) + { +/* + +TODO: Fix this contact hardening stuff + + float flNumCloserSamples = 1; + float flAccumulatedCloserSamples = objDepth; + float4 vBlockerDepths; + + // First, search for blockers + for( int j=0; j<8; j++ ) + { + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[j].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[j].xy) + RMatBottom.z; + vBlockerDepths = tex2D( DepthSampler, rotOffset.xy ); + + // Which samples are closer than the pixel we're rendering? + float4 vCloserSamples = (vBlockerDepths < objDepth.xxxx ); // Binary comparison results + flNumCloserSamples += dot( vCloserSamples, float4(1, 1, 1, 1) ); // How many samples are closer than receiver? + flAccumulatedCloserSamples += dot (vCloserSamples, vBlockerDepths ); // Total depths from samples closer than receiver + } + + float flBlockerDepth = flAccumulatedCloserSamples / flNumCloserSamples; + float flContactHardeningScale = (objDepth - flBlockerDepth) / flBlockerDepth; + + // Scale the kernel + RMatTop.xy *= flContactHardeningScale; + RMatBottom.xy *= flContactHardeningScale; +*/ + + for( int i=0; i<8; i++ ) + { + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[i].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[i].xy) + RMatBottom.z; + vLightDepths = tex2D( DepthSampler, rotOffset.xy ); + accum += (vLightDepths > objDepth.xxxx); + } + + fResult = dot( accum, float4( 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f) ); + } + else // ATI vanilla hardware shadow mapping + { + for( int i=0; i<2; i++ ) + { + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+0].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+0].xy) + RMatBottom.z; + vLightDepths.x = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+1].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+1].xy) + RMatBottom.z; + vLightDepths.y = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+2].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+2].xy) + RMatBottom.z; + vLightDepths.z = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+3].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+3].xy) + RMatBottom.z; + vLightDepths.w = tex2D( DepthSampler, rotOffset.xy ).x; + + accum += (vLightDepths > objDepth.xxxx); + } + + fResult = dot( accum, float4( 0.125, 0.125, 0.125, 0.125) ); + } + + return fResult; +} + +#if defined( _X360 ) + +// Poisson disc, randomly rotated at different UVs +float DoShadow360Simple( sampler DepthSampler, const float3 vProjCoords ) +{ + float fLOD; + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + +#if defined( REVERSE_DEPTH_ON_X360 ) + objDepth = 1.0f - objDepth; +#endif + + float4 vSampledDepths, vWeights; + + asm { + getCompTexLOD2D fLOD.x, shadowMapCenter.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + getWeights2D vWeights, shadowMapCenter.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true + }; + + vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y ); + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, vWeights ); +} + + +float Do360PCFFetch( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepths, vWeights; + + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + getWeights2D vWeights, tc.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true + }; + + vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y ); + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, vWeights ); +} + + + +float Do360NearestFetch( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepth; + + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepth.x___, tc, DepthSampler, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + return (vSampledDepth.x < objDepth.x); +#else + return (vSampledDepth.x > objDepth.x); +#endif + +} + + +float AmountShadowed_8Tap_360( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepthsA, vSampledDepthsB; + + // Optimal 8 rooks pattern to get an idea about whether we're at a penumbra or not + // From [Kallio07] "Scanline Edge-Flag Algorithm for Antialiasing" + // + // +---+---+---+---+---+---+---+---+ + // | | | | | | o | | | + // +---+---+---+---+---+---+---+---+ + // | o | | | | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | o | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | | | o | | + // +---+---+---+---+---+---+---+---+ + // | | o | | | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | o | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | | | | o | + // +---+---+---+---+---+---+---+---+ + // | | | o | | | | | | + // +---+---+---+---+---+---+---+---+ + // + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepthsA.x___, tc, DepthSampler, OffsetX = -2.0, OffsetY = -1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA._x__, tc, DepthSampler, OffsetX = -1.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA.__x_, tc, DepthSampler, OffsetX = -1.0, OffsetY = 2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA.___x, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + tfetch2D vSampledDepthsB.x___, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB._x__, tc, DepthSampler, OffsetX = 1.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB.__x_, tc, DepthSampler, OffsetX = 1.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB.___x, tc, DepthSampler, OffsetX = 2.0, OffsetY = 1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompareA = (vSampledDepthsA < objDepth.xxxx); + float4 vCompareB = (vSampledDepthsB < objDepth.xxxx); +#else + float4 vCompareA = (vSampledDepthsA > objDepth.xxxx); + float4 vCompareB = (vSampledDepthsB > objDepth.xxxx); +#endif + + return dot( vCompareA, float4(0.125,0.125,0.125,0.125) ) + dot( vCompareB, float4(0.125,0.125,0.125,0.125) ); +} + + +float AmountShadowed_4Tap_360( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepths; + + // Rotated grid pattern to get an idea about whether we're at a penumbra or not + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -1.0, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 1.0, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, float4(0.25,0.25,0.25,0.25) ); +} + +// Poisson disc, randomly rotated at different UVs +float DoShadowPoisson360( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks ) +{ + float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ), + float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ), + float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ), + float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) }; + + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + +#if defined( REVERSE_DEPTH_ON_X360 ) + objDepth = 1.0f - objDepth; +#endif + + float fAmountShadowed = AmountShadowed_4Tap_360( DepthSampler, shadowMapCenter, objDepth ); + + if ( fAmountShadowed >= 1.0f ) // Fully in light + { + return 1.0f; + } + else // Do the expensive filtering since we're at least partially shadowed + { + float flScaleOverMapSize = 1.7f / 512.0f; // Tweak parameters to shader + + // 2D Rotation Matrix setup + float3 RMatTop = 0, RMatBottom = 0; +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5)) * 2.0 - 1.0; + RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple +#endif + + RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution + RMatBottom *= flScaleOverMapSize; + RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below + RMatBottom.z = shadowMapCenter.y; + float2 rotOffset = float2(0,0); + float4 vAccum = 0; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z; + vAccum.x = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z; + vAccum.y = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z; + vAccum.z = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z; + vAccum.w = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z; + vAccum.x += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z; + vAccum.y += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z; + vAccum.z += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z; + vAccum.w += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + return dot( vAccum, float4( 0.25, 0.25, 0.25, 0.25) ); + } +} + +#endif // _X360 + + +float DoFlashlightShadow( sampler DepthSampler, sampler RandomRotationSampler, float3 vProjCoords, float2 vScreenPos, int nShadowLevel, float4 vShadowTweaks, bool bAllowHighQuality ) +{ + float flShadow = 1.0f; + +#if !defined( _X360 ) //PC + if( nShadowLevel == NVIDIA_PCF_POISSON ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, true, false ); + else if( nShadowLevel == ATI_NOPCF ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, false ); + else if( nShadowLevel == ATI_NO_PCF_FETCH4 ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, true ); + + return flShadow; +#else + + // Compile-time switch for shaders which allow high quality modes on 360 + if ( bAllowHighQuality ) + { + // Static control flow switch for shadow quality. Some non-interactive sequences use the high quality path + if ( g_bHighQualityShadows ) + { + flShadow = DoShadowPoisson360( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks ); + } + else + { + flShadow = DoShadow360Simple( DepthSampler, vProjCoords ); + } + } + else + { + flShadow = DoShadow360Simple( DepthSampler, vProjCoords ); + } + + return flShadow; + +#endif +} + +float3 SpecularLight( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent, + const float3 vEyeDir, const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel ) +{ + float3 result = float3(0.0f, 0.0f, 0.0f); + + //float3 vReflect = reflect( -vEyeDir, vWorldNormal ); + float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal + float3 vSpecular = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?) + vSpecular = pow( vSpecular.x, fSpecularExponent ); // Raise to specular power + + // Optionally warp as function of scalar specular and fresnel + if ( bDoSpecularWarp ) + vSpecular *= tex2D( specularWarpSampler, float2(vSpecular.x, fFresnel) ); // Sample at { (L.R)^k, fresnel } + + return vSpecular; +} + +void DoSpecularFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, + float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, sampler RandomRotationSampler, + int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, const float2 vScreenPos, const float fSpecularExponent, const float3 vEyeDir, + const bool bDoSpecularWarp, sampler specularWarpSampler, float fFresnel, float4 vShadowTweaks, + + // Outputs of this shader...separate shadowed diffuse and specular from the flashlight + out float3 diffuseLighting, out float3 specularLighting ) +{ + float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w; + float3 flashlightColor = float3(1,1,1); + +#if ( defined( _X360 ) ) + + float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f ); + float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f ); + + [branch] + if ( dot(ltz + gto, float3(1,1,1)) > 0 ) + { + clip(-1); + diffuseLighting = specularLighting = float3(0,0,0); + return; + } + else + { + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); + + [branch] + if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 ) + { + clip(-1); + diffuseLighting = specularLighting = float3(0,0,0); + return; + } + } +#else + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); +#endif + + +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + flashlightColor *= cFlashlightColor.xyz; // Flashlight color +#endif + + float3 delta = flashlightPos - worldPos; + float3 L = normalize( delta ); + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + + float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + + // Attenuation for light and to fade out shadow over distance + float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + + // Shadowing and coloring terms +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + if ( bDoShadows ) + { + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality ); + float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation + flashlightColor *= flShadow; // Shadow term + } +#endif + + diffuseLighting = fAtten; +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) + flFlashlightNoLambertValue ); // Lambertian term +#else + diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) ); // Lambertian (not Half-Lambert) term +#endif + diffuseLighting *= flashlightColor; + diffuseLighting *= endFalloffFactor; + + // Specular term (masked by diffuse) + specularLighting = diffuseLighting * SpecularLight ( worldNormal, L, fSpecularExponent, vEyeDir, bDoSpecularWarp, specularWarpSampler, fFresnel ); +} + +// Diffuse only version +float3 DoFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, + float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, + sampler RandomRotationSampler, int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, + const float2 vScreenPos, bool bClip, float4 vShadowTweaks = float4(3/1024.0f, 0.0005f, 0.0f, 0.0f), bool bHasNormal = true ) +{ + float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w; + float3 flashlightColor = float3(1,1,1); + +#if ( defined( _X360 ) ) + + float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f ); + float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f ); + + [branch] + if ( dot(ltz + gto, float3(1,1,1)) > 0 ) + { + if ( bClip ) + { + clip(-1); + } + return float3(0,0,0); + } + else + { + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); + + [branch] + if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 ) + { + if ( bClip ) + { + clip(-1); + } + return float3(0,0,0); + } + } +#else + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); +#endif + +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + flashlightColor *= cFlashlightColor.xyz; // Flashlight color +#endif + + float3 delta = flashlightPos - worldPos; + float3 L = normalize( delta ); + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + + float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + + // Attenuation for light and to fade out shadow over distance + float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + + // Shadowing and coloring terms +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + if ( bDoShadows ) + { + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality ); + float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation + flashlightColor *= flShadow; // Shadow term + } +#endif + + float3 diffuseLighting = fAtten; + + float flLDotWorldNormal; + if ( bHasNormal ) + { + flLDotWorldNormal = dot( L.xyz, worldNormal.xyz ); + } + else + { + flLDotWorldNormal = 1.0f; + } + +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + diffuseLighting *= saturate( flLDotWorldNormal + flFlashlightNoLambertValue ); // Lambertian term +#else + diffuseLighting *= saturate( flLDotWorldNormal ); // Lambertian (not Half-Lambert) term +#endif + + diffuseLighting *= flashlightColor; + diffuseLighting *= endFalloffFactor; + + return diffuseLighting; +} + +#endif //#ifndef COMMON_FLASHLIGHT_FXC_H_ diff --git a/mp/src/materialsystem/stdshaders/common_fxc.h b/mp/src/materialsystem/stdshaders/common_fxc.h new file mode 100644 index 00000000..b81c9a46 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_fxc.h @@ -0,0 +1,326 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_FXC_H_ +#define COMMON_FXC_H_ + +#include "common_pragmas.h" +#include "common_hlsl_cpp_consts.h" + +#ifdef NV3X +# define HALF half +# define HALF2 half2 +# define HALF3 half3 +# define HALF4 half4 +# define HALF3x3 half3x3 +# define HALF3x4 half3x4 +# define HALF4x3 half4x3 +# define HALF_CONSTANT( _constant ) ((HALF)_constant) +#else +# define HALF float +# define HALF2 float2 +# define HALF3 float3 +# define HALF4 float4 +# define HALF3x3 float3x3 +# define HALF3x4 float3x4 +# define HALF4x3 float4x3 +# define HALF_CONSTANT( _constant ) _constant +#endif + +// This is where all common code for both vertex and pixel shaders. +#define OO_SQRT_3 0.57735025882720947f +static const HALF3 bumpBasis[3] = { + HALF3( 0.81649661064147949f, 0.0f, OO_SQRT_3 ), + HALF3( -0.40824833512306213f, 0.70710676908493042f, OO_SQRT_3 ), + HALF3( -0.40824821591377258f, -0.7071068286895752f, OO_SQRT_3 ) +}; +static const HALF3 bumpBasisTranspose[3] = { + HALF3( 0.81649661064147949f, -0.40824833512306213f, -0.40824833512306213f ), + HALF3( 0.0f, 0.70710676908493042f, -0.7071068286895752f ), + HALF3( OO_SQRT_3, OO_SQRT_3, OO_SQRT_3 ) +}; + +#if defined( _X360 ) +#define REVERSE_DEPTH_ON_X360 //uncomment to use D3DFMT_D24FS8 with an inverted depth viewport for better performance. Keep this in sync with the same named #define in public/shaderapi/shareddefs.h +//Note that the reversal happens in the viewport. So ONLY reading back from a depth texture should be affected. Projected math is unaffected. +#endif + +HALF3 CalcReflectionVectorNormalized( HALF3 normal, HALF3 eyeVector ) +{ + // FIXME: might be better of normalizing with a normalizing cube map and + // get rid of the dot( normal, normal ) + // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v + return 2.0 * ( dot( normal, eyeVector ) / dot( normal, normal ) ) * normal - eyeVector; +} + +HALF3 CalcReflectionVectorUnnormalized( HALF3 normal, HALF3 eyeVector ) +{ + // FIXME: might be better of normalizing with a normalizing cube map and + // get rid of the dot( normal, normal ) + // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v + // multiply all values through by N.N. uniformly scaling reflection vector won't affect result + // since it is used in a cubemap lookup + return (2.0*(dot( normal, eyeVector ))*normal) - (dot( normal, normal )*eyeVector); +} + +float3 HuePreservingColorClamp( float3 c ) +{ + // Get the max of all of the color components and a specified maximum amount + float maximum = max( max( c.x, c.y ), max( c.z, 1.0f ) ); + + return (c / maximum); +} + +HALF3 HuePreservingColorClamp( HALF3 c, HALF maxVal ) +{ + // Get the max of all of the color components and a specified maximum amount + float maximum = max( max( c.x, c.y ), max( c.z, maxVal ) ); + return (c * ( maxVal / maximum ) ); +} + +#if (AA_CLAMP==1) +HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) +{ + HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99; + result += Lightmap3Coord; + return result; +} + +void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord, + out HALF2 bumpCoord1, + out HALF2 bumpCoord2, + out HALF2 bumpCoord3 ) +{ + HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99; + result += Lightmap3Coord; + bumpCoord1 = result + HALF2(Lightmap1and2Coord.z, 0); + bumpCoord2 = result + 2*HALF2(Lightmap1and2Coord.z, 0); + bumpCoord3 = result + 3*HALF2(Lightmap1and2Coord.z, 0); +} +#else +HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) +{ + return Lightmap1and2Coord.xy; +} + +void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord, + out HALF2 bumpCoord1, + out HALF2 bumpCoord2, + out HALF2 bumpCoord3 ) +{ + bumpCoord1 = Lightmap1and2Coord.xy; + bumpCoord2 = Lightmap1and2Coord.wz; // reversed order!!! + bumpCoord3 = Lightmap3Coord.xy; +} +#endif + +// Versions of matrix multiply functions which force HLSL compiler to explictly use DOTs, +// not giving it the option of using MAD expansion. In a perfect world, the compiler would +// always pick the best strategy, and these shouldn't be needed.. but.. well.. umm.. +// +// lorenmcq + +float3 mul3x3(float3 v, float3x3 m) +{ +#if !defined( _X360 ) + return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2])); +#else + // xbox360 fxc.exe (new back end) borks with transposes, generates bad code + return mul( v, m ); +#endif +} + +float3 mul4x3(float4 v, float4x3 m) +{ +#if !defined( _X360 ) + return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2])); +#else + // xbox360 fxc.exe (new back end) borks with transposes, generates bad code + return mul( v, m ); +#endif +} + +float3 DecompressHDR( float4 input ) +{ + return input.rgb * input.a * MAX_HDR_OVERBRIGHT; +} + +float4 CompressHDR( float3 input ) +{ + // FIXME: want to use min so that we clamp to white, but what happens if we + // have an albedo component that's less than 1/MAX_HDR_OVERBRIGHT? + // float fMax = max( max( color.r, color.g ), color.b ); + float4 output; + float fMax = min( min( input.r, input.g ), input.b ); + if( fMax > 1.0f ) + { + float oofMax = 1.0f / fMax; + output.rgb = oofMax * input.rgb; + output.a = min( fMax / MAX_HDR_OVERBRIGHT, 1.0f ); + } + else + { + output.rgb = input.rgb; + output.a = 0.0f; + } + return output; +} + + +float3 LinearToGamma( const float3 f3linear ) +{ + return pow( f3linear, 1.0f / 2.2f ); +} + +float4 LinearToGamma( const float4 f4linear ) +{ + return float4( pow( f4linear.xyz, 1.0f / 2.2f ), f4linear.w ); +} + +float LinearToGamma( const float f1linear ) +{ + return pow( f1linear, 1.0f / 2.2f ); +} + +float3 GammaToLinear( const float3 gamma ) +{ + return pow( gamma, 2.2f ); +} + +float4 GammaToLinear( const float4 gamma ) +{ + return float4( pow( gamma.xyz, 2.2f ), gamma.w ); +} + +float GammaToLinear( const float gamma ) +{ + return pow( gamma, 2.2f ); +} + +// These two functions use the actual sRGB math +float SrgbGammaToLinear( float flSrgbGammaValue ) +{ + float x = saturate( flSrgbGammaValue ); + return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) ); +} + +float SrgbLinearToGamma( float flLinearValue ) +{ + float x = saturate( flLinearValue ); + return ( x <= 0.0031308f ) ? ( x * 12.92f ) : ( 1.055f * pow( x, ( 1.0f / 2.4f ) ) ) - 0.055f; +} + +// These twofunctions use the XBox 360's exact piecewise linear algorithm +float X360GammaToLinear( float fl360GammaValue ) +{ + float flLinearValue; + + fl360GammaValue = saturate( fl360GammaValue ); + if ( fl360GammaValue < ( 96.0f / 255.0f ) ) + { + if ( fl360GammaValue < ( 64.0f / 255.0f ) ) + { + flLinearValue = fl360GammaValue * 255.0f; + } + else + { + flLinearValue = fl360GammaValue * ( 255.0f * 2.0f ) - 64.0f; + flLinearValue += floor( flLinearValue * ( 1.0f / 512.0f ) ); + } + } + else + { + if( fl360GammaValue < ( 192.0f / 255.0f ) ) + { + flLinearValue = fl360GammaValue * ( 255.0f * 4.0f ) - 256.0f; + flLinearValue += floor( flLinearValue * ( 1.0f / 256.0f ) ); + } + else + { + flLinearValue = fl360GammaValue * ( 255.0f * 8.0f ) - 1024.0f; + flLinearValue += floor( flLinearValue * ( 1.0f / 128.0f ) ); + } + } + + flLinearValue *= 1.0f / 1023.0f; + + flLinearValue = saturate( flLinearValue ); + return flLinearValue; +} + +float X360LinearToGamma( float flLinearValue ) +{ + float fl360GammaValue; + + flLinearValue = saturate( flLinearValue ); + if ( flLinearValue < ( 128.0f / 1023.0f ) ) + { + if ( flLinearValue < ( 64.0f / 1023.0f ) ) + { + fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) ); + } + else + { + fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f ); + } + } + else + { + if ( flLinearValue < ( 512.0f / 1023.0f ) ) + { + fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f ); + } + else + { + fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016 + if ( fl360GammaValue > 1.0f ) + { + fl360GammaValue = 1.0f; + } + } + } + + fl360GammaValue = saturate( fl360GammaValue ); + return fl360GammaValue; +} + +float SrgbGammaTo360Gamma( float flSrgbGammaValue ) +{ + float flLinearValue = SrgbGammaToLinear( flSrgbGammaValue ); + float fl360GammaValue = X360LinearToGamma( flLinearValue ); + return fl360GammaValue; +} + +float3 Vec3WorldToTangent( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + float3 vTangentVector; + vTangentVector.x = dot( iWorldVector.xyz, iWorldTangent.xyz ); + vTangentVector.y = dot( iWorldVector.xyz, iWorldBinormal.xyz ); + vTangentVector.z = dot( iWorldVector.xyz, iWorldNormal.xyz ); + return vTangentVector.xyz; // Return without normalizing +} + +float3 Vec3WorldToTangentNormalized( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + return normalize( Vec3WorldToTangent( iWorldVector, iWorldNormal, iWorldTangent, iWorldBinormal ) ); +} + +float3 Vec3TangentToWorld( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + float3 vWorldVector; + vWorldVector.xyz = iTangentVector.x * iWorldTangent.xyz; + vWorldVector.xyz += iTangentVector.y * iWorldBinormal.xyz; + vWorldVector.xyz += iTangentVector.z * iWorldNormal.xyz; + return vWorldVector.xyz; // Return without normalizing +} + +float3 Vec3TangentToWorldNormalized( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + return normalize( Vec3TangentToWorld( iTangentVector, iWorldNormal, iWorldTangent, iWorldBinormal ) ); +} + +#endif //#ifndef COMMON_FXC_H_ diff --git a/mp/src/materialsystem/stdshaders/common_fxc2.h b/mp/src/materialsystem/stdshaders/common_fxc2.h new file mode 100644 index 00000000..7ee8b48c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_fxc2.h @@ -0,0 +1,19 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_FXC2_H_ +#define COMMON_FXC2_H_ + +// This file is here so you can add new utility functions without +// changing common_fxc.h and causing a recompile of the entire universe. + +float LinearToMonochrome ( float3 r ) +{ + return dot( r, float3( 0.299f, 0.587f, 0.114f ) ); +} + +#endif //#ifndef COMMON_FXC2_H_ diff --git a/mp/src/materialsystem/stdshaders/common_hlsl_cpp_consts.h b/mp/src/materialsystem/stdshaders/common_hlsl_cpp_consts.h new file mode 100644 index 00000000..523feee4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_hlsl_cpp_consts.h @@ -0,0 +1,27 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_HLSL_CONSTS_H_ +#define COMMON_HLSL_CONSTS_H_ + +#ifdef NV3X + #define PSHADER_VECT_SCALE 20.0 + #define VSHADER_VECT_SCALE (1.0 / (PSHADER_VECT_SCALE) ) +#else + #define PSHADER_VECT_SCALE 1.0 + #define VSHADER_VECT_SCALE 1.0 +#endif + +// GR - HDR luminance maps to 0..n range +// IMPORTANT: Keep the same value as in materialsystem_global.h +// HDRFIXME: Make this a pixel shader constant? +#define MAX_HDR_OVERBRIGHT 16.0f + +#define LINEAR_FOG_COLOR 29 +#define TONE_MAPPING_SCALE_PSH_CONSTANT 30 + +#endif //#ifndef COMMON_HLSL_CONSTS_H_ diff --git a/mp/src/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h b/mp/src/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h new file mode 100644 index 00000000..e82bdf65 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h @@ -0,0 +1,202 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + + +#if defined( _X360 ) + +void GetBaseTextureAndNormal( sampler base, sampler base2, sampler bump, bool bBase2, bool bBump, float3 coords, float3 vWeights, + out float4 vResultBase, out float4 vResultBase2, out float4 vResultBump ) +{ + vResultBase = 0; + vResultBase2 = 0; + vResultBump = 0; + + if ( !bBump ) + { + vResultBump = float4(0, 0, 1, 1); + } + +#if SEAMLESS + + vWeights = max( vWeights - 0.3, 0 ); + + vWeights *= 1.0f / dot( vWeights, float3(1,1,1) ); + + [branch] + if (vWeights.x > 0) + { + vResultBase += vWeights.x * tex2D( base, coords.zy ); + + if ( bBase2 ) + { + vResultBase2 += vWeights.x * tex2D( base2, coords.zy ); + } + + if ( bBump ) + { + vResultBump += vWeights.x * tex2D( bump, coords.zy ); + } + } + + [branch] + if (vWeights.y > 0) + { + vResultBase += vWeights.y * tex2D( base, coords.xz ); + + if ( bBase2 ) + { + vResultBase2 += vWeights.y * tex2D( base2, coords.xz ); + } + if ( bBump ) + { + vResultBump += vWeights.y * tex2D( bump, coords.xz ); + } + } + + [branch] + if (vWeights.z > 0) + { + vResultBase += vWeights.z * tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.z * tex2D( base2, coords.xy ); + } + + if ( bBump ) + { + vResultBump += vWeights.z * tex2D( bump, coords.xy ); + } + } + +#else // not seamless + + vResultBase = tex2D( base, coords.xy ); + + if ( bBase2 ) + { + vResultBase2 = tex2D( base2, coords.xy ); + } + + if ( bBump ) + { + vResultBump = tex2D( bump, coords.xy ); + } + +#endif + + +} + +#else // PC + +void GetBaseTextureAndNormal( sampler base, sampler base2, sampler bump, bool bBase2, bool bBump, float3 coords, float3 vWeights, + out float4 vResultBase, out float4 vResultBase2, out float4 vResultBump ) +{ + vResultBase = 0; + vResultBase2 = 0; + vResultBump = 0; + + if ( !bBump ) + { + vResultBump = float4(0, 0, 1, 1); + } + +#if SEAMLESS + + vResultBase += vWeights.x * tex2D( base, coords.zy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.x * tex2D( base2, coords.zy ); + } + if ( bBump ) + { + vResultBump += vWeights.x * tex2D( bump, coords.zy ); + } + + vResultBase += vWeights.y * tex2D( base, coords.xz ); + if ( bBase2 ) + { + vResultBase2 += vWeights.y * tex2D( base2, coords.xz ); + } + if ( bBump ) + { + vResultBump += vWeights.y * tex2D( bump, coords.xz ); + } + + vResultBase += vWeights.z * tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.z * tex2D( base2, coords.xy ); + } + if ( bBump ) + { + vResultBump += vWeights.z * tex2D( bump, coords.xy ); + } + +#else // not seamless + + vResultBase = tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 = tex2D( base2, coords.xy ); + } + if ( bBump ) + { + vResultBump = tex2D( bump, coords.xy ); + } +#endif + +} + +#endif + + + + +float3 LightMapSample( sampler LightmapSampler, float2 vTexCoord ) +{ +# if ( !defined( _X360 ) || !defined( USE_32BIT_LIGHTMAPS_ON_360 ) ) + { + float3 sample = tex2D( LightmapSampler, vTexCoord ); + + return sample; + } +# else + { +# if 0 //1 for cheap sampling, 0 for accurate scaling from the individual samples + { + float4 sample = tex2D( LightmapSampler, vTexCoord ); + + return sample.rgb * sample.a; + } +# else + { + float4 Weights; + float4 samples_0; //no arrays allowed in inline assembly + float4 samples_1; + float4 samples_2; + float4 samples_3; + + asm { + tfetch2D samples_0, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_1, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_2, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_3, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + + getWeights2D Weights, vTexCoord.xy, LightmapSampler + }; + + Weights = float4( (1-Weights.x)*(1-Weights.y), Weights.x*(1-Weights.y), (1-Weights.x)*Weights.y, Weights.x*Weights.y ); + + float3 result; + result.rgb = samples_0.rgb * (samples_0.a * Weights.x); + result.rgb += samples_1.rgb * (samples_1.a * Weights.y); + result.rgb += samples_2.rgb * (samples_2.a * Weights.z); + result.rgb += samples_3.rgb * (samples_3.a * Weights.w); + + return result; + } +# endif + } +# endif +} + diff --git a/mp/src/materialsystem/stdshaders/common_pragmas.h b/mp/src/materialsystem/stdshaders/common_pragmas.h new file mode 100644 index 00000000..50b61ff0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_pragmas.h @@ -0,0 +1,38 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Common shader compiler pragmas +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_PRAGMAS_H_ +#define COMMON_PRAGMAS_H_ + +// +// Validated shader models: +// +// SHADER_MODEL_VS_1_1 +// SHADER_MODEL_VS_2_0 +// SHADER_MODEL_VS_3_0 +// +// SHADER_MODEL_PS_1_1 +// SHADER_MODEL_PS_1_4 +// SHADER_MODEL_PS_2_0 +// SHADER_MODEL_PS_2_B +// SHADER_MODEL_PS_3_0 +// +// +// +// Platforms: +// +// PC +// _X360 +// + +// Special pragmas silencing common warnings +#pragma warning ( disable : 3557 ) // warning X3557: Loop only executes for N iteration(s), forcing loop to unroll +#pragma warning ( disable : 3595 ) // warning X3595: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused +#pragma warning ( disable : 3596 ) // warning X3596: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused +#pragma warning ( disable : 4702 ) // warning X4702: complement opportunity missed because input result WAS clamped from 0 to 1 + +#endif //#ifndef COMMON_PRAGMAS_H_ diff --git a/mp/src/materialsystem/stdshaders/common_ps_fxc.h b/mp/src/materialsystem/stdshaders/common_ps_fxc.h new file mode 100644 index 00000000..d4a47ea5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_ps_fxc.h @@ -0,0 +1,804 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Common pixel shader code +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_PS_FXC_H_ +#define COMMON_PS_FXC_H_ + +#include "common_fxc.h" + +// Put global skip commands here. . make sure and check that the appropriate vars are defined +// so these aren't used on the wrong shaders! + +// -------------------------------------------------------------------------------- +// HDR should never be enabled if we don't aren't running in float or integer HDR mode. +// SKIP: defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED +// -------------------------------------------------------------------------------- +// We don't ever write water fog to dest alpha if we aren't doing water fog. +// SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA +// -------------------------------------------------------------------------------- +// We don't need fog in the pixel shader if we aren't in float fog mode2 +// NOSKIP: defined $HDRTYPE && defined $HDRENABLED && defined $PIXELFOGTYPE && $HDRTYPE != HDR_TYPE_FLOAT && $FOGTYPE != 0 +// -------------------------------------------------------------------------------- +// We don't do HDR and LIGHTING_PREVIEW at the same time since it's running LDR in hammer. +// SKIP: defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0 +// -------------------------------------------------------------------------------- +// Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW. +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH +// -------------------------------------------------------------------------------- +// Ditch flashlight depth when flashlight is disabled +// SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW +// -------------------------------------------------------------------------------- + +// System defined pixel shader constants + +#if defined( _X360 ) +const bool g_bHighQualityShadows : register( b0 ); +#endif + +// NOTE: w == 1.0f / (Dest alpha compressed depth range). +const float4 g_LinearFogColor : register( c29 ); +#define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w) + +// Linear and gamma light scale values +const float4 cLightScale : register( c30 ); +#define LINEAR_LIGHT_SCALE (cLightScale.x) +#define LIGHT_MAP_SCALE (cLightScale.y) +#define ENV_MAP_SCALE (cLightScale.z) +#define GAMMA_LIGHT_SCALE (cLightScale.w) + +// Flashlight constants +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + const float4 cFlashlightColor : register( c28 ); + const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused + #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0 +#endif + +#define HDR_INPUT_MAP_SCALE 16.0f + +#define TONEMAP_SCALE_NONE 0 +#define TONEMAP_SCALE_LINEAR 1 +#define TONEMAP_SCALE_GAMMA 2 + +#define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader +#define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits) +#define PIXEL_FOG_TYPE_HEIGHT 1 + +// If you change these, make the corresponding change in hardwareconfig.cpp +#define NVIDIA_PCF_POISSON 0 +#define ATI_NOPCF 1 +#define ATI_NO_PCF_FETCH4 2 + +struct LPREVIEW_PS_OUT +{ + float4 color : COLOR0; + float4 normal : COLOR1; + float4 position : COLOR2; + float4 flags : COLOR3; +}; + +/* +// unused +HALF Luminance( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) ); +} +*/ + +/* +// unused +HALF LuminanceScaled( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) ); +} +*/ + +/* +// unused +HALF AvgColor( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) ); +} +*/ + +/* +// unused +HALF4 DiffuseBump( sampler lightmapSampler, + float2 lightmapTexCoord1, + float2 lightmapTexCoord2, + float2 lightmapTexCoord3, + HALF3 normal ) +{ + HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 ); + HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 ); + HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 ); + + HALF3 diffuseLighting; + diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 + + saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 + + saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3; + + return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) ); +} +*/ + + +/* +// unused +HALF Fresnel( HALF3 normal, + HALF3 eye, + HALF2 scaleBias ) +{ + HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye ); + fresnel = pow( fresnel, HALF_CONSTANT(5.0f) ); + + return fresnel * scaleBias.x + scaleBias.y; +} +*/ + +/* +// unused +HALF4 GetNormal( sampler normalSampler, + float2 normalTexCoord ) +{ + HALF4 normal = tex2D( normalSampler, normalTexCoord ); + normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f); + + return normal; +} +*/ + +// Needs to match NormalDecodeMode_t enum in imaterialsystem.h +#define NORM_DECODE_NONE 0 +#define NORM_DECODE_ATI2N 1 +#define NORM_DECODE_ATI2N_ALPHA 2 + +float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler ) +{ + float4 normalTexel = tex2D( NormalSampler, tc ); + float4 result; + + if ( nDecompressionMode == NORM_DECODE_NONE ) + { + result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a ); + } + else if ( nDecompressionMode == NORM_DECODE_ATI2N ) + { + result.xy = normalTexel.xy * 2.0f - 1.0f; + result.z = sqrt( 1.0f - dot(result.xy, result.xy) ); + result.a = 1.0f; + } + else // ATI2N plus ATI1N for alpha + { + result.xy = normalTexel.xy * 2.0f - 1.0f; + result.z = sqrt( 1.0f - dot(result.xy, result.xy) ); + result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel + } + + return result; +} + +float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode ) +{ + return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler ); +} + + +HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input ) +{ +// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f; + return texCUBE( normalizeSampler, input ); +} + +/* +HALF4 EnvReflect( sampler envmapSampler, + sampler normalizeSampler, + HALF3 normal, + float3 eye, + HALF2 fresnelScaleBias ) +{ + HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye ); + HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias ); + HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye ); + return texCUBE( envmapSampler, reflect ); +} +*/ + +float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange ) +{ +// float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp + float flDepthFromWater = flWaterZ - flWorldPosZ; + + // if flDepthFromWater < 0, then set it to 0 + // This is the equivalent of moving the vert to the water surface if it's above the water surface + // We'll do this with the saturate at the end instead. +// flDepthFromWater = max( 0.0f, flDepthFromWater ); + + // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer + // to the vert is actually underwater. + float flDepthFromEye = flEyePosZ - flWorldPosZ; + float f = saturate(flDepthFromWater * (1.0/flDepthFromEye)); + + // $tmp.w is now the distance that we see through water. + return saturate(f * flProjPosZ * flFogOORange); +} + +float CalcRangeFog( const float flProjPosZ, const float flFogStartOverRange, const float flFogMaxDensity, const float flFogOORange ) +{ +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + return saturate( min( flFogMaxDensity, (flProjPosZ * flFogOORange) - flFogStartOverRange ) ); +#else + return 0.0f; //ps20 shaders will never have range fog enabled because too many ran out of slots. +#endif +} + +float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float retVal; + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE ) + { + retVal = 0.0f; + } + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters + { + retVal = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w ); + } + else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog + { + retVal = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w ); + } + + return retVal; +} + +//g_FogParams not defined by default, but this is the same layout for every shader that does define it +#define g_FogEndOverRange g_FogParams.x +#define g_WaterZ g_FogParams.y +#define g_FogMaxDensity g_FogParams.z +#define g_FogOORange g_FogParams.w + +float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE ) +{ + if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b + { +# if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + pixelFogFactor = saturate( pixelFogFactor ); + return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog +# else + return vShaderColor; +# endif + } + else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) + { + return lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + } + else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE ) + { + return vShaderColor; + } +} + + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) && ( CONVERT_TO_SRGB != 0 ) ) +sampler1D GammaTableSampler : register( s15 ); + +float3 SRGBOutput( const float3 vShaderColor ) +{ + //On ps2b capable hardware we always have the linear->gamma conversion table texture in sampler s15. + float3 result; + result.r = tex1D( GammaTableSampler, vShaderColor.r ).r; + result.g = tex1D( GammaTableSampler, vShaderColor.g ).r; + result.b = tex1D( GammaTableSampler, vShaderColor.b ).r; + return result; +} + +#else + +float3 SRGBOutput( const float3 vShaderColor ) +{ + return vShaderColor; //ps 1.1, 1.4, and 2.0 never do srgb conversion in the pixel shader +} + +#endif + + +float SoftParticleDepth( float flDepth ) +{ + return flDepth * OO_DESTALPHA_DEPTH_RANGE; +} + + +float DepthToDestAlpha( const float flProjZ ) +{ +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + return SoftParticleDepth( flProjZ ); +#else + return 1.0f; +#endif +} + + +float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f ) +{ + float4 result; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE ) + { + result.rgb = vShaderColor.rgb; + } + + if( bWriteDepthToDestAlpha ) + result.a = DepthToDestAlpha( flProjZ ); + else + result.a = vShaderColor.a; + + result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE ); + +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion +#endif + + return result; +} + +LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE ) +{ + LPREVIEW_PS_OUT result; + result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE ); + result.normal.rgb = SRGBOutput( vShaderColor.normal.rgb ); + result.normal.a = vShaderColor.normal.a; + + result.position.rgb = SRGBOutput( vShaderColor.position.rgb ); + result.position.a = vShaderColor.position.a; + + result.flags.rgb = SRGBOutput( vShaderColor.flags.rgb ); + result.flags.a = vShaderColor.flags.a; + + return result; +} + + + + +float RemapValClamped( float val, float A, float B, float C, float D) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + + return C + (D - C) * cVal; +} + + +//===================================================================================// +// This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI) +//===================================================================================// +// INPUT: +// inTexCoord: +// the texcoord for the height/displacement map before parallaxing +// +// vParallax: +// Compute initial parallax displacement direction: +// float2 vParallaxDirection = normalize( vViewTS.xy ); +// float fLength = length( vViewTS ); +// float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z; +// Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight; +// +// vNormal: +// tangent space normal +// +// vViewW: +// float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition ); +// +// OUTPUT: +// the new texcoord after parallaxing +float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal, + float3 vViewW, sampler HeightMapSampler ) +{ + const int nMinSamples = 8; + const int nMaxSamples = 50; + + // Normalize the incoming view vector to avoid artifacts: +// vView = normalize( vView ); + vViewW = normalize( vViewW ); +// vLight = normalize( vLight ); + + // Change the number of samples per ray depending on the viewing angle + // for the surface. Oblique angles require smaller step sizes to achieve + // more accurate precision + int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) ); + + float4 cResultColor = float4( 0, 0, 0, 1 ); + + //===============================================// + // Parallax occlusion mapping offset computation // + //===============================================// + float fCurrHeight = 0.0; + float fStepSize = 1.0 / (float) nNumSteps; + float fPrevHeight = 1.0; + float fNextHeight = 0.0; + + int nStepIndex = 0; +// bool bCondition = true; + + float2 dx = ddx( inTexCoord ); + float2 dy = ddy( inTexCoord ); + + float2 vTexOffsetPerStep = fStepSize * vParallax; + + float2 vTexCurrentOffset = inTexCoord; + float fCurrentBound = 1.0; + + float x = 0; + float y = 0; + float xh = 0; + float yh = 0; + + float2 texOffset2 = 0; + + bool bCondition = true; + while ( bCondition == true && nStepIndex < nNumSteps ) + { + vTexCurrentOffset -= vTexOffsetPerStep; + + fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r; + + fCurrentBound -= fStepSize; + + if ( fCurrHeight > fCurrentBound ) + { + x = fCurrentBound; + y = fCurrentBound + fStepSize; + xh = fCurrHeight; + yh = fPrevHeight; + + texOffset2 = vTexCurrentOffset - vTexOffsetPerStep; + + bCondition = false; + } + else + { + nStepIndex++; + fPrevHeight = fCurrHeight; + } + + } // End of while ( bCondition == true && nStepIndex > -1 )#else + + fCurrentBound -= fStepSize; + + float fParallaxAmount; + float numerator = (x * (y - yh) - y * (x - xh)); + float denomenator = ((y - yh) - (x - xh)); + // avoid NaN generation + if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) ) + { + fParallaxAmount = 0.0f; + } + else + { + fParallaxAmount = numerator / denomenator; + } + + float2 vParallaxOffset = vParallax * (1 - fParallaxAmount ); + + // Sample the height at the next possible step: + fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r; + + // Original offset: + float2 texSampleBase = inTexCoord - vParallaxOffset; + + return texSampleBase; + +#if 0 + cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight ); + + float fBound = 1.0 - fStepSize * nStepIndex; + if ( fNextHeight < fCurrentBound ) +// if( 0 ) + { + //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor ) + //cResultColor.rgb = float3(1,0,0); + DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + + cResultColor.rgb /= 5; +// cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f ); + } // End of if ( fNextHeight < fCurrentBound ) + +#if DOSHADOWS + { + //============================================// + // Soft shadow and self-occlusion computation // + //============================================// + // Compute the blurry shadows (note that this computation takes into + // account self-occlusion for shadow computation): + float sh0 = tex2D( sNormalMap, texSampleBase).w; + float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening; + float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening; + float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening; + float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening; + float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening; + float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening; + float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening; + + // Compute the actual shadow strength: + float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 ); + + cResultColor.rgb *= fShadow * 0.6 + 0.4; + } +#endif + + return cResultColor; +#endif +} + + +//======================================// +// HSL Color space conversion routines // +//======================================// + +#define HUE 0 +#define SATURATION 1 +#define LIGHTNESS 2 + +// Convert from RGB to HSL color space +float4 RGBtoHSL( float4 inColor ) +{ + float h, s; + float flMax = max( inColor.r, max( inColor.g, inColor.b ) ); + float flMin = min( inColor.r, min( inColor.g, inColor.b ) ); + + float l = (flMax + flMin) / 2.0f; + + if (flMax == flMin) // achromatic case + { + s = h = 0; + } + else // chromatic case + { + // Next, calculate the hue + float delta = flMax - flMin; + + // First, calculate the saturation + if (l < 0.5f) // If we're in the lower hexcone + { + s = delta/(flMax + flMin); + } + else + { + s = delta/(2 - flMax - flMin); + } + + if ( inColor.r == flMax ) + { + h = (inColor.g - inColor.b)/delta; // color between yellow and magenta + } + else if ( inColor.g == flMax ) + { + h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow + } + else // blue must be max + { + h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan + } + + h *= 60.0f; + + if (h < 0.0f) + { + h += 360.0f; + } + + h /= 360.0f; + } + + return float4 (h, s, l, 1.0f); +} + +float HueToRGB( float v1, float v2, float vH ) +{ + float fResult = v1; + + vH = fmod (vH + 1.0f, 1.0f); + + if ( ( 6.0f * vH ) < 1.0f ) + { + fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH ); + } + else if ( ( 2.0f * vH ) < 1.0f ) + { + fResult = ( v2 ); + } + else if ( ( 3.0f * vH ) < 2.0f ) + { + fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f ); + } + + return fResult; +} + +// Convert from HSL to RGB color space +float4 HSLtoRGB( float4 hsl ) +{ + float r, g, b; + float h = hsl[HUE]; + float s = hsl[SATURATION]; + float l = hsl[LIGHTNESS]; + + if ( s == 0 ) + { + r = g = b = l; + } + else + { + float v1, v2; + + if ( l < 0.5f ) + v2 = l * ( 1.0f + s ); + else + v2 = ( l + s ) - ( s * l ); + + v1 = 2 * l - v2; + + r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) ); + g = HueToRGB( v1, v2, h ); + b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) ); + } + + return float4( r, g, b, 1.0f ); +} + + +// texture combining modes for combining base and detail/basetexture2 +#define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode +#define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend +#define TCOMBINE_DETAIL_OVER_BASE 2 +#define TCOMBINE_FADE 3 // straight fade between base and detail. +#define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail +#define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting +#define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6 +#define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail +#define TCOMBINE_MULTIPLY 8 +#define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base +#define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump +#define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11 + +float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode, + float fBlendFactor ) +{ + if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS) + { + float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a); + baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor); + } + if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2) + baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor); + if ( combine_mode == TCOMBINE_RGB_ADDITIVE ) + baseColor.rgb += fBlendFactor * detailColor.rgb; + if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE ) + { + float fblend=fBlendFactor * detailColor.a; + baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend); + } + if ( combine_mode == TCOMBINE_FADE ) + { + baseColor = lerp( baseColor, detailColor, fBlendFactor); + } + if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL ) + { + float fblend=fBlendFactor * (1-baseColor.a); + baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend ); + baseColor.a = detailColor.a; + } + if ( combine_mode == TCOMBINE_MULTIPLY ) + { + baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor); + } + + if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA ) + { + baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor ); + } + if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP ) + { + baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 ); + } + return baseColor; +} + +float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x) +{ + return f1+(f2-f1)*(x-i1)/(i2-i1); +} + +float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode, + float fBlendFactor ) +{ + if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM ) + lit_baseColor += fBlendFactor * detailColor.rgb; + if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE ) + { + // fade in an unusual way - instead of fading out color, remap an increasing band of it from + // 0..1 + //if (fBlendFactor > 0.5) + // lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) ); + //else + // lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5); + + float f = fBlendFactor - 0.5; + float fMult = (f >= 0) ? 1.0/fBlendFactor : 4*fBlendFactor; + float fAdd = (f >= 0) ? 1.0-fMult : -0.5*fMult; + lit_baseColor += saturate(fMult * detailColor.rgb + fAdd); + } + return lit_baseColor; +} + +//NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader +float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants ) +{ +# if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b + { + float flFeatheredAlpha; + float2 flDepths; +#define flSceneDepth flDepths.x +#define flSpriteDepth flDepths.y + +# if ( defined( _X360 ) ) + { + //Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors + asm { + tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point + }; + +# if( !defined( REVERSE_DEPTH_ON_X360 ) ) + flSceneDepth = 1.0f - flSceneDepth; +# endif + + //get the sprite depth into the same range as the texture depth + flSpriteDepth = fProjZ / fProjW; + + //unproject to get at the pre-projection z. This value is much more linear than depth + flDepths = vDepthBlendConstants.z / flDepths; + flDepths = vDepthBlendConstants.y - flDepths; + + flFeatheredAlpha = flSceneDepth - flSpriteDepth; + flFeatheredAlpha *= vDepthBlendConstants.x; + flFeatheredAlpha = saturate( flFeatheredAlpha ); + } +# else + { + flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer + flSpriteDepth = SoftParticleDepth( fProjZ ); + + flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x; + flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering. + flFeatheredAlpha = saturate( flFeatheredAlpha ); + } +# endif + +#undef flSceneDepth +#undef flSpriteDepth + + return flFeatheredAlpha; + } +# else + { + return 1.0f; + } +# endif +} + +#endif //#ifndef COMMON_PS_FXC_H_ diff --git a/mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h b/mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h new file mode 100644 index 00000000..66cc642a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h @@ -0,0 +1,423 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef COMMON_VERTEXLITGENERIC_DX9_H_ +#define COMMON_VERTEXLITGENERIC_DX9_H_ + +#include "common_ps_fxc.h" + +// We store four light colors and positions in an +// array of three of these structures like so: +// +// x y z w +// +------+------+------+------+ +// | L0.rgb | | +// +------+------+------+ | +// | L0.pos | L3 | +// +------+------+------+ rgb | +// | L1.rgb | | +// +------+------+------+------+ +// | L1.pos | | +// +------+------+------+ | +// | L2.rgb | L3 | +// +------+------+------+ pos | +// | L2.pos | | +// +------+------+------+------+ +// +struct PixelShaderLightInfo +{ + float4 color; + float4 pos; +}; + +#define cOverbright 2.0f +#define cOOOverbright 0.5f + +#define LIGHTTYPE_NONE 0 +#define LIGHTTYPE_SPOT 1 +#define LIGHTTYPE_POINT 2 +#define LIGHTTYPE_DIRECTIONAL 3 + +// Better suited to Pixel shader models, 11 instructions in pixel shader +// ... actually, now only 9: mul, cmp, cmp, mul, mad, mad, mad, mad, mad +float3 PixelShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + float3 linearColor, nSquared = worldNormal * worldNormal; + float3 isNegative = ( worldNormal >= 0.0 ) ? 0 : nSquared; + float3 isPositive = ( worldNormal >= 0.0 ) ? nSquared : 0; + linearColor = isPositive.x * cAmbientCube[0] + isNegative.x * cAmbientCube[1] + + isPositive.y * cAmbientCube[2] + isNegative.y * cAmbientCube[3] + + isPositive.z * cAmbientCube[4] + isNegative.z * cAmbientCube[5]; + return linearColor; +} + +// Better suited to Vertex shader models +// Six VS instructions due to use of constant indexing (slt, mova, mul, mul, mad, mad) +float3 VertexShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + float3 nSquared = worldNormal * worldNormal; + int3 isNegative = ( worldNormal < 0.0 ); + float3 linearColor; + linearColor = nSquared.x * cAmbientCube[isNegative.x] + + nSquared.y * cAmbientCube[isNegative.y+2] + + nSquared.z * cAmbientCube[isNegative.z+4]; + return linearColor; +} + +float3 AmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + // Vertex shader cases +#ifdef SHADER_MODEL_VS_1_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_1_1 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_2_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_3_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#else + // Pixel shader case + return PixelShaderAmbientLight( worldNormal, cAmbientCube ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Compute scalar diffuse term with various optional tweaks such as +// Half Lambert and ambient occlusion +//----------------------------------------------------------------------------- +float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const float3 lightDir, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float fResult; + + float NDotL = dot( worldNormal, lightDir ); // Unsaturated dot (-1 to 1 range) + + if ( bHalfLambert ) + { + fResult = saturate(NDotL * 0.5 + 0.5); // Scale and bias to 0 to 1 range + + if ( !bDoLightingWarp ) + { + fResult *= fResult; // Square + } + } + else + { + fResult = saturate( NDotL ); // Saturate pure Lambertian term + } + + if ( bDoAmbientOcclusion ) + { + // Raise to higher powers for darker AO values +// float fAOPower = lerp( 4.0f, 1.0f, fAmbientOcclusion ); +// result *= pow( NDotL * 0.5 + 0.5, fAOPower ); + fResult *= fAmbientOcclusion; + } + + float3 fOut = float3( fResult, fResult, fResult ); + if ( bDoLightingWarp ) + { + fOut = 2.0f * tex1D( lightWarpSampler, fResult ); + } + + return fOut; +} + +float3 PixelShaderDoGeneralDiffuseLight( const float fAtten, const float3 worldPos, const float3 worldNormal, + in sampler NormalizeSampler, + const float3 vPosition, const float3 vColor, const bool bHalfLambert, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + float3 lightDir = normalize( vPosition - worldPos ); +#else + float3 lightDir = NormalizeWithCubemap( NormalizeSampler, vPosition - worldPos ); +#endif + return vColor * fAtten * DiffuseTerm( bHalfLambert, worldNormal, lightDir, bDoAmbientOcclusion, fAmbientOcclusion, bDoLightingWarp, lightWarpSampler ); +} + +float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cLightInfo[3], int nLightIndex ) +{ + if ( nLightIndex == 3 ) + { + // Unpack light 3 from w components... + float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w ); + return normalize( vLight3Pos - worldPos ); + } + else + { + return normalize( cLightInfo[nLightIndex].pos - worldPos ); + } +} + +float3 PixelShaderGetLightColor( PixelShaderLightInfo cLightInfo[3], int nLightIndex ) +{ + if ( nLightIndex == 3 ) + { + // Unpack light 3 from w components... + return float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w ); + } + else + { + return cLightInfo[nLightIndex].color.rgb; + } +} + + +void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent, + const float3 vEyeDir, const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel, + const float3 color, const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + rimLighting = float3(0.0f, 0.0f, 0.0f); + + //float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal + float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal + float LdotR = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?) + specularLighting = pow( LdotR, fSpecularExponent ); // Raise to specular exponent + + // Optionally warp as function of scalar specular and fresnel + if ( bDoSpecularWarp ) + specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel } + + specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L + specularLighting *= color; // Modulate with light color + + if ( bDoAmbientOcclusion ) // Optionally modulate with ambient occlusion + specularLighting *= fAmbientOcclusion; + + if ( bDoRimLighting ) // Optionally do rim lighting + { + rimLighting = pow( LdotR, fRimExponent ); // Raise to rim exponent + rimLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L + rimLighting *= color; // Modulate with light color + } +} + +// Traditional fresnel term approximation +float Fresnel( const float3 vNormal, const float3 vEyeDir ) +{ + float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term + return fresnel * fresnel; // Square for a more subtle look +} + +// Traditional fresnel term approximation which uses 4th power (square twice) +float Fresnel4( const float3 vNormal, const float3 vEyeDir ) +{ + float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term + fresnel = fresnel * fresnel; // Square + return fresnel * fresnel; // Square again for a more subtle look +} + + +// +// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function +// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between +// low and mid while the 0.5 to 1 range blends between mid and high +// +// | +// | . M . . . H +// | . +// L +// | +// +---------------- +// 0 1 +// +float Fresnel( const float3 vNormal, const float3 vEyeDir, float3 vRanges ) +{ + //float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel + //if ( f > 0.5f ) + // result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values + //else + // result = lerp( vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values + + // note: vRanges is now encoded as ((mid-min)*2, mid, (max-mid)*2) to optimize math + float f = saturate( 1 - dot( vNormal, vEyeDir ) ); + f = f*f - 0.5; + return vRanges.y + (f >= 0.0 ? vRanges.z : vRanges.x) * f; +} + +void PixelShaderDoSpecularLight( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir, + const float fAtten, const float3 vLightColor, const float3 vLightDir, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel, + const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + // Compute Specular and rim terms + SpecularAndRimTerms( vWorldNormal, vLightDir, fSpecularExponent, + vEyeDir, bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten, + bDoRimLighting, fRimExponent, specularLighting, rimLighting ); +} + +float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6], + in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bHalfLambert, const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float3 linearColor = 0.0f; + + if ( bStaticLight ) + { + // The static lighting comes in in gamma space and has also been premultiplied by $cOOOverbright + // need to get it into + // linear space so that we can do adds. + linearColor += GammaToLinear( staticLightingColor * cOverbright ); + } + + if ( bAmbientLight ) + { + float3 ambient = AmbientLight( worldNormal, cAmbientCube ); + + if ( bDoAmbientOcclusion ) + ambient *= fAmbientOcclusion * fAmbientOcclusion; // Note squaring... + + linearColor += ambient; + } + + if ( nNumLights > 0 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler, + cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 1 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler, + cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 2 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler, + cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 3 ) + { + // Unpack the 4th light's data from tight constant packing + float3 vLight3Color = float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w ); + float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w ); + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler, + vLight3Pos, vLight3Color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + } + } + } + } + + return linearColor; +} + +void PixelShaderDoSpecularLighting( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir, + const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel, + const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 localSpecularTerm, localRimTerm; + + if( nNumLights > 0 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 0 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + if( nNumLights > 1 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 1 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + + if( nNumLights > 2 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 2 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + if( nNumLights > 3 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 3 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + +} + +float3 PixelShaderDoRimLighting( const float3 worldNormal, const float3 vEyeDir, const float3 cAmbientCube[6], float fFresnel ) +{ + float3 vReflect = reflect( -vEyeDir, worldNormal ); // Reflect view through normal + + return fFresnel * PixelShaderAmbientLight( vEyeDir, cAmbientCube ); +} + +// Called directly by newer shaders or through the following wrapper for older shaders +float3 PixelShaderDoLighting( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6], + in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bHalfLambert, + + // New optional/experimental parameters + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float3 linearColor = PixelShaderDoLightingLinear( worldPos, worldNormal, staticLightingColor, + bStaticLight, bAmbientLight, lightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + + // go ahead and clamp to the linear space equivalent of overbright 2 so that we match + // everything else. +// linearColor = HuePreservingColorClamp( linearColor, pow( 2.0f, 2.2 ) ); + + return linearColor; +} + +#endif //#ifndef COMMON_VERTEXLITGENERIC_DX9_H_ diff --git a/mp/src/materialsystem/stdshaders/common_vs_fxc.h b/mp/src/materialsystem/stdshaders/common_vs_fxc.h new file mode 100644 index 00000000..fe2e117a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/common_vs_fxc.h @@ -0,0 +1,955 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: This is where all common code for vertex shaders go. +// +// $NoKeywords: $ +// +//===========================================================================// + + + +#ifndef COMMON_VS_FXC_H_ +#define COMMON_VS_FXC_H_ + +#include "common_fxc.h" + +// Put global skip commands here. . make sure and check that the appropriate vars are defined +// so these aren't used on the wrong shaders! +// -------------------------------------------------------------------------------- +// Ditch all fastpath attemps if we are doing LIGHTING_PREVIEW. +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH +// -------------------------------------------------------------------------------- + + +#ifndef COMPRESSED_VERTS +// Default to no vertex compression +#define COMPRESSED_VERTS 0 +#endif + +#if ( !defined( SHADER_MODEL_VS_2_0 ) && !defined( SHADER_MODEL_VS_3_0 ) ) +#if COMPRESSED_VERTS == 1 +#error "Vertex compression is only for DX9 and up!" +#endif +#endif + +// We're testing 2 normal compression methods +// One compressed normals+tangents into a SHORT2 each (8 bytes total) +// The other compresses them together, into a single UBYTE4 (4 bytes total) +// FIXME: pick one or the other, compare lighting quality in important cases +#define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0 +#define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1 +//#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 +#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 + + +#define FOGTYPE_RANGE 0 +#define FOGTYPE_HEIGHT 1 + +#define COMPILE_ERROR ( 1/0; ) + +// ------------------------- +// CONSTANTS +// ------------------------- + +#pragma def ( vs, c0, 0.0f, 1.0f, 2.0f, 0.5f ) + +const float4 cConstants1 : register(c1); +#define cOOGamma cConstants1.x +#define cOverbright 2.0f +#define cOneThird cConstants1.z +#define cOOOverbright ( 1.0f / 2.0f ) + + +// The g_bLightEnabled registers and g_nLightCountRegister hold the same information regarding +// enabling lights, but callers internal to this file tend to use the loops, while external +// callers will end up using the booleans +const bool g_bLightEnabled[4] : register(b0); + // through b3 + +const int g_nLightCountRegister : register(i0); + + +#define g_nLightCount g_nLightCountRegister.x + +const float4 cEyePosWaterZ : register(c2); +#define cEyePos cEyePosWaterZ.xyz + +// Only cFlexScale.x is used +// It is a binary value used to switch on/off the addition of the flex delta stream +const float4 cFlexScale : register( c3 ); + +const float4x4 cModelViewProj : register(c4); +const float4x4 cViewProj : register(c8); + +// Used to compute projPosZ in shaders without skinning +// Using cModelViewProj with FastClip generates incorrect results +// This is just row two of the non-FastClip cModelViewProj matrix +const float4 cModelViewProjZ : register(c12); + +// More constants working back from the top... +const float4 cViewProjZ : register(c13); + +const float4 cFogParams : register(c16); +#define cFogEndOverFogRange cFogParams.x +#define cFogOne cFogParams.y +#define cFogMaxDensity cFogParams.z +#define cOOFogRange cFogParams.w + +const float4x4 cViewModel : register(c17); + +const float3 cAmbientCubeX [ 2 ] : register ( c21 ) ; +const float3 cAmbientCubeY [ 2 ] : register ( c23 ) ; +const float3 cAmbientCubeZ [ 2 ] : register ( c25 ) ; + +#if defined ( SHADER_MODEL_VS_3_0 ) +const float4 cFlexWeights [ 512 ] : register ( c1024 ) ; +#endif + +struct LightInfo +{ + float4 color; // {xyz} is color w is light type code (see comment below) + float4 dir; // {xyz} is dir w is light type code + float4 pos; + float4 spotParams; + float4 atten; +}; + +// w components of color and dir indicate light type: +// 1x - directional +// 01 - spot +// 00 - point + +// Four lights x 5 constants each = 20 constants +LightInfo cLightInfo[4] : register(c27); +#define LIGHT_0_POSITION_REG c29 + +#ifdef SHADER_MODEL_VS_1_1 + +const float4 cModulationColor : register(c37); + +#define SHADER_SPECIFIC_CONST_0 c38 +#define SHADER_SPECIFIC_CONST_1 c39 +#define SHADER_SPECIFIC_CONST_2 c40 +#define SHADER_SPECIFIC_CONST_3 c41 +#define SHADER_SPECIFIC_CONST_4 c42 +#define SHADER_SPECIFIC_CONST_5 c43 +#define SHADER_SPECIFIC_CONST_6 c44 +#define SHADER_SPECIFIC_CONST_7 c45 +#define SHADER_SPECIFIC_CONST_8 c46 +#define SHADER_SPECIFIC_CONST_9 c47 +#define SHADER_SPECIFIC_CONST_10 c14 +#define SHADER_SPECIFIC_CONST_11 c15 + +static const int cModel0Index = 48; +const float4x3 cModel[16] : register(c48); +// last cmodel is c105 for dx80, c214 for dx90 + +#else // DX9 shaders (vs20 and beyond) + +const float4 cModulationColor : register( c47 ); + +#define SHADER_SPECIFIC_CONST_0 c48 +#define SHADER_SPECIFIC_CONST_1 c49 +#define SHADER_SPECIFIC_CONST_2 c50 +#define SHADER_SPECIFIC_CONST_3 c51 +#define SHADER_SPECIFIC_CONST_4 c52 +#define SHADER_SPECIFIC_CONST_5 c53 +#define SHADER_SPECIFIC_CONST_6 c54 +#define SHADER_SPECIFIC_CONST_7 c55 +#define SHADER_SPECIFIC_CONST_8 c56 +#define SHADER_SPECIFIC_CONST_9 c57 +#define SHADER_SPECIFIC_CONST_10 c14 +#define SHADER_SPECIFIC_CONST_11 c15 + +static const int cModel0Index = 58; +const float4x3 cModel[53] : register( c58 ); +// last cmodel is c105 for dx80, c216 for dx90 + + +#define SHADER_SPECIFIC_BOOL_CONST_0 b4 +#define SHADER_SPECIFIC_BOOL_CONST_1 b5 +#define SHADER_SPECIFIC_BOOL_CONST_2 b6 +#define SHADER_SPECIFIC_BOOL_CONST_3 b7 +#define SHADER_SPECIFIC_BOOL_CONST_4 b8 +#define SHADER_SPECIFIC_BOOL_CONST_5 b9 +#define SHADER_SPECIFIC_BOOL_CONST_6 b10 +#define SHADER_SPECIFIC_BOOL_CONST_7 b11 +#endif // vertex shader model constant packing changes + + +//======================================================================================= +// Methods to decompress vertex normals +//======================================================================================= + +//----------------------------------------------------------------------------------- +// Decompress a normal from two-component compressed format +// We expect this data to come from a signed SHORT2 stream in the range of -32768..32767 +// +// -32678 and 0 are invalid encodings +// w contains the sign to use in the cross product when generating a binormal +void _DecompressShort2Tangent( float2 inputTangent, out float4 outputTangent ) +{ + float2 ztSigns = sign( inputTangent ); // sign bits for z and tangent (+1 or -1) + float2 xyAbs = abs( inputTangent ); // 1..32767 + outputTangent.xy = (xyAbs - 16384.0f) / 16384.0f; // x and y + outputTangent.z = ztSigns.x * sqrt( saturate( 1.0f - dot( outputTangent.xy, outputTangent.xy ) ) ); + outputTangent.w = ztSigns.y; +} + +//----------------------------------------------------------------------------------- +// Same code as _DecompressShort2Tangent, just one returns a float4, one a float3 +void _DecompressShort2Normal( float2 inputNormal, out float3 outputNormal ) +{ + float4 result; + _DecompressShort2Tangent( inputNormal, result ); + outputNormal = result.xyz; +} + +//----------------------------------------------------------------------------------- +// Decompress normal+tangent together +void _DecompressShort2NormalTangent( float2 inputNormal, float2 inputTangent, out float3 outputNormal, out float4 outputTangent ) +{ + // FIXME: if we end up sticking with the SHORT2 format, pack the normal and tangent into a single SHORT4 element + // (that would make unpacking normal+tangent here together much cheaper than the sum of their parts) + _DecompressShort2Normal( inputNormal, outputNormal ); + _DecompressShort2Tangent( inputTangent, outputTangent ); +} + +//======================================================================================= +// Decompress a normal and tangent from four-component compressed format +// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255 +// The final vTangent.w contains the sign to use in the cross product when generating a binormal +void _DecompressUByte4NormalTangent( float4 inputNormal, + out float3 outputNormal, // {nX, nY, nZ} + out float4 outputTangent ) // {tX, tY, tZ, sign of binormal} +{ + float fOne = 1.0f; + + float4 ztztSignBits = ( inputNormal - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction + float4 xyxyAbs = abs( inputNormal - 128.0f ) - ztztSignBits; // 0..127 + float4 xyxySignBits = ( xyxyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0) + float4 normTan = (abs( xyxyAbs - 64.0f ) - xyxySignBits) / 63.0f; // abs({nX, nY, tX, tY}) + outputNormal.xy = normTan.xy; // abs({nX, nY, __, __}) + outputTangent.xy = normTan.zw; // abs({tX, tY, __, __}) + + float4 xyxySigns = 1 - 2*xyxySignBits; // Convert sign bits to signs + float4 ztztSigns = 1 - 2*ztztSignBits; // ( [1,0] -> [-1,+1] ) + + outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1 + outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere + outputNormal.xy *= xyxySigns.xy; // Restore x and y signs + outputNormal.z *= ztztSigns.x; // Restore z sign + + outputTangent.z = 1.0f - outputTangent.x - outputTangent.y; // Project onto x+y+z=1 + outputTangent.xyz = normalize( outputTangent.xyz ); // Normalize onto unit sphere + outputTangent.xy *= xyxySigns.zw; // Restore x and y signs + outputTangent.z *= ztztSigns.z; // Restore z sign + outputTangent.w = ztztSigns.w; // Binormal sign +} + + +//----------------------------------------------------------------------------------- +// Decompress just a normal from four-component compressed format (same as above) +// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255 +// [ When compiled, this works out to approximately 17 asm instructions ] +void _DecompressUByte4Normal( float4 inputNormal, + out float3 outputNormal) // {nX, nY, nZ} +{ + float fOne = 1.0f; + + float2 ztSigns = ( inputNormal.xy - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction + float2 xyAbs = abs( inputNormal.xy - 128.0f ) - ztSigns; // 0..127 + float2 xySigns = ( xyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0) + outputNormal.xy = ( abs( xyAbs - 64.0f ) - xySigns ) / 63.0f; // abs({nX, nY}) + + outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1 + outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere + + outputNormal.xy *= lerp( fOne.xx, -fOne.xx, xySigns ); // Restore x and y signs + outputNormal.z *= lerp( fOne.x, -fOne.x, ztSigns.x ); // Restore z sign +} + + +void DecompressVertex_Normal( float4 inputNormal, out float3 outputNormal ) +{ + if ( COMPRESSED_VERTS == 1 ) + { + if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) + { + _DecompressShort2Normal( inputNormal.xy, outputNormal ); + } + else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) + { + _DecompressUByte4Normal( inputNormal, outputNormal ); + } + } + else + { + outputNormal = inputNormal.xyz; + } +} + +void DecompressVertex_NormalTangent( float4 inputNormal, float4 inputTangent, out float3 outputNormal, out float4 outputTangent ) +{ + if ( COMPRESSED_VERTS == 1 ) + { + if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) + { + _DecompressShort2NormalTangent( inputNormal.xy, inputTangent.xy, outputNormal, outputTangent ); + } + else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) + { + _DecompressUByte4NormalTangent( inputNormal, outputNormal, outputTangent ); + } + } + else + { + outputNormal = inputNormal.xyz; + outputTangent = inputTangent; + } +} + + +#ifdef SHADER_MODEL_VS_3_0 + +//----------------------------------------------------------------------------- +// Methods to sample morph data from a vertex texture +// NOTE: vMorphTargetTextureDim.x = width, cVertexTextureDim.y = height, cVertexTextureDim.z = # of float4 fields per vertex +// For position + normal morph for example, there will be 2 fields. +//----------------------------------------------------------------------------- +float4 SampleMorphDelta( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, const float flField ) +{ + float flColumn = floor( flVertexID / vMorphSubrect.w ); + + float4 t; + t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + flField + 0.5f; + t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f; + t.xy /= vMorphTargetTextureDim.xy; + t.z = t.w = 0.f; + + return tex2Dlod( vt, t ); +} + +// Optimized version which reads 2 deltas +void SampleMorphDelta2( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, out float4 delta1, out float4 delta2 ) +{ + float flColumn = floor( flVertexID / vMorphSubrect.w ); + + float4 t; + t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + 0.5f; + t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f; + t.xy /= vMorphTargetTextureDim.xy; + t.z = t.w = 0.f; + + delta1 = tex2Dlod( vt, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + delta2 = tex2Dlod( vt, t ); +} + +#endif // SHADER_MODEL_VS_3_0 + + +#if ( defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 ) ) + +//----------------------------------------------------------------------------- +// Method to apply morphs +//----------------------------------------------------------------------------- +bool ApplyMorph( float3 vPosFlex, inout float3 vPosition ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + return true; +} + +bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, inout float3 vPosition, inout float3 vNormal ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + return true; +} + +bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + vTangent.xyz += vNormalDelta; + return true; +} + +bool ApplyMorph( float4 vPosFlex, float3 vNormalFlex, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + flWrinkle = vPosFlex.w * cFlexScale.y; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + vTangent.xyz += vNormalDelta; + return true; +} + +#endif // defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 ) + + +#ifdef SHADER_MODEL_VS_3_0 + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition ) +{ +#if MORPHING + +#if !DECAL + // Flexes coming in from a separate stream + float4 vPosDelta = SampleMorphDelta( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, 0 ); + vPosition += vPosDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // !MORPHING + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // !MORPHING + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; + vTangent += vNormalDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; + vTangent += vNormalDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // MORPHING + + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; + vTangent += vNormalDelta.xyz; + flWrinkle = vPosDelta.w; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float4 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; + vTangent += vNormalDelta.xyz * vMorphTexCoord.z; + flWrinkle = vPosDelta.w * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // MORPHING + + flWrinkle = 0.0f; + return false; + +#endif +} + +#endif // SHADER_MODEL_VS_3_0 + + +float RangeFog( const float3 projPos ) +{ + return max( cFogMaxDensity, ( -projPos.z * cOOFogRange + cFogEndOverFogRange ) ); +} + +float WaterFog( const float3 worldPos, const float3 projPos ) +{ + float4 tmp; + + tmp.xy = cEyePosWaterZ.wz - worldPos.z; + + // tmp.x is the distance from the water surface to the vert + // tmp.y is the distance from the eye position to the vert + + // if $tmp.x < 0, then set it to 0 + // This is the equivalent of moving the vert to the water surface if it's above the water surface + + tmp.x = max( 0.0f, tmp.x ); + + // $tmp.w = $tmp.x / $tmp.y + tmp.w = tmp.x / tmp.y; + + tmp.w *= projPos.z; + + // $tmp.w is now the distance that we see through water. + + return max( cFogMaxDensity, ( -tmp.w * cOOFogRange + cFogOne ) ); +} + +float CalcFog( const float3 worldPos, const float3 projPos, const int fogType ) +{ +#if defined( _X360 ) + // 360 only does pixel fog + return 1.0f; +#endif + + if( fogType == FOGTYPE_RANGE ) + { + return RangeFog( projPos ); + } + else + { +#if SHADERMODEL_VS_2_0 == 1 + // We do this work in the pixel shader in dx9, so don't do any fog here. + return 1.0f; +#else + return WaterFog( worldPos, projPos ); +#endif + } +} + +float CalcFog( const float3 worldPos, const float3 projPos, const bool bWaterFog ) +{ +#if defined( _X360 ) + // 360 only does pixel fog + return 1.0f; +#endif + + float flFog; + if( !bWaterFog ) + { + flFog = RangeFog( projPos ); + } + else + { +#if SHADERMODEL_VS_2_0 == 1 + // We do this work in the pixel shader in dx9, so don't do any fog here. + flFog = 1.0f; +#else + flFog = WaterFog( worldPos, projPos ); +#endif + } + + return flFog; +} + +float4 DecompressBoneWeights( const float4 weights ) +{ + float4 result = weights; + + if ( COMPRESSED_VERTS ) + { + // Decompress from SHORT2 to float. In our case, [-1, +32767] -> [0, +1] + // NOTE: we add 1 here so we can divide by 32768 - which is exact (divide by 32767 is not). + // This avoids cracking between meshes with different numbers of bone weights. + // We use SHORT2 instead of SHORT2N for a similar reason - the GPU's conversion + // from [-32768,+32767] to [-1,+1] is imprecise in the same way. + result += 1; + result /= 32768; + } + + return result; +} + +void SkinPosition( bool bSkinning, const float4 modelPos, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos ) +{ +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + } + } +} + +void SkinPositionAndNormal( bool bSkinning, const float4 modelPos, const float3 modelNormal, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos, out float3 worldNormal ) +{ + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + worldNormal = mul3x3( modelNormal, ( float3x3 )blendMatrix ); + } + + } // end [isolate] +} + +// Is it worth keeping SkinPosition and SkinPositionAndNormal around since the optimizer +// gets rid of anything that isn't used? +void SkinPositionNormalAndTangentSpace( + bool bSkinning, + const float4 modelPos, const float3 modelNormal, + const float4 modelTangentS, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos, out float3 worldNormal, + out float3 worldTangentS, out float3 worldTangentT ) +{ +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] ); + worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )blendMatrix ); + worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )blendMatrix ); + } + worldTangentT = cross( worldNormal, worldTangentS ) * modelTangentS.w; + } +} + + +//----------------------------------------------------------------------------- +// Lighting helper functions +//----------------------------------------------------------------------------- + +float3 AmbientLight( const float3 worldNormal ) +{ + float3 nSquared = worldNormal * worldNormal; + int3 isNegative = ( worldNormal < 0.0 ); + float3 linearColor; + linearColor = nSquared.x * cAmbientCubeX[isNegative.x] + + nSquared.y * cAmbientCubeY[isNegative.y] + + nSquared.z * cAmbientCubeZ[isNegative.z]; + return linearColor; +} + +// The following "internal" routines are called "privately" by other routines in this file which +// handle the particular flavor of vs20 control flow appropriate to the original caller +float VertexAttenInternal( const float3 worldPos, int lightNum ) +{ + float result = 0.0f; + + // Get light direction + float3 lightDir = cLightInfo[lightNum].pos - worldPos; + + // Get light distance squared. + float lightDistSquared = dot( lightDir, lightDir ); + + // Get 1/lightDistance + float ooLightDist = rsqrt( lightDistSquared ); + + // Normalize light direction + lightDir *= ooLightDist; + + float3 vDist; +# if defined( _X360 ) + { + //X360 dynamic compile hits an internal compiler error using dst(), this is the breakdown of how dst() works from the 360 docs. + vDist.x = 1; + vDist.y = lightDistSquared * ooLightDist; + vDist.z = lightDistSquared; + //flDist.w = ooLightDist; + } +# else + { + vDist = dst( lightDistSquared, ooLightDist ); + } +# endif + + float flDistanceAtten = 1.0f / dot( cLightInfo[lightNum].atten.xyz, vDist ); + + // Spot attenuation + float flCosTheta = dot( cLightInfo[lightNum].dir.xyz, -lightDir ); + float flSpotAtten = (flCosTheta - cLightInfo[lightNum].spotParams.z) * cLightInfo[lightNum].spotParams.w; + flSpotAtten = max( 0.0001f, flSpotAtten ); + flSpotAtten = pow( flSpotAtten, cLightInfo[lightNum].spotParams.x ); + flSpotAtten = saturate( flSpotAtten ); + + // Select between point and spot + float flAtten = lerp( flDistanceAtten, flDistanceAtten * flSpotAtten, cLightInfo[lightNum].dir.w ); + + // Select between above and directional (no attenuation) + result = lerp( flAtten, 1.0f, cLightInfo[lightNum].color.w ); + + return result; +} + +float CosineTermInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert ) +{ + // Calculate light direction assuming this is a point or spot + float3 lightDir = normalize( cLightInfo[lightNum].pos - worldPos ); + + // Select the above direction or the one in the structure, based upon light type + lightDir = lerp( lightDir, -cLightInfo[lightNum].dir, cLightInfo[lightNum].color.w ); + + // compute N dot L + float NDotL = dot( worldNormal, lightDir ); + + if ( !bHalfLambert ) + { + NDotL = max( 0.0f, NDotL ); + } + else // Half-Lambert + { + NDotL = NDotL * 0.5 + 0.5; + NDotL = NDotL * NDotL; + } + return NDotL; +} + +// This routine uses booleans to do early-outs and is meant to be called by routines OUTSIDE of this file +float GetVertexAttenForLight( const float3 worldPos, int lightNum, bool bUseStaticControlFlow ) +{ + float result = 0.0f; + + // Direct3D uses static control flow but OpenGL currently does not + if ( bUseStaticControlFlow ) + { + if ( g_bLightEnabled[lightNum] ) + { + result = VertexAttenInternal( worldPos, lightNum ); + } + } + else // OpenGL non-static-control-flow path + { + result = VertexAttenInternal( worldPos, lightNum ); + } + + return result; +} + +float3 DoLightInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert ) +{ + return cLightInfo[lightNum].color * + CosineTermInternal( worldPos, worldNormal, lightNum, bHalfLambert ) * + VertexAttenInternal( worldPos, lightNum ); +} + +float3 DoLighting( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bDynamicLight, bool bHalfLambert ) +{ + float3 linearColor = float3( 0.0f, 0.0f, 0.0f ); + + if( bStaticLight ) // Static light + { + float3 col = staticLightingColor * cOverbright; +#if defined ( _X360 ) + linearColor += col * col; +#else + linearColor += GammaToLinear( col ); +#endif + } + + if( bDynamicLight ) // Dynamic light + { + for (int i = 0; i < g_nLightCount; i++) + { + linearColor += DoLightInternal( worldPos, worldNormal, i, bHalfLambert ); + } + } + + if( bDynamicLight ) + { + linearColor += AmbientLight( worldNormal ); //ambient light is already remapped + } + + return linearColor; +} + +float3 DoLightingUnrolled( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bDynamicLight, bool bHalfLambert, const int nNumLights ) +{ + float3 linearColor = float3( 0.0f, 0.0f, 0.0f ); + + if( bStaticLight ) // Static light + { + linearColor += GammaToLinear( staticLightingColor * cOverbright ); + } + + if( bDynamicLight ) // Ambient light + { + if ( nNumLights >= 1 ) + linearColor += DoLightInternal( worldPos, worldNormal, 0, bHalfLambert ); + if ( nNumLights >= 2 ) + linearColor += DoLightInternal( worldPos, worldNormal, 1, bHalfLambert ); + if ( nNumLights >= 3 ) + linearColor += DoLightInternal( worldPos, worldNormal, 2, bHalfLambert ); + if ( nNumLights >= 4 ) + linearColor += DoLightInternal( worldPos, worldNormal, 3, bHalfLambert ); + } + + if( bDynamicLight ) + { + linearColor += AmbientLight( worldNormal ); //ambient light is already remapped + } + + return linearColor; +} + +int4 FloatToInt( in float4 floats ) +{ + return D3DCOLORtoUBYTE4( floats.zyxw / 255.001953125 ); +} + +float2 ComputeSphereMapTexCoords( in float3 reflectionVector ) +{ + // transform reflection vector into view space + reflectionVector = mul( reflectionVector, ( float3x3 )cViewModel ); + + // generate + float3 tmp = float3( reflectionVector.x, reflectionVector.y, reflectionVector.z + 1.0f ); + + // find 1 / len + float ooLen = dot( tmp, tmp ); + ooLen = 1.0f / sqrt( ooLen ); + + // tmp = tmp/|tmp| + 1 + tmp.xy = ooLen * tmp.xy + 1.0f; + + return tmp.xy * 0.5f; +} + + +#define DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE 1 + // minxyz.minsoftness / maxxyz.maxsoftness +float3 ApplyDeformation( float3 worldpos, int deftype, float4 defparms0, float4 defparms1, + float4 defparms2, float4 defparms3 ) +{ + float3 ret = worldpos; + if ( deftype == DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE ) + { + ret=max( ret, defparms2.xyz ); + ret=min( ret, defparms3.xyz ); + } + + return ret; +} + + +#endif //#ifndef COMMON_VS_FXC_H_ diff --git a/mp/src/materialsystem/stdshaders/cpp_shader_constant_register_map.h b/mp/src/materialsystem/stdshaders/cpp_shader_constant_register_map.h new file mode 100644 index 00000000..b448b048 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cpp_shader_constant_register_map.h @@ -0,0 +1,45 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Provide convenient mapping for shader constants +// +// $NoKeywords: $ +//============================================================================= + +#define C_CODE_HACK +#include "shader_constant_register_map.h" +#undef C_CODE_HACK + +// For the C code, map the above file's defines back to integers... +#define PSREG_CONSTANT_00 0 +#define PSREG_CONSTANT_01 1 +#define PSREG_CONSTANT_02 2 +#define PSREG_CONSTANT_03 3 +#define PSREG_CONSTANT_04 4 +#define PSREG_CONSTANT_05 5 +#define PSREG_CONSTANT_06 6 +#define PSREG_CONSTANT_07 7 +#define PSREG_CONSTANT_08 8 +#define PSREG_CONSTANT_09 9 +#define PSREG_CONSTANT_10 10 +#define PSREG_CONSTANT_11 11 +#define PSREG_CONSTANT_12 12 +#define PSREG_CONSTANT_13 13 +#define PSREG_CONSTANT_14 14 +#define PSREG_CONSTANT_15 15 +#define PSREG_CONSTANT_16 16 +#define PSREG_CONSTANT_17 17 +#define PSREG_CONSTANT_18 18 +#define PSREG_CONSTANT_19 19 +#define PSREG_CONSTANT_20 20 +#define PSREG_CONSTANT_21 21 +#define PSREG_CONSTANT_22 22 +#define PSREG_CONSTANT_23 23 +#define PSREG_CONSTANT_24 24 +#define PSREG_CONSTANT_25 25 +#define PSREG_CONSTANT_26 26 +#define PSREG_CONSTANT_27 27 +#define PSREG_CONSTANT_28 28 +#define PSREG_CONSTANT_29 29 +#define PSREG_CONSTANT_30 30 +#define PSREG_CONSTANT_31 31 + diff --git a/mp/src/materialsystem/stdshaders/dx8fallbacks.cpp b/mp/src/materialsystem/stdshaders/dx8fallbacks.cpp new file mode 100644 index 00000000..9ee2659c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/dx8fallbacks.cpp @@ -0,0 +1,11 @@ +#include "BaseVSShader.h" + +// This one isn't supported on dx8 +DEFINE_FALLBACK_SHADER( SDK_DepthWrite, Wireframe ) + +DEFINE_FALLBACK_SHADER( SDK_EyeRefract, Eyes_dx8 ) +DEFINE_FALLBACK_SHADER( SDK_VolumeClouds, UnlitGeneric_DX8 ) + +// FIXME: These aren't supported on dx8, but need to be. +DEFINE_FALLBACK_SHADER( SDK_EyeGlint, EyeGlint ) +DEFINE_FALLBACK_SHADER( SDK_AfterShock, AfterShock ) diff --git a/mp/src/materialsystem/stdshaders/example_model_dx9.cpp b/mp/src/materialsystem/stdshaders/example_model_dx9.cpp new file mode 100644 index 00000000..87e012e3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/example_model_dx9.cpp @@ -0,0 +1,60 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Example shader that can be applied to models +// +//================================================================================================== + +#include "BaseVSShader.h" +#include "convar.h" +#include "example_model_dx9_helper.h" + +#ifdef GAME_SHADER_DLL +DEFINE_FALLBACK_SHADER( Mod_Example_Model, Mod_Example_Model_DX9 ) +BEGIN_VS_SHADER( Mod_Example_Model_DX9, "Help for Example Model Shader" ) +#else +DEFINE_FALLBACK_SHADER( Example_Model, Example_Model_DX9 ) +BEGIN_VS_SHADER( Example_Model_DX9, "Help for Example Model Shader" ) +#endif + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + END_SHADER_PARAMS + + void SetupVars( ExampleModel_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + } + + SHADER_INIT_PARAMS() + { + ExampleModel_DX9_Vars_t info; + SetupVars( info ); + InitParamsExampleModel_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + ExampleModel_DX9_Vars_t info; + SetupVars( info ); + InitExampleModel_DX9( this, params, info ); + } + + SHADER_DRAW + { + ExampleModel_DX9_Vars_t info; + SetupVars( info ); + DrawExampleModel_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression, pContextDataPtr ); + } + +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp new file mode 100644 index 00000000..471b9f80 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp @@ -0,0 +1,341 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "BaseVSShader.h" +#include "example_model_dx9_helper.h" +#include "convar.h" +#include "cpp_shader_constant_register_map.h" +#include "example_model_vs20.inc" +#include "example_model_ps20b.inc" +#include "commandbuilder.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT ); +static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT ); +static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT ); + +// Textures may be bound to the following samplers: +// SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha +// SHADER_SAMPLER4 Flashlight Shadow Depth Map +// SHADER_SAMPLER5 Normalization cube map +// SHADER_SAMPLER6 Flashlight Cookie + + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, ExampleModel_DX9_Vars_t &info ) +{ + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + Assert( info.m_nFlashlightTexture >= 0 ); + + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // This shader can be used with hw skinning + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); +} + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- +void InitExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, ExampleModel_DX9_Vars_t &info ) +{ + Assert( info.m_nFlashlightTexture >= 0 ); + pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB ); + + bool bIsBaseTextureTranslucent = false; + if ( params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + } +} + +class CExampleModel_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; + bool m_bFastPath; + +}; + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +void DrawExampleModel_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bHasFlashlight, ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) +{ + bool bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture(); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + + BlendType_t nBlendType= pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true ); + bool bFullyOpaque = ( nBlendType != BT_BLENDADD ) && ( nBlendType != BT_BLEND ) && !bIsAlphaTested && !bHasFlashlight; + + CExampleModel_DX9_Context *pContextData = reinterpret_cast< CExampleModel_DX9_Context *> ( *pContextDataPtr ); + if ( !pContextData ) + { + pContextData = new CExampleModel_DX9_Context; + *pContextDataPtr = pContextData; + } + + if( pShader->IsSnapshotting() ) + { + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + int nShadowFilterMode = 0; + if( bHasFlashlight ) + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + + if( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + else // not flashlight pass + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true ); + } + } + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int userDataSize = 0; + + // Always enable...will bind white if nothing specified... + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base (albedo) map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + if( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Noise map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Flashlight cookie + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true ); + userDataSize = 4; // tangent S + } + + // Always enable, since flat normal will be bound + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Normal map + userDataSize = 4; // tangent S + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Normalizing cube map + pShaderShadow->EnableSRGBWrite( true ); + + // texcoord0 : base texcoord, texcoord2 : decal hw morph delta + int pTexCoordDim[3] = { 2, 0, 3 }; + int nTexCoordCount = 1; + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( example_model_vs20 ); + SET_STATIC_VERTEX_SHADER( example_model_vs20 ); + + // Assume we're only going to get in here if we support 2b + DECLARE_STATIC_PIXEL_SHADER( example_model_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 ); + SET_STATIC_PIXEL_SHADER( example_model_ps20b ); + + if( bHasFlashlight ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + else // not snapshotting -- begin dynamic state + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + + if( bHasBaseTexture ) + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + + LightState_t lightState = { 0, false, false }; + bool bFlashlightShadows = false; + if( bHasFlashlight ) + { + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + pShader->BindTexture( SHADER_SAMPLER6, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame ); + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + + SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + } + } + else // no flashlight + { + pShaderAPI->GetDX9LightState( &lightState ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + int numBones = pShaderAPI->GetCurrentNumBones(); + + bool bWriteDepthToAlpha = false; + bool bWriteWaterFogToAlpha = false; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( example_model_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( example_model_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( example_model_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( example_model_ps20b ); + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + pShader->SetAmbientCubeDynamicStateVertexShader(); + + if( !bHasFlashlight ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + } + + pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight ); // Force to black if not bAmbientLight + pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY ); + + // handle mat_fullbright 2 (diffuse lighting only) + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + if( bHasFlashlight ) + { + VMatrix worldToTexture; + float atten[4], pos[4], tweaks[4]; + + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + pShader->BindTexture( SHADER_SAMPLER6, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + } + } + pShader->Draw(); +} + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +void DrawExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr ) + +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if ( bHasFlashlight ) + { + DrawExampleModel_DX9_Internal( pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression, pContextDataPtr++ ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + DrawExampleModel_DX9_Internal( pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression, pContextDataPtr ); +} diff --git a/mp/src/materialsystem/stdshaders/example_model_dx9_helper.h b/mp/src/materialsystem/stdshaders/example_model_dx9_helper.h new file mode 100644 index 00000000..3b82e71f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/example_model_dx9_helper.h @@ -0,0 +1,46 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Example shader that can be applied to models +// +//================================================================================================== + +#ifndef EXAMPLE_MODEL_DX9_HELPER_H +#define EXAMPLE_MODEL_DX9_HELPER_H + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct ExampleModel_DX9_Vars_t +{ + ExampleModel_DX9_Vars_t() { memset( this, 0xFF, sizeof(*this) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nAlphaTestReference; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; +}; + +void InitParamsExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, + const char *pMaterialName, ExampleModel_DX9_Vars_t &info ); + +void InitExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, + ExampleModel_DX9_Vars_t &info ); + +void DrawExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, + ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ); + +#endif // EXAMPLE_MODEL_DX9_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/example_model_ps20b.fxc b/mp/src/materialsystem/stdshaders/example_model_ps20b.fxc new file mode 100644 index 00000000..a7b35e44 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/example_model_ps20b.fxc @@ -0,0 +1,92 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Example pixel shader that can be applied to models +// +//================================================================================================== + +// STATIC: "CONVERT_TO_SRGB" "0..0" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] + +// SKIP: ($PIXELFOGTYPE == 0) && ($WRITEWATERFOGTODESTALPHA != 0) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b] + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +const float4 g_DiffuseModulation : register( PSREG_DIFFUSE_MODULATION ); +const float4 g_ShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_FlashlightAttenuationFactors : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass +const float4 g_FlashlightPos_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total (4th light spread across w's) + +#define g_FlashlightPos g_FlashlightPos_RimBoost.xyz + +sampler BaseTextureSampler : register( s0 ); // Base map, selfillum in alpha +sampler ShadowDepthSampler : register( s4 ); // Flashlight shadow depth map sampler +sampler NormalizeRandRotSampler : register( s5 ); // Normalization / RandomRotation samplers +sampler FlashlightSampler : register( s6 ); // Flashlight cookie + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float4 lightAtten : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 worldPos : TEXCOORD3; + float3 projPos : TEXCOORD4; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + + float3 diffuseLighting; + if ( FLASHLIGHT != 0 ) + { + float4 flashlightSpacePosition = mul( float4( i.worldPos, 1.0f ), g_FlashlightWorldToTexture ); + + diffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos, flashlightSpacePosition, + i.worldNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, i.projPos, false, g_ShadowTweaks ); + } + else // non-flashlight path + { + // Summation of diffuse illumination from all local lights + diffuseLighting = PixelShaderDoLighting( i.worldPos, i.worldNormal, + float3( 0.0f, 0.0f, 0.0f ), false, true, i.lightAtten, + cAmbientCube, NormalizeRandRotSampler, NUM_LIGHTS, cLightInfo, true, + + // These are dummy parameters: + false, 1.0f, + false, BaseTextureSampler ); + } + + float3 result = baseColor.rgb * g_DiffuseModulation.rgb * diffuseLighting; + float alpha = g_DiffuseModulation.a * baseColor.a; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos.z, i.projPos.z ); + +#if WRITEWATERFOGTODESTALPHA && ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) + alpha = fogFactor; +#endif + + bool bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 ); + + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.projPos.z ); +} diff --git a/mp/src/materialsystem/stdshaders/example_model_vs20.fxc b/mp/src/materialsystem/stdshaders/example_model_vs20.fxc new file mode 100644 index 00000000..877c84e2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/example_model_vs20.fxc @@ -0,0 +1,91 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Example vertex shader that can be applied to models +// +//================================================================================================== + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPosSetup : POSITION; + float fog : FOG; + // Stuff that is seen by the pixel shader + float2 baseTexCoord : TEXCOORD0; + float4 lightAtten : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 worldPos : TEXCOORD3; + float3 projPos : TEXCOORD4; +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + + float3 worldNormal, worldPos; + SkinPositionAndNormal( g_bSkinning, v.vPos, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPosSetup = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.projPos = vProjPos.xyz; + o.fog = CalcFog( worldPos, vProjPos.xyz, g_FogType ); + + // Needed for water fog alpha and diffuse lighting + o.worldPos = worldPos; + o.worldNormal = normalize( worldNormal ); + + // Scalar attenuations for four lights + o.lightAtten.xyz = float4(0,0,0,0); + #if ( NUM_LIGHTS > 0 ) + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, false ); + #endif + #if ( NUM_LIGHTS > 1 ) + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, false ); + #endif + #if ( NUM_LIGHTS > 2 ) + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, false ); + #endif + #if ( NUM_LIGHTS > 3 ) + o.lightAtten.w = GetVertexAttenForLight( worldPos, 3, false ); + #endif + + // Base texture coordinate transform + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/fxctmp9/example_model_ps20b.inc b/mp/src/materialsystem/stdshaders/fxctmp9/example_model_ps20b.inc new file mode 100644 index 00000000..018f7b63 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/fxctmp9/example_model_ps20b.inc @@ -0,0 +1,237 @@ +#include "shaderlib/cshader.h" +class example_model_ps20b_Static_Index +{ +private: + int m_nCONVERT_TO_SRGB; +#ifdef _DEBUG + bool m_bCONVERT_TO_SRGB; +#endif +public: + void SetCONVERT_TO_SRGB( int i ) + { + Assert( i >= 0 && i <= 0 ); + m_nCONVERT_TO_SRGB = i; +#ifdef _DEBUG + m_bCONVERT_TO_SRGB = true; +#endif + } + void SetCONVERT_TO_SRGB( bool i ) + { + m_nCONVERT_TO_SRGB = i ? 1 : 0; +#ifdef _DEBUG + m_bCONVERT_TO_SRGB = true; +#endif + } +private: + int m_nFLASHLIGHT; +#ifdef _DEBUG + bool m_bFLASHLIGHT; +#endif +public: + void SetFLASHLIGHT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nFLASHLIGHT = i; +#ifdef _DEBUG + m_bFLASHLIGHT = true; +#endif + } + void SetFLASHLIGHT( bool i ) + { + m_nFLASHLIGHT = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHT = true; +#endif + } +private: + int m_nFLASHLIGHTDEPTHFILTERMODE; +#ifdef _DEBUG + bool m_bFLASHLIGHTDEPTHFILTERMODE; +#endif +public: + void SetFLASHLIGHTDEPTHFILTERMODE( int i ) + { + Assert( i >= 0 && i <= 2 ); + m_nFLASHLIGHTDEPTHFILTERMODE = i; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = true; +#endif + } + void SetFLASHLIGHTDEPTHFILTERMODE( bool i ) + { + m_nFLASHLIGHTDEPTHFILTERMODE = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = true; +#endif + } +public: + example_model_ps20b_Static_Index( ) + { +#ifdef _DEBUG + m_bCONVERT_TO_SRGB = false; +#endif // _DEBUG + m_nCONVERT_TO_SRGB = 0; +#ifdef _DEBUG + m_bFLASHLIGHT = false; +#endif // _DEBUG + m_nFLASHLIGHT = 0; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = false; +#endif // _DEBUG + m_nFLASHLIGHTDEPTHFILTERMODE = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bCONVERT_TO_SRGB && m_bFLASHLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nFLASHLIGHT ) + ( 160 * m_nFLASHLIGHTDEPTHFILTERMODE ) + 0; + } +}; +#define shaderStaticTest_example_model_ps20b psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + 0 +class example_model_ps20b_Dynamic_Index +{ +private: + int m_nWRITEWATERFOGTODESTALPHA; +#ifdef _DEBUG + bool m_bWRITEWATERFOGTODESTALPHA; +#endif +public: + void SetWRITEWATERFOGTODESTALPHA( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nWRITEWATERFOGTODESTALPHA = i; +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = true; +#endif + } + void SetWRITEWATERFOGTODESTALPHA( bool i ) + { + m_nWRITEWATERFOGTODESTALPHA = i ? 1 : 0; +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = true; +#endif + } +private: + int m_nPIXELFOGTYPE; +#ifdef _DEBUG + bool m_bPIXELFOGTYPE; +#endif +public: + void SetPIXELFOGTYPE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPIXELFOGTYPE = i; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } + void SetPIXELFOGTYPE( bool i ) + { + m_nPIXELFOGTYPE = i ? 1 : 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } +private: + int m_nNUM_LIGHTS; +#ifdef _DEBUG + bool m_bNUM_LIGHTS; +#endif +public: + void SetNUM_LIGHTS( int i ) + { + Assert( i >= 0 && i <= 4 ); + m_nNUM_LIGHTS = i; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } + void SetNUM_LIGHTS( bool i ) + { + m_nNUM_LIGHTS = i ? 1 : 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } +private: + int m_nWRITE_DEPTH_TO_DESTALPHA; +#ifdef _DEBUG + bool m_bWRITE_DEPTH_TO_DESTALPHA; +#endif +public: + void SetWRITE_DEPTH_TO_DESTALPHA( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nWRITE_DEPTH_TO_DESTALPHA = i; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = true; +#endif + } + void SetWRITE_DEPTH_TO_DESTALPHA( bool i ) + { + m_nWRITE_DEPTH_TO_DESTALPHA = i ? 1 : 0; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = true; +#endif + } +private: + int m_nFLASHLIGHTSHADOWS; +#ifdef _DEBUG + bool m_bFLASHLIGHTSHADOWS; +#endif +public: + void SetFLASHLIGHTSHADOWS( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nFLASHLIGHTSHADOWS = i; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = true; +#endif + } + void SetFLASHLIGHTSHADOWS( bool i ) + { + m_nFLASHLIGHTSHADOWS = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = true; +#endif + } +public: + example_model_ps20b_Dynamic_Index() + { +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = false; +#endif // _DEBUG + m_nWRITEWATERFOGTODESTALPHA = 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = false; +#endif // _DEBUG + m_nPIXELFOGTYPE = 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = false; +#endif // _DEBUG + m_nNUM_LIGHTS = 0; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = false; +#endif // _DEBUG + m_nWRITE_DEPTH_TO_DESTALPHA = 0; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = false; +#endif // _DEBUG + m_nFLASHLIGHTSHADOWS = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bWRITEWATERFOGTODESTALPHA && m_bPIXELFOGTYPE && m_bNUM_LIGHTS && m_bWRITE_DEPTH_TO_DESTALPHA && m_bFLASHLIGHTSHADOWS; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nWRITEWATERFOGTODESTALPHA ) + ( 2 * m_nPIXELFOGTYPE ) + ( 4 * m_nNUM_LIGHTS ) + ( 20 * m_nWRITE_DEPTH_TO_DESTALPHA ) + ( 40 * m_nFLASHLIGHTSHADOWS ) + 0; + } +}; +#define shaderDynamicTest_example_model_ps20b psh_forgot_to_set_dynamic_WRITEWATERFOGTODESTALPHA + psh_forgot_to_set_dynamic_PIXELFOGTYPE + psh_forgot_to_set_dynamic_NUM_LIGHTS + psh_forgot_to_set_dynamic_WRITE_DEPTH_TO_DESTALPHA + psh_forgot_to_set_dynamic_FLASHLIGHTSHADOWS + 0 diff --git a/mp/src/materialsystem/stdshaders/fxctmp9/example_model_vs20.inc b/mp/src/materialsystem/stdshaders/fxctmp9/example_model_vs20.inc new file mode 100644 index 00000000..a8dbd23f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/fxctmp9/example_model_vs20.inc @@ -0,0 +1,160 @@ +#include "shaderlib/cshader.h" +class example_model_vs20_Static_Index +{ +public: + example_model_vs20_Static_Index( ) + { + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG +#endif // _DEBUG + return 0; + } +}; +#define shaderStaticTest_example_model_vs20 0 +class example_model_vs20_Dynamic_Index +{ +private: + int m_nCOMPRESSED_VERTS; +#ifdef _DEBUG + bool m_bCOMPRESSED_VERTS; +#endif +public: + void SetCOMPRESSED_VERTS( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nCOMPRESSED_VERTS = i; +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = true; +#endif + } + void SetCOMPRESSED_VERTS( bool i ) + { + m_nCOMPRESSED_VERTS = i ? 1 : 0; +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = true; +#endif + } +private: + int m_nDOWATERFOG; +#ifdef _DEBUG + bool m_bDOWATERFOG; +#endif +public: + void SetDOWATERFOG( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nDOWATERFOG = i; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } + void SetDOWATERFOG( bool i ) + { + m_nDOWATERFOG = i ? 1 : 0; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } +private: + int m_nSKINNING; +#ifdef _DEBUG + bool m_bSKINNING; +#endif +public: + void SetSKINNING( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nSKINNING = i; +#ifdef _DEBUG + m_bSKINNING = true; +#endif + } + void SetSKINNING( bool i ) + { + m_nSKINNING = i ? 1 : 0; +#ifdef _DEBUG + m_bSKINNING = true; +#endif + } +private: + int m_nLIGHTING_PREVIEW; +#ifdef _DEBUG + bool m_bLIGHTING_PREVIEW; +#endif +public: + void SetLIGHTING_PREVIEW( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nLIGHTING_PREVIEW = i; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = true; +#endif + } + void SetLIGHTING_PREVIEW( bool i ) + { + m_nLIGHTING_PREVIEW = i ? 1 : 0; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = true; +#endif + } +private: + int m_nNUM_LIGHTS; +#ifdef _DEBUG + bool m_bNUM_LIGHTS; +#endif +public: + void SetNUM_LIGHTS( int i ) + { + Assert( i >= 0 && i <= 4 ); + m_nNUM_LIGHTS = i; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } + void SetNUM_LIGHTS( bool i ) + { + m_nNUM_LIGHTS = i ? 1 : 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } +public: + example_model_vs20_Dynamic_Index() + { +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = false; +#endif // _DEBUG + m_nCOMPRESSED_VERTS = 0; +#ifdef _DEBUG + m_bDOWATERFOG = false; +#endif // _DEBUG + m_nDOWATERFOG = 0; +#ifdef _DEBUG + m_bSKINNING = false; +#endif // _DEBUG + m_nSKINNING = 0; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = false; +#endif // _DEBUG + m_nLIGHTING_PREVIEW = 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = false; +#endif // _DEBUG + m_nNUM_LIGHTS = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bCOMPRESSED_VERTS && m_bDOWATERFOG && m_bSKINNING && m_bLIGHTING_PREVIEW && m_bNUM_LIGHTS; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nCOMPRESSED_VERTS ) + ( 2 * m_nDOWATERFOG ) + ( 4 * m_nSKINNING ) + ( 8 * m_nLIGHTING_PREVIEW ) + ( 16 * m_nNUM_LIGHTS ) + 0; + } +}; +#define shaderDynamicTest_example_model_vs20 vsh_forgot_to_set_dynamic_COMPRESSED_VERTS + vsh_forgot_to_set_dynamic_DOWATERFOG + vsh_forgot_to_set_dynamic_SKINNING + vsh_forgot_to_set_dynamic_LIGHTING_PREVIEW + vsh_forgot_to_set_dynamic_NUM_LIGHTS + 0 diff --git a/mp/src/materialsystem/stdshaders/game_shader_dx9_base.vpc b/mp/src/materialsystem/stdshaders/game_shader_dx9_base.vpc new file mode 100644 index 00000000..2fb7fc9e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/game_shader_dx9_base.vpc @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// game_shader_dx9.vpc +// +// Project Script for mods to use an an example of how to override shaders +//----------------------------------------------------------------------------- + +$Macro OUTBINDIR "$SRCDIR\..\game\$GAMENAME\bin" + +$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc" + +$Configuration "Debug" +{ + $General + { + $OutputDirectory "Debug_dx9_$GAMENAME" [$WIN32] + $IntermediateDirectory "Debug_dx9_$GAMENAME" [$WIN32] + } +} + +$Configuration "Release" +{ + $General + { + $OutputDirectory "Release_dx9_$GAMENAME" [$WIN32] + $IntermediateDirectory "Release_dx9_$GAMENAME" [$WIN32] + } +} + +// Common Configuration +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE;fxctmp9;vshtmp9;" [$WIN32||$POSIX] +// $AdditionalIncludeDirectories "$BASE;..\..\dx9sdk\include" [$WIN32] + $AdditionalIncludeDirectories "$BASE;fxctmp9_360;vshtmp9_360" [$X360] + $PreprocessorDefinitions "$BASE;STDSHADER_DX9_DLL_EXPORT;FAST_MATERIALVAR_ACCESS;GAME_SHADER_DLL" + $PreprocessorDefinitions "$BASE;USE_ACTUAL_DX" [($WIN32||$X360) && !$GL] + } + + $Linker + { + $AdditionalDependencies "$BASE version.lib winmm.lib" [$WIN32] + $SystemLibraries "iconv" [$OSXALL] + } +} + +$Project +{ + $Folder "Source Files" + { + $File "BaseVSShader.cpp" + + $File "example_model_dx9.cpp" + $File "example_model_dx9_helper.cpp" + } + + $Folder "Header Files" + { + $File "BaseVSShader.h" + $File "common_fxc.h" + $File "common_hlsl_cpp_consts.h" + $File "common_ps_fxc.h" + $File "common_vertexlitgeneric_dx9.h" + $File "common_vs_fxc.h" + $File "shader_constant_register_map.h" + + $File "example_model_dx9_helper.h" + } + + $Folder "Link Libraries" [$WIN32] + { +// $File "$SRCDIR\dx9sdk\lib\d3dx9.lib" + $DynamicFile "$SRCDIR\lib\public\mathlib.lib" + $DynamicFile "$SRCDIR\lib\public\shaderlib.lib" + } + + $Folder "Link Libraries" [$X360] + { + $DynamicFile "$SRCDIR\lib\public\mathlib_360.lib" + $DynamicFile "$SRCDIR\lib\public\shaderlib_360.lib" + } + + $Folder "Link Libraries" [$POSIX&&!$LINUX] + { + $DynamicFile "$SRCDIR\lib\$PLATFORM\mathlib$_STATICLIB_EXT" + $DynamicFile "$SRCDIR\lib\$PLATFORM\shaderlib$_STATICLIB_EXT" + } + + $Folder "Link Libraries" [$LINUX] + { + $Lib mathlib + $Lib shaderlib + } + + $File "buildsdkshaders.bat" + $File "buildshaders.bat" + + $Shaders "stdshader_dx9_20b.txt" + $Shaders "stdshader_dx9_30.txt" +} diff --git a/mp/src/materialsystem/stdshaders/game_shader_dx9_hl2mp.vpc b/mp/src/materialsystem/stdshaders/game_shader_dx9_hl2mp.vpc new file mode 100644 index 00000000..7f5339b7 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/game_shader_dx9_hl2mp.vpc @@ -0,0 +1,13 @@ +//----------------------------------------------------------------------------- +// game_shader_dx9.vpc +// +// Project Script for mods to use an an example of how to override shaders +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro GAMENAME "mod_hl2mp" +$Include "$SRCDIR\materialsystem\stdshaders\game_shader_dx9_base.vpc" + +$Project "Shaders (HL2MP)" +{ +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/genwaterloop.pl b/mp/src/materialsystem/stdshaders/genwaterloop.pl new file mode 100644 index 00000000..0a4701ce --- /dev/null +++ b/mp/src/materialsystem/stdshaders/genwaterloop.pl @@ -0,0 +1,9 @@ +for($ix=-2;$ix<=2;$ix++) +{ + for($iy=-2;$iy<=2;$iy++) + { + print "vRefractColor += tex2D( RefractSampler, vRefractTexCoord + $ix * ddx1 + $iy * ddy1 );\n"; + $sumweights+=1; + } +} +print "float sumweights = $sumweights;\n"; diff --git a/mp/src/materialsystem/stdshaders/macros.vsh b/mp/src/materialsystem/stdshaders/macros.vsh new file mode 100644 index 00000000..9b19f777 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/macros.vsh @@ -0,0 +1,1393 @@ +;------------------------------------ +; RULES FOR AUTHORING VERTEX SHADERS: +;------------------------------------ +; - never use "def" . . .set constants in code instead. . our constant shadowing will break otherwise. +; (same goes for pixel shaders) +; - use cN notation instead of c[N] notation. .makes grepping for registers easier. +; The only exception is c[a0.x+blah] where you have no choice. +$g_NumRegisters = 12; + +; NOTE: These must match the same values in vsh_prep.pl! +$vPos = "v0"; +$vBoneWeights = "v1"; +$vBoneIndices = "v2"; +$vNormal = "v3"; +$vColor = "v5"; +$vSpecular = "v6"; +$vTexCoord0 = "v7"; +$vTexCoord1 = "v8"; +$vTexCoord2 = "v9"; +$vTexCoord3 = "v10"; +$vTangentS = "v11"; +$vTangentT = "v12"; +$vUserData = "v14"; + +if( $g_dx9 ) +{ + if( $g_usesPos ) + { + dcl_position $vPos; + } + + if( $g_usesBoneWeights ) + { + dcl_blendweight $vBoneWeights; + } + if( $g_usesBoneIndices ) + { + dcl_blendindices $vBoneIndices; + } + if( $g_usesNormal ) + { + dcl_normal $vNormal; + } + if( $g_usesColor ) + { + dcl_color0 $vColor; + } + if( $g_usesSpecular ) + { + dcl_color1 $vSpecular; + } + if( $g_usesTexCoord0 ) + { + dcl_texcoord0 $vTexCoord0; + } + if( $g_usesTexCoord1 ) + { + dcl_texcoord1 $vTexCoord1; + } + if( $g_usesTexCoord2 ) + { + dcl_texcoord2 $vTexCoord2; + } + if( $g_usesTexCoord3 ) + { + dcl_texcoord3 $vTexCoord3; + } + if( $g_usesTangentS ) + { + dcl_tangent $vTangentS; + } + if( $g_usesTangentT ) + { + dcl_binormal0 $vTangentT; + } + if( $g_usesUserData ) + { + dcl_tangent $vUserData; + } +} + +# NOTE: These should match g_LightCombinations in vertexshaderdx8.cpp! +# NOTE: Leave this on single lines or shit might blow up. +@g_staticLightTypeArray = ( "none", "static", "none", "none", "none", "none", "none", "none", "none", "none", "none", "none", "static", "static", "static", "static", "static", "static", "static", "static", "static", "static" ); +@g_ambientLightTypeArray = ( "none", "none", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient" ); +@g_localLightType1Array = ( "none", "none", "none", "spot", "point", "directional", "spot", "spot", "spot", "point", "point", "directional", "none", "spot", "point", "directional", "spot", "spot", "spot", "point", "point", "directional" ); +@g_localLightType2Array = ( "none", "none", "none", "none", "none", "none", "spot", "point", "directional", "point", "directional", "directional", "none", "none", "none", "none", "spot", "point", "directional", "point", "directional", "directional" ); + +$cConstants0 = "c0"; +$cZero = "c0.x"; +$cOne = "c0.y"; +$cTwo = "c0.z"; +$cHalf = "c0.w"; + +$cConstants1 = "c1"; +$cOOGamma = "c1.x"; # 1/2.2 +$cOtherOverbrightFactor = "c1.y"; # overbright +$cOneThird = "c1.z"; # 1/3 +$cOverbrightFactor = "c1.w"; # 1/overbright + +$cEyePos = "c2"; +$cWaterZ = "c2.w"; +$cEyePosWaterZ = "c2"; + +$cLightIndex = "c3"; +$cLight0Offset = "c3.x"; # 27 +$cLight1Offset = "c3.y"; # 32 +$cColorToIntScale = "c3.z"; # matrix array offset = 3.0f * 255.0f + 0.01 (epsilon ensures floor yields desired result) +$cModel0Index = "c3.w"; # base for start of skinning matrices + +; NOTE: These must match the same values in vsh_prep.pl! +$cModelViewProj0 = "c4"; +$cModelViewProj1 = "c5"; +$cModelViewProj2 = "c6"; +$cModelViewProj3 = "c7"; + +$cViewProj0 = "c8"; +$cViewProj1 = "c9"; +$cViewProj2 = "c10"; +$cViewProj3 = "c11"; + +; currently unused +; c12, c13 + +$SHADER_SPECIFIC_CONST_10 = "c14"; +$SHADER_SPECIFIC_CONST_11 = "c15"; + +$cFogParams = "c16"; +$cFogEndOverFogRange = "c16.x"; +$cFogOne = "c16.y"; +$cFogMaxDensity = "c16.z"; +$cOOFogRange = "c16.w"; # (1/(fogEnd-fogStart)) + +$cViewModel0 = "c17"; +$cViewModel1 = "c18"; +$cViewModel2 = "c19"; +$cViewModel3 = "c20"; + +$cAmbientColorPosX = "c21"; +$cAmbientColorNegX = "c22"; +$cAmbientColorPosY = "c23"; +$cAmbientColorNegY = "c24"; +$cAmbientColorPosZ = "c25"; +$cAmbientColorNegZ = "c26"; + +$cAmbientColorPosXOffset = "21"; +$cAmbientColorPosYOffset = "23"; +$cAmbientColorPosZOffset = "25"; + +$cLight0DiffColor = "c27"; +$cLight0Dir = "c28"; +$cLight0Pos = "c29"; +$cLight0SpotParams = "c30"; # [ exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2) +$cLight0Atten = "c31"; # [ constant, linear, quadratic, 0.0f ] + +$cLight1DiffColor = "c32"; +$cLight1Dir = "c33"; +$cLight1Pos = "c34"; +$cLight1SpotParams = "c35"; # [ exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2) +$cLight1Atten = "c36"; # [ constant, linear, quadratic, 0.0f ] + +$cModulationColor = "c37"; + +$SHADER_SPECIFIC_CONST_0 = "c38"; +$SHADER_SPECIFIC_CONST_1 = "c39"; +$SHADER_SPECIFIC_CONST_2 = "c40"; +$SHADER_SPECIFIC_CONST_3 = "c41"; +$SHADER_SPECIFIC_CONST_4 = "c42"; +$SHADER_SPECIFIC_CONST_5 = "c43"; +$SHADER_SPECIFIC_CONST_6 = "c44"; +$SHADER_SPECIFIC_CONST_7 = "c45"; +$SHADER_SPECIFIC_CONST_8 = "c46"; +$SHADER_SPECIFIC_CONST_9 = "c47"; +; $SHADER_SPECIFIC_CONST_10 is c14 +; $SHADER_SPECIFIC_CONST_11 is c15 + +; There are 16 model matrices for skinning +; NOTE: These must match the same values in vsh_prep.pl! +$cModel0 = "c48"; +$cModel1 = "c49"; +$cModel2 = "c50"; + +sub OutputUsedRegisters +{ + local( $i ); + ; USED REGISTERS + for( $i = 0; $i < $g_NumRegisters; $i++ ) + { + if( $g_allocated[$i] ) + { + ; $g_allocatedname[$i] = r$i + } + } + ; +} + +sub AllocateRegister +{ + local( *reg ) = shift; + local( $regname ) = shift; + local( $i ); + for( $i = 0; $i < $g_NumRegisters; $i++ ) + { + if( !$g_allocated[$i] ) + { + $g_allocated[$i] = 1; + $g_allocatedname[$i] = $regname; + ; AllocateRegister $regname = r$i + $reg = "r$i"; + &OutputUsedRegisters(); + return; + } + } + ; Out of registers allocating $regname! + $reg = "rERROR_OUT_OF_REGISTERS"; + &OutputUsedRegisters(); +} + +; pass in a reference to a var that contains a register. . ie \$var where var will constain "r1", etc +sub FreeRegister +{ + local( *reg ) = shift; + local( $regname ) = shift; + ; FreeRegister $regname = $reg + if( $reg =~ m/rERROR_DEALLOCATED/ ) + { + ; $regname already deallocated + ; $reg = "rALREADY_DEALLOCATED"; + &OutputUsedRegisters(); + return; + } +; if( $regname ne g_allocatedname[$reg] ) +; { +; ; Error freeing $reg +; mov compileerror, freed unallocated register $regname +; } + + if( ( $reg =~ m/r(.*)/ ) ) + { + $g_allocated[$1] = 0; + } + $reg = "rERROR_DEALLOCATED"; + &OutputUsedRegisters(); +} + +sub CheckUnfreedRegisters() +{ + local( $i ); + for( $i = 0; $i < $g_NumRegisters; $i++ ) + { + if( $g_allocated[$i] ) + { + print "ERROR: r$i allocated to $g_allocatedname[$i] at end of program\n"; + $g_allocated[$i] = 0; + } + } +} + +sub Normalize +{ + local( $r ) = shift; + dp3 $r.w, $r, $r + rsq $r.w, $r.w + mul $r, $r, $r.w +} + +sub Cross +{ + local( $result ) = shift; + local( $a ) = shift; + local( $b ) = shift; + + mul $result.xyz, $a.yzx, $b.zxy + mad $result.xyz, -$b.yzx, $a.zxy, $result +} + +sub RangeFog +{ + local( $projPos ) = shift; + + ;------------------------------ + ; Regular range fog + ;------------------------------ + + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + ; compute fog factor f = (fog_end - dist)*(1/(fog_end-fog_start)) + ; this is == to: (fog_end/(fog_end-fog_start) - dist/(fog_end-fog_start) + ; which can be expressed with a single mad instruction! + + ; Compute |projPos| + local( $tmp ); + &AllocateRegister( \$tmp ); + dp3 $tmp.x, $projPos.xyw, $projPos.xyw + rsq $tmp.x, $tmp.x + rcp $tmp.x, $tmp.x + + if( $g_dx9 ) + { + mad $tmp, -$tmp.x, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max oFog, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$tmp.x, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max oFog.x, $tmp.x, $cFogMaxDensity + } + &FreeRegister( \$tmp ); +} + +sub DepthFog +{ + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + ;------------------------------ + ; Regular range fog + ;------------------------------ + + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + ; compute fog factor f = (fog_end - dist)*(1/(fog_end-fog_start)) + ; this is == to: (fog_end/(fog_end-fog_start) - dist/(fog_end-fog_start) + ; which can be expressed with a single mad instruction! + + ; Compute |projPos| + local( $tmp ); + &AllocateRegister( \$tmp ); + + if( $g_dx9 ) + { + mad $tmp, -$projPos.w, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max $dest, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$projPos.w, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max $dest.x, $tmp.x, $cFogMaxDensity + } + + &FreeRegister( \$tmp ); +} + +sub WaterRangeFog +{ + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + + ; only $worldPos.z is used out of worldPos + local( $worldPos ) = shift; + local( $projPos ) = shift; + + local( $tmp ); + &AllocateRegister( \$tmp ); + + ; This is simple similar triangles. Imagine a line passing from the point directly vertically + ; and another line passing from the point to the eye position. + ; Let d = total distance from point to the eye + ; Let h = vertical distance from the point to the eye + ; Let hw = vertical distance from the point to the water surface + ; Let dw = distance from the point to a point on the water surface that lies along the ray from point to eye + ; Therefore d/h = dw/hw by similar triangles, or dw = d * hw / h. + ; d = |projPos|, h = eyepos.z - worldPos.z, hw = waterheight.z - worldPos.z, dw = what we solve for + + ; Now, tmp.x = hw, and tmp.y = h + add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z + + ; if $tmp.x < 0, then set it to 0 + ; This is the equivalent of moving the vert to the water surface if it's above the water surface + max $tmp.x, $tmp.x, $cZero + + ; Compute 1 / |projPos| = 1/d + dp3 $tmp.z, $projPos.xyw, $projPos.xyw + rsq $tmp.z, $tmp.z + + ; Now we have h/d + mul $tmp.z, $tmp.z, $tmp.y + + ; Now we have d/h + rcp $tmp.w, $tmp.z + + ; We finally have d * hw / h + ; $tmp.w is now the distance that we see through water. + mul $tmp.w, $tmp.x, $tmp.w + + if( $g_dx9 ) + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max oFog, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max oFog.x, $tmp.x, $cFogMaxDensity + } + + &FreeRegister( \$tmp ); +} + +sub WaterDepthFog +{ + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + + ; only $worldPos.z is used out of worldPos + local( $worldPos ) = shift; + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + local( $tmp ); + &AllocateRegister( \$tmp ); + + ; This is simple similar triangles. Imagine a line passing from the point directly vertically + ; and another line passing from the point to the eye position. + ; Let d = total distance from point to the eye + ; Let h = vertical distance from the point to the eye + ; Let hw = vertical distance from the point to the water surface + ; Let dw = distance from the point to a point on the water surface that lies along the ray from point to eye + ; Therefore d/h = dw/hw by similar triangles, or dw = d * hw / h. + ; d = projPos.w, h = eyepos.z - worldPos.z, hw = waterheight.z - worldPos.z, dw = what we solve for + + ; Now, tmp.x = hw, and tmp.y = h + add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z + + ; if $tmp.x < 0, then set it to 0 + ; This is the equivalent of moving the vert to the water surface if it's above the water surface + max $tmp.x, $tmp.x, $cZero + + ; Now we have 1/h + rcp $tmp.z, $tmp.y + + ; Now we have d/h + mul $tmp.w, $projPos.w, $tmp.z + + ; We finally have d * hw / h + ; $tmp.w is now the distance that we see through water. + mul $tmp.w, $tmp.x, $tmp.w + + if( $g_dx9 ) + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max $dest, $tmp.x, $cZero + } + else + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max $dest.x, $tmp.x, $cZero + } + + &FreeRegister( \$tmp ); +} + + +;------------------------------------------------------------------------------ +; Main fogging routine +;------------------------------------------------------------------------------ +sub CalcFog +{ + if( !defined $DOWATERFOG ) + { + die "CalcFog called without using \$DOWATERFOG\n"; + } + my $fogType; + if( $DOWATERFOG == 0 ) + { + $fogType = "rangefog"; + } + else + { + $fogType = "heightfog"; + } + +# print "\$fogType = $fogType\n"; + + ; CalcFog + local( $worldPos ) = shift; + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + if( $fogType eq "rangefog" ) + { + &DepthFog( $projPos, $dest ); + } + elsif( $fogType eq "heightfog" ) + { + &WaterDepthFog( $worldPos, $projPos, $dest ); + } + else + { + die; + } +} + +sub CalcRangeFog +{ + ; CalcFog + local( $worldPos ) = shift; + local( $projPos ) = shift; + + if( $DOWATERFOG == 0 ) + { + &RangeFog( $projPos ); + } + elsif( $DOWATERFOG == 1 ) + { + &WaterRangeFog( $worldPos, $projPos ); + } + else + { + die; + } +} + +sub GammaToLinear +{ + local( $gamma ) = shift; + local( $linear ) = shift; + + local( $tmp ); + &AllocateRegister( \$tmp ); + + ; Is rcp more expensive than just storing 2.2 somewhere and doing a mov? + rcp $gamma.w, $cOOGamma ; $gamma.w = 2.2 + lit $linear.z, $gamma.zzzw ; r0.z = linear blue + lit $tmp.z, $gamma.yyyw ; r2.z = linear green + mov $linear.y, $tmp.z ; r0.y = linear green + lit $tmp.z, $gamma.xxxw ; r2.z = linear red + mov $linear.x, $tmp.z ; r0.x = linear red + + &FreeRegister( \$tmp ); +} + +sub LinearToGamma +{ + local( $linear ) = shift; + local( $gamma ) = shift; + + local( $tmp ); + &AllocateRegister( \$tmp ); + + mov $linear.w, $cOOGamma ; $linear.w = 1.0/2.2 + lit $gamma.z, $linear.zzzw ; r0.z = gamma blue + lit $tmp.z, $linear.yyyw ; r2.z = gamma green + mov $gamma.y, $tmp.z ; r0.y = gamma green + lit $tmp.z, $linear.xxxw ; r2.z = gamma red + mov $gamma.x, $tmp.z ; r0.x = gamma red + + &FreeRegister( \$tmp ); +} + +sub ComputeReflectionVector +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $reflectionVector ) = shift; + + local( $vertToEye ); &AllocateRegister( \$vertToEye ); + local( $tmp ); &AllocateRegister( \$tmp ); + + ; compute reflection vector r = 2 * (n dot v) n - v + sub $vertToEye.xyz, $cEyePos.xyz, $worldPos ; $tmp1 = v = c - p + dp3 $tmp, $worldNormal, $vertToEye ; $tmp = n dot v + mul $tmp.xyz, $tmp.xyz, $worldNormal ; $tmp = (n dot v ) n + mad $reflectionVector.xyz, $tmp, $cTwo, -$vertToEye + + &FreeRegister( \$vertToEye ); + &FreeRegister( \$tmp ); +} + +sub ComputeSphereMapTexCoords +{ + local( $reflectionVector ) = shift; + local( $sphereMapTexCoords ) = shift; + + local( $tmp ); &AllocateRegister( \$tmp ); + + ; transform reflection vector into view space + dp3 $tmp.x, $reflectionVector, $cViewModel0 + dp3 $tmp.y, $reflectionVector, $cViewModel1 + dp3 $tmp.z, $reflectionVector, $cViewModel2 + + ; generate + add $tmp.z, $tmp.z, $cOne + + ; find 1 / the length of r2 + dp3 $tmp.w, $tmp, $tmp + rsq $tmp.w, $tmp.w + + ; r1 = r2/|r2| + 1 + mad $tmp.xy, $tmp.w, $tmp, $cOne + mul $sphereMapTexCoords.xy, $tmp.xy, $cHalf + + &FreeRegister( \$tmp ); +} + +sub SkinPosition +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (4 instructions) + ; + ; Transform position into world space + ; position + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + } + else + { + ; + ; 3 bone skinning (19 instructions) + ; + local( $boneIndices ); + local( $blendedMatrix0 ); + local( $blendedMatrix1 ); + local( $blendedMatrix2 ); + local( $localPos ); + &AllocateRegister( \$boneIndices ); + &AllocateRegister( \$blendedMatrix0 ); + &AllocateRegister( \$blendedMatrix1 ); + &AllocateRegister( \$blendedMatrix2 ); + + ; Transform position into world space using all bones + ; denormalize d3dcolor to matrix index + mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; r11 = boneindices at this point + ; first matrix + mov a0.x, $boneIndices.z + mul $blendedMatrix0, $vBoneWeights.x, c[a0.x] + mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1] + mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2] + ; second matrix + mov a0.x, $boneIndices.y + mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2 + + ; Calculate third weight + ; compute 1-(weight1+weight2) to calculate weight2 + ; Use $boneIndices.w as a temp since we aren't using it for anything. + add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y + sub $boneIndices.w, $cOne, $boneIndices.w + + ; third matrix + mov a0.x, $boneIndices.x + mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2 + + dp4 $worldPos.x, $vPos, $blendedMatrix0 + dp4 $worldPos.y, $vPos, $blendedMatrix1 + dp4 $worldPos.z, $vPos, $blendedMatrix2 + mov $worldPos.w, $cOne + + &FreeRegister( \$boneIndices ); + &FreeRegister( \$blendedMatrix0 ); + &FreeRegister( \$blendedMatrix1 ); + &FreeRegister( \$blendedMatrix2 ); + } +} + + +sub SkinPositionAndNormal +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (13 instructions) + ; + ; Transform position + normal + tangentS + tangentT into world space + ; position + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + } + else + { + local( $boneIndices ); + local( $blendedMatrix0 ); + local( $blendedMatrix1 ); + local( $blendedMatrix2 ); + local( $localPos ); + local( $localNormal ); + local( $normalLength ); + local( $ooNormalLength ); + &AllocateRegister( \$boneIndices ); + &AllocateRegister( \$blendedMatrix0 ); + &AllocateRegister( \$blendedMatrix1 ); + &AllocateRegister( \$blendedMatrix2 ); + + ; Transform position into world space using all bones + ; denormalize d3dcolor to matrix index + mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; r11 = boneindices at this point + ; first matrix + mov a0.x, $boneIndices.z + mul $blendedMatrix0, $vBoneWeights.x, c[a0.x] + mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1] + mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2] + ; second matrix + mov a0.x, $boneIndices.y + mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2 + + ; Calculate third weight + ; compute 1-(weight1+weight2) to calculate weight2 + ; Use $boneIndices.w as a temp since we aren't using it for anything. + add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y + sub $boneIndices.w, $cOne, $boneIndices.w + + ; third matrix + mov a0.x, $boneIndices.x + mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2 + + dp4 $worldPos.x, $vPos, $blendedMatrix0 + dp4 $worldPos.y, $vPos, $blendedMatrix1 + dp4 $worldPos.z, $vPos, $blendedMatrix2 + mov $worldPos.w, $cOne + + ; normal + dp3 $worldNormal.x, $vNormal, $blendedMatrix0 + dp3 $worldNormal.y, $vNormal, $blendedMatrix1 + dp3 $worldNormal.z, $vNormal, $blendedMatrix2 + + &FreeRegister( \$boneIndices ); + &FreeRegister( \$blendedMatrix0 ); + &FreeRegister( \$blendedMatrix1 ); + &FreeRegister( \$blendedMatrix2 ); + } +} + +sub SkinPositionNormalAndTangentSpace +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $worldTangentS ) = shift; + local( $worldTangentT ) = shift; + local( $userData ); + local( $localPos ); + local( $localNormal ); + local( $normalLength ); + local( $ooNormalLength ); + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# &AllocateRegister( \$userData ); +# ; remap compressed range [0..1] to [-1..1] +# mad $userData, $vUserData, $cTwo, -$cOne +# } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (13 instructions) + ; + ; Transform position + normal + tangentS + tangentT into world space + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# ; tangents +# dp3 $worldTangentS.x, $userData, $cModel0 +# dp3 $worldTangentS.y, $userData, $cModel1 +# dp3 $worldTangentS.z, $userData, $cModel2 +# +# ; calculate tangent t via cross( N, S ) * S[3] +# &Cross( $worldTangentT, $worldNormal, $worldTangentS ); +# mul $worldTangentT.xyz, $userData.w, $worldTangentT.xyz +# } +# else + { + ; tangents + dp3 $worldTangentS.x, $vUserData, $cModel0 + dp3 $worldTangentS.y, $vUserData, $cModel1 + dp3 $worldTangentS.z, $vUserData, $cModel2 + + ; calculate tangent t via cross( N, S ) * S[3] + &Cross( $worldTangentT, $worldNormal, $worldTangentS ); + mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz + } + } + else + { + local( $boneIndices ); + local( $blendedMatrix0 ); + local( $blendedMatrix1 ); + local( $blendedMatrix2 ); + &AllocateRegister( \$boneIndices ); + &AllocateRegister( \$blendedMatrix0 ); + &AllocateRegister( \$blendedMatrix1 ); + &AllocateRegister( \$blendedMatrix2 ); + + ; Transform position into world space using all bones + ; denormalize d3dcolor to matrix index + mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; r11 = boneindices at this point + ; first matrix + mov a0.x, $boneIndices.z + mul $blendedMatrix0, $vBoneWeights.x, c[a0.x] + mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1] + mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2] + ; second matrix + mov a0.x, $boneIndices.y + mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2 + + ; Calculate third weight + ; compute 1-(weight1+weight2) to calculate weight2 + ; Use $boneIndices.w as a temp since we aren't using it for anything. + add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y + sub $boneIndices.w, $cOne, $boneIndices.w + + ; third matrix + mov a0.x, $boneIndices.x + mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2 + + ; position + dp4 $worldPos.x, $vPos, $blendedMatrix0 + dp4 $worldPos.y, $vPos, $blendedMatrix1 + dp4 $worldPos.z, $vPos, $blendedMatrix2 + mov $worldPos.w, $cOne + + ; normal + dp3 $worldNormal.x, $vNormal, $blendedMatrix0 + dp3 $worldNormal.y, $vNormal, $blendedMatrix1 + dp3 $worldNormal.z, $vNormal, $blendedMatrix2 + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# ; tangents +# dp3 $worldTangentS.x, $userData, $blendedMatrix0 +# dp3 $worldTangentS.y, $userData, $blendedMatrix1 +# dp3 $worldTangentS.z, $userData, $blendedMatrix2 +# +# ; calculate tangent t via cross( N, S ) * S[3] +# &Cross( $worldTangentT, $worldNormal, $worldTangentS ); +# mul $worldTangentT.xyz, $userData.w, $worldTangentT.xyz +# } +# else + { + ; tangents + dp3 $worldTangentS.x, $vUserData, $blendedMatrix0 + dp3 $worldTangentS.y, $vUserData, $blendedMatrix1 + dp3 $worldTangentS.z, $vUserData, $blendedMatrix2 + + ; calculate tangent t via cross( N, S ) * S[3] + &Cross( $worldTangentT, $worldNormal, $worldTangentS ); + mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz + } + + &FreeRegister( \$boneIndices ); + &FreeRegister( \$blendedMatrix0 ); + &FreeRegister( \$blendedMatrix1 ); + &FreeRegister( \$blendedMatrix2 ); + } + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# &FreeRegister( \$userData ); +# } +} + +sub ColorClamp +{ + ; ColorClamp; stomps $color.w + local( $color ) = shift; + local( $dst ) = shift; + + ; Get the max of RGB and stick it in W + max $color.w, $color.x, $color.y + max $color.w, $color.w, $color.z + + ; get the greater of one and the max color. + max $color.w, $color.w, $cOne + + rcp $color.w, $color.w + mul $dst.xyz, $color.w, $color.xyz +} + +sub AmbientLight +{ + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + ; Ambient lighting + &AllocateRegister( \$nSquared ); + &AllocateRegister( \$isNegative ); + + mul $nSquared.xyz, $worldNormal.xyz, $worldNormal.xyz ; compute n times n + slt $isNegative.xyz, $worldNormal.xyz, $cZero ; Figure out whether each component is >0 + mov a0.x, $isNegative.x + if( $add ) + { + mad $linearColor.xyz, $nSquared.x, c[a0.x + $cAmbientColorPosXOffset], $linearColor ; $linearColor = normal[0]*normal[0] * box color of appropriate x side + } + else + { + mul $linearColor.xyz, $nSquared.x, c[a0.x + $cAmbientColorPosXOffset] ; $linearColor = normal[0]*normal[0] * box color of appropriate x side + } + mov a0.x, $isNegative.y + mad $linearColor.xyz, $nSquared.y, c[a0.x + $cAmbientColorPosYOffset], $linearColor + mov a0.x, $isNegative.z + mad $linearColor.xyz, $nSquared.z, c[a0.x + $cAmbientColorPosZOffset], $linearColor + + &FreeRegister( \$isNegative ); + &FreeRegister( \$nSquared ); +} + +sub DirectionalLight +{ + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + &AllocateRegister( \$nDotL ); # FIXME: This only needs to be a scalar + + ; NOTE: Gotta use -l here, since light direction = -l + ; DIRECTIONAL LIGHT + ; compute n dot l + dp3 $nDotL.x, -c[a0.x + 1], $worldNormal + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $nDotL.x, $nDotL.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $nDotL.x, $nDotL.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5)^2 + mul $nDotL.x, $nDotL.x, $nDotL.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + if( $add ) + { + mad $linearColor.xyz, c[a0.x], $nDotL.x, $linearColor + } + else + { + mul $linearColor.xyz, c[a0.x], $nDotL.x + } + + &FreeRegister( \$nDotL ); +} + +sub PointLight +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + local( $lightDir ); + &AllocateRegister( \$lightDir ); + + ; POINT LIGHT + ; compute light direction + sub $lightDir, c[a0.x+2], $worldPos + + local( $lightDistSquared ); + local( $ooLightDist ); + &AllocateRegister( \$lightDistSquared ); + &AllocateRegister( \$ooLightDist ); + + ; normalize light direction, maintain temporaries for attenuation + dp3 $lightDistSquared, $lightDir, $lightDir + rsq $ooLightDist, $lightDistSquared.x + mul $lightDir, $lightDir, $ooLightDist.x + + local( $attenuationFactors ); + &AllocateRegister( \$attenuationFactors ); + + ; compute attenuation amount (r2 = 'd*d d*d d*d d*d', r3 = '1/d 1/d 1/d 1/d') + dst $attenuationFactors, $lightDistSquared, $ooLightDist ; r4 = ( 1, d, d*d, 1/d ) + &FreeRegister( \$lightDistSquared ); + &FreeRegister( \$ooLightDist ); + local( $attenuation ); + &AllocateRegister( \$attenuation ); + dp3 $attenuation, $attenuationFactors, c[a0.x+4] ; r3 = atten0 + d * atten1 + d*d * atten2 + + rcp $lightDir.w, $attenuation ; $lightDir.w = 1 / (atten0 + d * atten1 + d*d * atten2) + + &FreeRegister( \$attenuationFactors ); + &FreeRegister( \$attenuation ); + + local( $tmp ); + &AllocateRegister( \$tmp ); # FIXME : really only needs to be a scalar + + ; compute n dot l, fold in distance attenutation + dp3 $tmp.x, $lightDir, $worldNormal + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $tmp.x, $tmp.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $tmp.x, $tmp.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5)^2 + mul $tmp.x, $tmp.x, $tmp.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + mul $tmp.x, $tmp.x, $lightDir.w + if( $add ) + { + mad $linearColor.xyz, c[a0.x], $tmp.x, $linearColor + } + else + { + mul $linearColor.xyz, c[a0.x], $tmp.x + } + + &FreeRegister( \$lightDir ); + &FreeRegister( \$tmp ); # FIXME : really only needs to be a scalar +} + +sub SpotLight +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + local( $lightDir ); + &AllocateRegister( \$lightDir ); + + ; SPOTLIGHT + ; compute light direction + sub $lightDir, c[a0.x+2], $worldPos + + local( $lightDistSquared ); + local( $ooLightDist ); + &AllocateRegister( \$lightDistSquared ); + &AllocateRegister( \$ooLightDist ); + + ; normalize light direction, maintain temporaries for attenuation + dp3 $lightDistSquared, $lightDir, $lightDir + rsq $ooLightDist, $lightDistSquared.x + mul $lightDir, $lightDir, $ooLightDist.x + + local( $attenuationFactors ); + &AllocateRegister( \$attenuationFactors ); + + ; compute attenuation amount (r2 = 'd*d d*d d*d d*d', r3 = '1/d 1/d 1/d 1/d') + dst $attenuationFactors, $lightDistSquared, $ooLightDist ; r4 = ( 1, d, d*d, 1/d ) + + &FreeRegister( \$lightDistSquared ); + &FreeRegister( \$ooLightDist ); + local( $attenuation ); &AllocateRegister( \$attenuation ); + + dp3 $attenuation, $attenuationFactors, c[a0.x+4] ; r3 = atten0 + d * atten1 + d*d * atten2 + rcp $lightDir.w, $attenuation ; r1.w = 1 / (atten0 + d * atten1 + d*d * atten2) + + &FreeRegister( \$attenuationFactors ); + &FreeRegister( \$attenuation ); + + local( $litSrc ); &AllocateRegister( \$litSrc ); + local( $tmp ); &AllocateRegister( \$tmp ); # FIXME - only needs to be scalar + + ; compute n dot l + dp3 $litSrc.x, $worldNormal, $lightDir + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $litSrc.x, $litSrc.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $litSrc.x, $litSrc.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5) ^ 2 + mul $litSrc.x, $litSrc.x, $litSrc.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + ; compute angular attenuation + dp3 $tmp.x, c[a0.x+1], -$lightDir ; dot = -delta * spot direction + sub $litSrc.y, $tmp.x, c[a0.x+3].z ; r2.y = dot - stopdot2 + &FreeRegister( \$tmp ); + mul $litSrc.y, $litSrc.y, c[a0.x+3].w ; r2.y = (dot - stopdot2) / (stopdot - stopdot2) + mov $litSrc.w, c[a0.x+3].x ; r2.w = exponent + local( $litDst ); &AllocateRegister( \$litDst ); + lit $litDst, $litSrc ; r3.y = N dot L or 0, whichever is bigger + &FreeRegister( \$litSrc ); + ; r3.z = pow((dot - stopdot2) / (stopdot - stopdot2), exponent) + min $litDst.z, $litDst.z, $cOne ; clamp pow() to 1 + + local( $tmp1 ); &AllocateRegister( \$tmp1 ); + local( $tmp2 ); &AllocateRegister( \$tmp2 ); # FIXME - could be scalar + + ; fold in distance attenutation with other factors + mul $tmp1, c[a0.x], $lightDir.w + mul $tmp2.x, $litDst.y, $litDst.z + if( $add ) + { + mad $linearColor.xyz, $tmp1, $tmp2.x, $linearColor + } + else + { + mul $linearColor.xyz, $tmp1, $tmp2.x + } + + &FreeRegister( \$lightDir ); + &FreeRegister( \$litDst ); + &FreeRegister( \$tmp1 ); + &FreeRegister( \$tmp2 ); +} + +sub DoLight +{ + local( $lightType ) = shift; + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + if( $lightType eq "spot" ) + { + &SpotLight( $worldPos, $worldNormal, $linearColor, $add ); + } + elsif( $lightType eq "point" ) + { + &PointLight( $worldPos, $worldNormal, $linearColor, $add ); + } + elsif( $lightType eq "directional" ) + { + &DirectionalLight( $worldNormal, $linearColor, $add ); + } + else + { + die "don't know about light type \"$lightType\"\n"; + } +} + +sub DoLighting +{ + if( !defined $LIGHT_COMBO ) + { + die "DoLighting called without using \$LIGHT_COMBO\n"; + } + if ( !defined $HALF_LAMBERT ) + { + die "DoLighting called without using \$HALF_LAMBERT\n"; + } + + my $staticLightType = $g_staticLightTypeArray[$LIGHT_COMBO]; + my $ambientLightType = $g_ambientLightTypeArray[$LIGHT_COMBO]; + my $localLightType1 = $g_localLightType1Array[$LIGHT_COMBO]; + my $localLightType2 = $g_localLightType2Array[$LIGHT_COMBO]; + +# print "\$staticLightType = $staticLightType\n"; +# print "\$ambientLightType = $ambientLightType\n"; +# print "\$localLightType1 = $localLightType1\n"; +# print "\$localLightType2 = $localLightType2\n"; + + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + + ; special case for no lighting + if( $staticLightType eq "none" && $ambientLightType eq "none" && + $localLightType1 eq "none" && $localLightType2 eq "none" ) + { + ; Have to write something here since debug d3d runtime will barf otherwise. + mov oD0, $cOne + return; + } + + ; special case for static lighting only + ; Don't need to bother converting to linear space in this case. + if( $staticLightType eq "static" && $ambientLightType eq "none" && + $localLightType1 eq "none" && $localLightType2 eq "none" ) + { + mov oD0, $vSpecular + return; + } + + alloc $linearColor + alloc $gammaColor + + local( $add ) = 0; + if( $staticLightType eq "static" ) + { + ; The static lighting comes in in gamma space and has also been premultiplied by $cOverbrightFactor + ; need to get it into + ; linear space so that we can do adds. + rcp $gammaColor.w, $cOverbrightFactor + mul $gammaColor.xyz, $vSpecular, $gammaColor.w + &GammaToLinear( $gammaColor, $linearColor ); + $add = 1; + } + + if( $ambientLightType eq "ambient" ) + { + &AmbientLight( $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType1 ne "none" ) + { + mov a0.x, $cLight0Offset + &DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType2 ne "none" ) + { + mov a0.x, $cLight1Offset + &DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } + + ;------------------------------------------------------------------------------ + ; Output color (gamma correction) + ;------------------------------------------------------------------------------ + + &LinearToGamma( $linearColor, $gammaColor ); + if( 0 ) + { + mul oD0.xyz, $gammaColor.xyz, $cOverbrightFactor + } + else + { + mul $gammaColor.xyz, $gammaColor.xyz, $cOverbrightFactor + &ColorClamp( $gammaColor, "oD0" ); + } + +; mov oD0.xyz, $linearColor + mov oD0.w, $cOne ; make sure all components are defined + + free $linearColor + free $gammaColor +} + +sub DoDynamicLightingToLinear +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + + if( !defined $LIGHT_COMBO ) + { + die "DoLighting called without using \$LIGHT_COMBO\n"; + } + if ( !defined $HALF_LAMBERT ) + { + die "DoLighting called without using \$HALF_LAMBERT\n"; + } + + my $staticLightType = $g_staticLightTypeArray[$LIGHT_COMBO]; + my $ambientLightType = $g_ambientLightTypeArray[$LIGHT_COMBO]; + my $localLightType1 = $g_localLightType1Array[$LIGHT_COMBO]; + my $localLightType2 = $g_localLightType2Array[$LIGHT_COMBO]; + + # No lights at all. . note that we don't even consider static lighting here. + if( $ambientLightType eq "none" && + $localLightType1 eq "none" && $localLightType2 eq "none" ) + { + mov $linearColor, $cZero + return; + } + + local( $add ) = 0; + if( $ambientLightType eq "ambient" ) + { + &AmbientLight( $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType1 ne "none" ) + { + mov a0.x, $cLight0Offset + &DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType2 ne "none" ) + { + mov a0.x, $cLight1Offset + &DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } +} + +sub NotImplementedYet +{ + &AllocateRegister( \$projPos ); + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 + mov oPos, $projPos + &FreeRegister( \$projPos ); + exit; +} diff --git a/mp/src/materialsystem/stdshaders/shader_constant_register_map.h b/mp/src/materialsystem/stdshaders/shader_constant_register_map.h new file mode 100644 index 00000000..485bb7c4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/shader_constant_register_map.h @@ -0,0 +1,81 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Provide convenient mapping for shader constants +// +// $NoKeywords: $ +//============================================================================= + +#ifndef C_CODE_HACK +#include "common_vertexlitgeneric_dx9.h" +#endif + +#define PSREG_SELFILLUMTINT PSREG_CONSTANT_00 +#define PSREG_DIFFUSE_MODULATION PSREG_CONSTANT_01 +#define PSREG_ENVMAP_TINT__SHADOW_TWEAKS PSREG_CONSTANT_02 +#define PSREG_SELFILLUM_SCALE_BIAS_EXP PSREG_CONSTANT_03 +#define PSREG_AMBIENT_CUBE PSREG_CONSTANT_04 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_05 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_06 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_07 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_08 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_09 +#define PSREG_ENVMAP_FRESNEL__SELFILLUMMASK PSREG_CONSTANT_10 +#define PSREG_EYEPOS_SPEC_EXPONENT PSREG_CONSTANT_11 +#define PSREG_FOG_PARAMS PSREG_CONSTANT_12 +#define PSREG_FLASHLIGHT_ATTENUATION PSREG_CONSTANT_13 +#define PSREG_FLASHLIGHT_POSITION_RIM_BOOST PSREG_CONSTANT_14 +#define PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_15 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_16 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_17 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_18 +#define PSREG_FRESNEL_SPEC_PARAMS PSREG_CONSTANT_19 +#define PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_20 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_21 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_22 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_23 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_24 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_25 +#define PSREG_SPEC_RIM_PARAMS PSREG_CONSTANT_26 +// #define **free** PSREG_CONSTANT_27 //actually using this often blows constant limits, since literals have to get stuffed somewhere... +#define PSREG_FLASHLIGHT_COLOR PSREG_CONSTANT_28 +#define PSREG_LINEAR_FOG_COLOR PSREG_CONSTANT_29 +#define PSREG_LIGHT_SCALE PSREG_CONSTANT_30 +#define PSREG_FLASHLIGHT_SCREEN_SCALE PSREG_CONSTANT_31 +// --- End of ps_2_0 and ps_2_b constants --- + + +#ifndef C_CODE_HACK +//for fxc code, map the constants to register names. +#define PSREG_CONSTANT_00 c0 +#define PSREG_CONSTANT_01 c1 +#define PSREG_CONSTANT_02 c2 +#define PSREG_CONSTANT_03 c3 +#define PSREG_CONSTANT_04 c4 +#define PSREG_CONSTANT_05 c5 +#define PSREG_CONSTANT_06 c6 +#define PSREG_CONSTANT_07 c7 +#define PSREG_CONSTANT_08 c8 +#define PSREG_CONSTANT_09 c9 +#define PSREG_CONSTANT_10 c10 +#define PSREG_CONSTANT_11 c11 +#define PSREG_CONSTANT_12 c12 +#define PSREG_CONSTANT_13 c13 +#define PSREG_CONSTANT_14 c14 +#define PSREG_CONSTANT_15 c15 +#define PSREG_CONSTANT_16 c16 +#define PSREG_CONSTANT_17 c17 +#define PSREG_CONSTANT_18 c18 +#define PSREG_CONSTANT_19 c19 +#define PSREG_CONSTANT_20 c20 +#define PSREG_CONSTANT_21 c21 +#define PSREG_CONSTANT_22 c22 +#define PSREG_CONSTANT_23 c23 +#define PSREG_CONSTANT_24 c24 +#define PSREG_CONSTANT_25 c25 +#define PSREG_CONSTANT_26 c26 +#define PSREG_CONSTANT_27 c27 +#define PSREG_CONSTANT_28 c28 +#define PSREG_CONSTANT_29 c29 +#define PSREG_CONSTANT_30 c30 +#define PSREG_CONSTANT_31 c31 +#endif diff --git a/mp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt b/mp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt new file mode 100644 index 00000000..f70ae0a2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt @@ -0,0 +1,11 @@ +// +// Standard shaders collection +// +// These shaders are compiled as the following shader models: +// _ps20.vcs +// _ps20b.vcs +// _vs20.vcs +// + +example_model_ps20b.fxc +example_model_vs20.fxc diff --git a/mp/src/materialsystem/stdshaders/stdshader_dx9_30.txt b/mp/src/materialsystem/stdshaders/stdshader_dx9_30.txt new file mode 100644 index 00000000..5a09a37b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/stdshader_dx9_30.txt @@ -0,0 +1,10 @@ +// +// vs 3.0 ps 3.0 shaders collection +// +// These shaders are forced to compile as shader model 3.0 +// using the new compiler. +// _ps30.vcs +// _vs30.vcs +// + +// There are no examples of such shaders in the SDK, but add yours here. diff --git a/mp/src/public/appframework/ilaunchermgr.h b/mp/src/public/appframework/ilaunchermgr.h index 5d38b15a..7fa5dc76 100644 --- a/mp/src/public/appframework/ilaunchermgr.h +++ b/mp/src/public/appframework/ilaunchermgr.h @@ -10,7 +10,7 @@ #pragma once #endif -#if defined( USE_SDL ) || defined( OSX ) +#if defined( USE_SDL ) #include "tier0/threadtools.h" #include "appframework/IAppSystem.h" @@ -29,18 +29,12 @@ class CShowPixelsParams; #endif // if you rev this version also update materialsystem/cmaterialsystem.cpp CMaterialSystem::Connect as it defines the string directly -#if defined( USE_SDL ) - #define SDLMGR_INTERFACE_VERSION "SDLMgrInterface001" -#elif defined( OSX ) - #define COCOAMGR_INTERFACE_VERSION "CocoaMgrInterface006" -#endif +#define SDLMGR_INTERFACE_VERSION "SDLMgrInterface001" class CCocoaEvent; class CStackCrawlParams; -#if defined( USE_SDL ) typedef struct SDL_Cursor SDL_Cursor; -#endif class ILauncherMgr : public IAppSystem { @@ -103,11 +97,9 @@ public: virtual void *GetWindowRef() = 0; virtual void SetMouseVisible( bool bState ) = 0; -#ifdef USE_SDL virtual void SetMouseCursor( SDL_Cursor *hCursor ) = 0; virtual void SetForbidMouseGrab( bool bForbidMouseGrab ) = 0; virtual void OnFrameRendered() = 0; -#endif virtual void SetGammaRamp( const uint16 *pRed, const uint16 *pGreen, const uint16 *pBlue ) = 0; @@ -163,6 +155,6 @@ public: int m_MouseButton; // which of the CocoaMouseButton_t buttons this is for from above }; -#endif // USE_SDL || OSX +#endif // defined( USE_SDL ) #endif // ILAUNCHERMGR_H diff --git a/mp/src/public/cdll_int.h b/mp/src/public/cdll_int.h index 1757d5d7..1801c383 100644 --- a/mp/src/public/cdll_int.h +++ b/mp/src/public/cdll_int.h @@ -525,7 +525,7 @@ public: virtual void SetGamestatsData( CGamestatsData *pGamestatsData ) = 0; virtual CGamestatsData *GetGamestatsData() = 0; -#if defined( USE_SDL ) || defined( OSX ) +#if defined( USE_SDL ) // we need to pull delta's from the cocoa mgr, the engine vectors this for us virtual void GetMouseDelta( int &x, int &y, bool bIgnoreNextMouseDelta = false ) = 0; #endif diff --git a/mp/src/public/eiface.h b/mp/src/public/eiface.h index ea0a4ab7..821df8d6 100644 --- a/mp/src/public/eiface.h +++ b/mp/src/public/eiface.h @@ -407,6 +407,9 @@ public: // Server version from the steam.inf, this will be compared to the GC version virtual int GetServerVersion() const = 0; + + // Get sv.GetTime() + virtual float GetServerTime() const = 0; }; diff --git a/mp/src/public/engine/ivdebugoverlay.h b/mp/src/public/engine/ivdebugoverlay.h index 51aeafd1..0b24c777 100644 --- a/mp/src/public/engine/ivdebugoverlay.h +++ b/mp/src/public/engine/ivdebugoverlay.h @@ -25,7 +25,7 @@ class Vector; // When used as a duration by a server-side NDebugOverlay:: call, // causes the overlay to persist until the next server update. -#define NDEBUG_PERSIST_TILL_NEXT_SERVER (0.01023f) +#define NDEBUG_PERSIST_TILL_NEXT_SERVER (0.0f) class OverlayText_t; diff --git a/mp/src/public/headtrack/iheadtrack.h b/mp/src/public/headtrack/iheadtrack.h deleted file mode 100644 index 4f5fcced..00000000 --- a/mp/src/public/headtrack/iheadtrack.h +++ /dev/null @@ -1,84 +0,0 @@ -//===== Copyright (c), Valve Corporation, All rights reserved. ======// -// -// Purpose: Contains the IHeadTrack interface, which is implemented in headtrack.dll -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef IHEADTRACK_H -#define IHEADTRACK_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include "tier1/refcount.h" -#include "appframework/IAppSystem.h" -#include "mathlib/vmatrix.h" -#include "view_shared.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// important enumeration -//----------------------------------------------------------------------------- - -// NOTE NOTE NOTE!!!! If you up this, grep for "NEW_INTERFACE" to see if there is anything -// waiting to be enabled during an interface revision. -#define HEAD_TRACK_INTERFACE_VERSION "VHeadTrack001" - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -abstract_class IHeadTrack : public IAppSystem -{ -public: - virtual ~IHeadTrack() {} - - // Placeholder for API revision - virtual bool Connect( CreateInterfaceFn factory ) = 0; - virtual void Disconnect() = 0; - virtual void *QueryInterface( const char *pInterfaceName ) = 0; - virtual InitReturnVal_t Init() = 0; - virtual void Shutdown() = 0; - - //----------------------------------------------------------------------------- - // Tracking section - //----------------------------------------------------------------------------- - // All methods return true on success, false on failure. - - // Also sets the zero pose - virtual bool ResetTracking() = 0; - - // Set the current pose as the "zero" - virtual bool SetCurrentCameraAsZero() = 0; - - // Raw interfaces - one one or other of these, not both (GetCameraPoseZeroFromCurrent calls GetCameraFromWorldPose ); - virtual bool GetCameraFromWorldPose ( VMatrix *pResultCameraFromWorldPose, VMatrix *pResultCameraFromWorldPoseUnpredicted = NULL, double *pflAcquireTime = NULL ) = 0; - virtual bool GetCameraPoseZeroFromCurrent ( VMatrix *pResultMatrix ) = 0; - - // All-in-one interfaces (they call GetCameraPoseZeroFromCurrent) - // Grabs the current tracking data and sets up state for the Override* calls. - virtual bool ProcessCurrentTrackingState ( float PlayerGameFov ) = 0; - - // Performs the distortion post-processing. - virtual bool DoDistortionProcessing ( const vrect_t *SrcRect ) = 0; - -}; - - - -//----------------------------------------------------------------------------- - -extern IHeadTrack *g_pHeadTrack; - -inline bool UseHeadTracking() -{ - return g_pHeadTrack != NULL; -} -#endif // IHEADTRACK_H diff --git a/mp/src/public/materialsystem/materialsystem_config.h b/mp/src/public/materialsystem/materialsystem_config.h index 1cdca782..1a8d1d1d 100644 --- a/mp/src/public/materialsystem/materialsystem_config.h +++ b/mp/src/public/materialsystem/materialsystem_config.h @@ -32,6 +32,7 @@ enum MaterialSystem_Config_Flags_t MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE = ( 1 << 13 ), MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION = ( 1 << 14 ), MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS = ( 1 << 15 ), + MATSYS_VIDCFG_FLAGS_DISABLE_PHONG = ( 1 << 16 ), }; struct MaterialSystemHardwareIdentifier_t @@ -62,6 +63,7 @@ struct MaterialSystem_Config_t bool LimitWindowedSize() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE ) != 0; } bool ScaleToOutputResolution() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION ) != 0; } bool UsingMultipleWindows() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS ) != 0; } + bool UsePhong() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_PHONG ) == 0; } bool ShadowDepthTexture() const { return m_bShadowDepthTexture; } bool MotionBlur() const { return m_bMotionBlur; } bool SupportFlashlight() const { return m_bSupportFlashlight; } @@ -157,6 +159,7 @@ struct MaterialSystem_Config_t SetFlag( MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE, false ); SetFlag( MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION, false ); SetFlag( MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS, false ); + SetFlag( MATSYS_VIDCFG_FLAGS_DISABLE_PHONG, false ); m_VideoMode.m_Width = 640; m_VideoMode.m_Height = 480; diff --git a/mp/src/public/mathlib/mathlib.h b/mp/src/public/mathlib/mathlib.h index 83fdb6a0..e1873cd0 100644 --- a/mp/src/public/mathlib/mathlib.h +++ b/mp/src/public/mathlib/mathlib.h @@ -97,7 +97,9 @@ private: #ifdef DEBUG // stop crashing edit-and-continue FORCEINLINE float clamp( float val, float minVal, float maxVal ) { - if( val < minVal ) + if ( maxVal < minVal ) + return maxVal; + else if( val < minVal ) return minVal; else if( val > maxVal ) return maxVal; @@ -115,8 +117,8 @@ FORCEINLINE float clamp( float val, float minVal, float maxVal ) _mm_load_ss(&minVal) ), _mm_load_ss(&maxVal) ) ); #else - val = fpmin(maxVal, val); val = fpmax(minVal, val); + val = fpmin(maxVal, val); #endif return val; } @@ -128,7 +130,9 @@ FORCEINLINE float clamp( float val, float minVal, float maxVal ) template< class T > inline T clamp( T const &val, T const &minVal, T const &maxVal ) { - if( val < minVal ) + if ( maxVal < minVal ) + return maxVal; + else if( val < minVal ) return minVal; else if( val > maxVal ) return maxVal; @@ -2172,9 +2176,9 @@ bool AlmostEqual(float a, float b, int maxUlps = 10); inline bool AlmostEqual( const Vector &a, const Vector &b, int maxUlps = 10) { - return AlmostEqual( a.x, a.x, maxUlps ) && - AlmostEqual( a.y, a.y, maxUlps ) && - AlmostEqual( a.z, a.z, maxUlps ); + return AlmostEqual( a.x, b.x, maxUlps ) && + AlmostEqual( a.y, b.y, maxUlps ) && + AlmostEqual( a.z, b.z, maxUlps ); } diff --git a/mp/src/public/optimize.h b/mp/src/public/optimize.h index b473a65d..b71dc895 100644 --- a/mp/src/public/optimize.h +++ b/mp/src/public/optimize.h @@ -226,7 +226,7 @@ struct FileHeader_t int maxBonesPerVert; // must match checkSum in the .mdl - long checkSum; + int checkSum; int numLODs; // garymcthack - this is also specified in ModelHeader_t and should match diff --git a/mp/src/public/renderparm.h b/mp/src/public/renderparm.h index 32c0fbc0..91c9cfd5 100644 --- a/mp/src/public/renderparm.h +++ b/mp/src/public/renderparm.h @@ -26,6 +26,7 @@ enum RenderParamVector_t VECTOR_RENDERPARM_HMDWARP_GROW_OUTIN, VECTOR_RENDERPARM_HMDWARP_GROW_ABOVEBELOW, VECTOR_RENDERPARM_HMDWARP_ASPECT, + INT_RENDERPARM_DISTORTION_TYPE, MAX_VECTOR_RENDER_PARMS = 20 }; diff --git a/mp/src/public/steam/steam_api.h b/mp/src/public/steam/steam_api.h index fe021f80..e16f226b 100644 --- a/mp/src/public/steam/steam_api.h +++ b/mp/src/public/steam/steam_api.h @@ -512,8 +512,8 @@ inline bool CSteamAPIContext::Init() #if defined(USE_BREAKPAD_HANDLER) || defined(STEAM_API_EXPORTS) // this should be called before the game initialized the steam APIs -// pchDate should be of the format "Mmm dd yyyy" (such as from the __DATE__ macro ) -// pchTime should be of the format "hh:mm:ss" (such as from the __TIME__ macro ) +// pchDate should be of the format "Mmm dd yyyy" (such as from the __DATE __ macro ) +// pchTime should be of the format "hh:mm:ss" (such as from the __TIME __ macro ) // bFullMemoryDumps (Win32 only) -- writes out a uuid-full.dmp in the client/dumps folder // pvContext-- can be NULL, will be the void * context passed into m_pfnPreMinidumpCallback // PFNPreMinidumpCallback m_pfnPreMinidumpCallback -- optional callback which occurs just before a .dmp file is written during a crash. Applications can hook this to allow adding additional information into the .dmp comment stream. diff --git a/mp/src/public/studio.h b/mp/src/public/studio.h index 7770c2af..9b58ab0c 100644 --- a/mp/src/public/studio.h +++ b/mp/src/public/studio.h @@ -1816,7 +1816,7 @@ struct vertexFileHeader_t DECLARE_BYTESWAP_DATADESC(); int id; // MODEL_VERTEX_FILE_ID int version; // MODEL_VERTEX_FILE_VERSION - long checksum; // same as studiohdr_t, ensures sync + int checksum; // same as studiohdr_t, ensures sync int numLODs; // num of valid lods int numLODVertexes[MAX_NUM_LODS]; // num verts for desired root lod int numFixups; // num of vertexFileFixup_t @@ -1991,7 +1991,7 @@ struct studiohdr_t int id; int version; - long checksum; // this has to be the same in the phy and vtx files to load! + int checksum; // this has to be the same in the phy and vtx files to load! inline const char * pszName( void ) const { if (studiohdr2index && pStudioHdr2()->pszName()) return pStudioHdr2()->pszName(); else return name; } char name[64]; diff --git a/mp/src/public/studio_virtualmodel.cpp b/mp/src/public/studio_virtualmodel.cpp index 748ed3b2..269e7cdf 100644 --- a/mp/src/public/studio_virtualmodel.cpp +++ b/mp/src/public/studio_virtualmodel.cpp @@ -572,4 +572,23 @@ void virtualmodel_t::AppendIKLocks( int group, const studiohdr_t *pStudioHdr ) } m_iklock = iklock; + + // copy knee directions for uninitialized knees + if ( group != 0 ) + { + studiohdr_t *pBaseHdr = (studiohdr_t *)m_group[ 0 ].GetStudioHdr(); + if ( pStudioHdr->numikchains == pBaseHdr->numikchains ) + { + for (j = 0; j < pStudioHdr->numikchains; j++) + { + if ( pBaseHdr->pIKChain( j )->pLink(0)->kneeDir.LengthSqr() == 0.0f ) + { + if ( pStudioHdr->pIKChain( j )->pLink(0)->kneeDir.LengthSqr() > 0.0f ) + { + pBaseHdr->pIKChain( j )->pLink(0)->kneeDir = pStudioHdr->pIKChain( j )->pLink(0)->kneeDir; + } + } + } + } + } } diff --git a/mp/src/public/tier0/memalloc.h b/mp/src/public/tier0/memalloc.h index 52578760..2840d095 100644 --- a/mp/src/public/tier0/memalloc.h +++ b/mp/src/public/tier0/memalloc.h @@ -535,7 +535,7 @@ inline void MemAlloc_GlobalMemoryStatus( size_t *pusedMemory, size_t *pfreeMemor *pusedMemory = 0; *pfreeMemory = 0; } -#define MemAlloc_MemoryAllocFailed() 1 +#define MemAlloc_MemoryAllocFailed() 0 #define MemAlloc_GetDebugInfoSize() 0 #define MemAlloc_SaveDebugInfo( pvDebugInfo ) ((void)0) diff --git a/mp/src/public/tier0/platform.h b/mp/src/public/tier0/platform.h index 914cd39a..38e6b563 100644 --- a/mp/src/public/tier0/platform.h +++ b/mp/src/public/tier0/platform.h @@ -1085,7 +1085,7 @@ PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode(); PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded. -PLATFORM_INTERFACE unsigned long Plat_MSTime(); // Time in milliseconds. +PLATFORM_INTERFACE unsigned int Plat_MSTime(); // Time in milliseconds. PLATFORM_INTERFACE char * Plat_asctime( const struct tm *tm, char *buf ); PLATFORM_INTERFACE char * Plat_ctime( const time_t *timep, char *buf, size_t bufsize ); PLATFORM_INTERFACE struct tm * Plat_gmtime( const time_t *timep, struct tm *result ); diff --git a/mp/src/public/tier1/checksum_crc.h b/mp/src/public/tier1/checksum_crc.h index a8ef71e5..130577ee 100644 --- a/mp/src/public/tier1/checksum_crc.h +++ b/mp/src/public/tier1/checksum_crc.h @@ -10,7 +10,7 @@ #pragma once #endif -typedef unsigned long CRC32_t; +typedef unsigned int CRC32_t; void CRC32_Init( CRC32_t *pulCRC ); void CRC32_ProcessBuffer( CRC32_t *pulCRC, const void *p, int len ); diff --git a/mp/src/public/tier1/ilocalize.h b/mp/src/public/tier1/ilocalize.h index 348986ad..a3dd6bb8 100644 --- a/mp/src/public/tier1/ilocalize.h +++ b/mp/src/public/tier1/ilocalize.h @@ -135,7 +135,7 @@ private: typedef char locchar_t; #define loc_snprintf Q_snprintf - #define loc_sprintf_safe V_snprintf_safe + #define loc_sprintf_safe V_sprintf_safe #define loc_sncat Q_strncat #define loc_scat_safe V_strcat_safe #define loc_sncpy Q_strncpy @@ -148,7 +148,7 @@ private: typedef wchar_t locchar_t; #define loc_snprintf V_snwprintf - #define loc_sprintf_safe V_snwprintf_safe + #define loc_sprintf_safe V_swprintf_safe #define loc_sncat V_wcsncat #define loc_scat_safe V_wcscat_safe #define loc_sncpy Q_wcsncpy diff --git a/mp/src/public/tier1/lzmaDecoder.h b/mp/src/public/tier1/lzmaDecoder.h index eb501c10..8aa1f2ca 100644 --- a/mp/src/public/tier1/lzmaDecoder.h +++ b/mp/src/public/tier1/lzmaDecoder.h @@ -1,4 +1,3 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// // // LZMA Decoder. Designed for run time decoding. // diff --git a/mp/src/public/tier1/strtools.h b/mp/src/public/tier1/strtools.h index 8e38436f..6089a8f4 100644 --- a/mp/src/public/tier1/strtools.h +++ b/mp/src/public/tier1/strtools.h @@ -290,7 +290,7 @@ template int V_vsprintf_safe( OUT_Z_ARRAY char (&pDe int V_snprintf( OUT_Z_CAP(maxLenInChars) char *pDest, int maxLenInChars, PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 3, 4 ); // gcc insists on only having format annotations on declarations, not definitions, which is why I have both. template int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 2, 3 ); -template int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], const char *pFormat, ... ) +template int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const char *pFormat, ... ) { va_list params; va_start( params, pFormat ); diff --git a/mp/src/public/tier1/utlrbtree.h b/mp/src/public/tier1/utlrbtree.h index b2665194..6ea22614 100644 --- a/mp/src/public/tier1/utlrbtree.h +++ b/mp/src/public/tier1/utlrbtree.h @@ -1350,7 +1350,7 @@ int CUtlRBTree::Depth( I node ) const int depthright = Depth( RightChild(node) ); int depthleft = Depth( LeftChild(node) ); - return max(depthright, depthleft) + 1; + return Max(depthright, depthleft) + 1; } diff --git a/mp/src/public/togl/glfuncs.inl b/mp/src/public/togl/glfuncs.inl new file mode 100644 index 00000000..dafd0949 --- /dev/null +++ b/mp/src/public/togl/glfuncs.inl @@ -0,0 +1,7 @@ +#if defined(LINUX) || defined(_WIN32) +#include "togl/linuxwin/glfuncs.h" +#endif +#if defined(OSX) +#include "togl/osx/glfuncs.h" +#endif + diff --git a/mp/src/public/togl/linuxwin/cglmbuffer.h b/mp/src/public/togl/linuxwin/cglmbuffer.h new file mode 100644 index 00000000..ffec2742 --- /dev/null +++ b/mp/src/public/togl/linuxwin/cglmbuffer.h @@ -0,0 +1,190 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmprogram.h +// GLMgr buffers (index / vertex) +// ... maybe add PBO later as well +//=============================================================================== + +#ifndef CGLMBUFFER_H +#define CGLMBUFFER_H + +#pragma once + +//=============================================================================== + +extern bool g_bUsePseudoBufs; + +// forward declarations + +class GLMContext; + +enum EGLMBufferType +{ + kGLMVertexBuffer, + kGLMIndexBuffer, + kGLMUniformBuffer, // for bindable uniform + kGLMPixelBuffer, // for PBO + + kGLMNumBufferTypes +}; + +// pass this in "options" to constructor to make a dynamic buffer +#define GLMBufferOptionDynamic 0x00000001 + +struct GLMBuffLockParams +{ + uint m_nOffset; + uint m_nSize; + bool m_bNoOverwrite; + bool m_bDiscard; +}; + +#define GL_STATIC_BUFFER_SIZE ( 2048 * 1024 ) +#define GL_MAX_STATIC_BUFFERS 2 + +extern void glBufferSubDataMaxSize( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data, uint nMaxSizePerCall = 128 * 1024 ); + +//=============================================================================== + +#if GL_ENABLE_INDEX_VERIFICATION + +struct GLDynamicBuf_t +{ + GLenum m_nGLType; + uint m_nHandle; + uint m_nActualBufSize; + uint m_nSize; + + uint m_nLockOffset; + uint m_nLockSize; +}; + +class CGLMBufferSpanManager +{ + CGLMBufferSpanManager( const CGLMBufferSpanManager& ); + CGLMBufferSpanManager& operator= ( const CGLMBufferSpanManager& ); + +public: + CGLMBufferSpanManager(); + ~CGLMBufferSpanManager(); + + void Init( GLMContext *pContext, EGLMBufferType nBufType, uint nInitialCapacity, uint nBufSize, bool bDynamic ); + void Deinit(); + + inline GLMContext *GetContext() const { return m_pCtx; } + + inline GLenum GetGLBufType() const { return ( m_nBufType == kGLMVertexBuffer ) ? GL_ARRAY_BUFFER_ARB : GL_ELEMENT_ARRAY_BUFFER_ARB; } + + struct ActiveSpan_t + { + uint m_nStart; + uint m_nEnd; + + GLDynamicBuf_t m_buf; + bool m_bOriginalAlloc; + + inline ActiveSpan_t() { } + inline ActiveSpan_t( uint nStart, uint nEnd, GLDynamicBuf_t &buf, bool bOriginalAlloc ) : m_nStart( nStart ), m_nEnd( nEnd ), m_buf( buf ), m_bOriginalAlloc( bOriginalAlloc ) { Assert( nStart <= nEnd ); } + }; + + ActiveSpan_t *AddSpan( uint nOffset, uint nMaxSize, uint nActualSize, bool bDiscard, bool bNoOverwrite ); + + void DiscardAllSpans(); + + bool IsValid( uint nOffset, uint nSize ) const; + +private: + bool AllocDynamicBuf( uint nSize, GLDynamicBuf_t &buf ); + void ReleaseDynamicBuf( GLDynamicBuf_t &buf ); + + GLMContext *m_pCtx; + + EGLMBufferType m_nBufType; + + uint m_nBufSize; + bool m_bDynamic; + + CUtlVector m_ActiveSpans; + CUtlVector m_DeletedSpans; + + int m_nSpanEndMax; + + int m_nNumAllocatedBufs; + int m_nTotalBytesAllocated; +}; + +#endif // GL_ENABLE_INDEX_VERIFICATION + +class CGLMBuffer +{ +public: + void Lock( GLMBuffLockParams *pParams, char **pAddressOut ); + void Unlock( int nActualSize = -1, const void *pActualData = NULL ); + + friend class GLMContext; // only GLMContext can make CGLMBuffer objects + friend class GLMTester; + friend struct IDirect3D9; + friend struct IDirect3DDevice9; + + CGLMBuffer( GLMContext *pCtx, EGLMBufferType type, uint size, uint options ); + ~CGLMBuffer(); + + void SetModes( bool bAsyncMap, bool bExplicitFlush, bool bForce = false ); + void FlushRange( uint offset, uint size ); + +#if GL_ENABLE_INDEX_VERIFICATION + bool IsSpanValid( uint nOffset, uint nSize ) const; +#endif + + GLMContext *m_pCtx; // link back to parent context + EGLMBufferType m_type; + uint m_nSize; + uint m_nActualSize; + + bool m_bDynamic; + + GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB + GLuint m_nHandle; // name of this program in the context + + uint m_nRevision; // bump anytime the size changes or buffer is orphaned + + bool m_bEnableAsyncMap; // mirror of the buffer state + bool m_bEnableExplicitFlush; // mirror of the buffer state + + bool m_bMapped; // is it currently mapped + + uint m_dirtyMinOffset; // when equal, range is empty + uint m_dirtyMaxOffset; + + float *m_pLastMappedAddress; + + int m_nPinnedMemoryOfs; + + bool m_bPseudo; // true if the m_name is 0, and the backing is plain RAM + + // in pseudo mode, there is just one RAM buffer that acts as the backing. + // expectation is that this mode would only be used for dynamic indices. + // since indices have to be consumed (copied to command stream) prior to return from a drawing call, + // there's no need to do any fencing or multibuffering. orphaning in particular becomes a no-op. + + char *m_pActualPseudoBuf; // storage for pseudo buffer + char *m_pPseudoBuf; // storage for pseudo buffer + char *m_pStaticBuffer; + + GLMBuffLockParams m_LockParams; + + static char ALIGN16 m_StaticBuffers[ GL_MAX_STATIC_BUFFERS ][ GL_STATIC_BUFFER_SIZE ] ALIGN16_POST; + static bool m_bStaticBufferUsed[ GL_MAX_STATIC_BUFFERS ]; + +#if GL_ENABLE_INDEX_VERIFICATION + CGLMBufferSpanManager m_BufferSpanManager; +#endif + +#if GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION + uint m_nDirtyRangeStart; + uint m_nDirtyRangeEnd; +#endif +}; + +#endif // CGLMBUFFER_H + diff --git a/mp/src/public/togl/linuxwin/cglmfbo.h b/mp/src/public/togl/linuxwin/cglmfbo.h new file mode 100644 index 00000000..f3415795 --- /dev/null +++ b/mp/src/public/togl/linuxwin/cglmfbo.h @@ -0,0 +1,82 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmfbo.h +// GLMgr FBO's (render targets) +// +//=============================================================================== + +#ifndef CGLMFBO_H +#define CGLMFBO_H + +#pragma once + +// good FBO references / recaps +// http://www.songho.ca/opengl/gl_fbo.html +// http://www.gamedev.net/reference/articles/article2331.asp + +// ext links + +// http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt +// http://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt + +//=============================================================================== + +// tokens not in the SDK headers + +#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT + #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; + +enum EGLMFBOAttachment +{ + kAttColor0, kAttColor1, kAttColor2, kAttColor3, + kAttDepth, kAttStencil, kAttDepthStencil, + kAttCount +}; + +struct GLMFBOTexAttachParams +{ + CGLMTex *m_tex; + int m_face; // keep zero if not cube map + int m_mip; // keep zero if notmip mapped + int m_zslice; // keep zero if not a 3D tex +}; + +class CGLMFBO +{ + friend class GLMContext; + friend class GLMTester; + friend class CGLMTex; + + friend struct IDirect3D9; + friend struct IDirect3DDevice9; + +public: + CGLMFBO( GLMContext *ctx ); + ~CGLMFBO( ); + +protected: + void TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); + void TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); + // you can also pass GL_READ_FRAMEBUFFER_EXT or GL_DRAW_FRAMEBUFFER_EXT to selectively bind the receiving FBO to one or the other. + + void TexScrub( CGLMTex *tex ); + // search and destroy any attachment for the named texture + + bool IsReady( void ); // aka FBO completeness check - ready to draw + + GLMContext *m_ctx; // link back to parent context + + GLuint m_name; // name of this FBO in the context + + GLMFBOTexAttachParams m_attach[ kAttCount ]; // indexed by EGLMFBOAttachment +}; + + +#endif \ No newline at end of file diff --git a/mp/src/public/togl/linuxwin/cglmprogram.h b/mp/src/public/togl/linuxwin/cglmprogram.h new file mode 100644 index 00000000..ca32af00 --- /dev/null +++ b/mp/src/public/togl/linuxwin/cglmprogram.h @@ -0,0 +1,420 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmprogram.h +// GLMgr programs (ARBVP/ARBfp) +// +//=============================================================================== + +#ifndef CGLMPROGRAM_H +#define CGLMPROGRAM_H + +#include + +#pragma once + +// good ARB program references +// http://petewarden.com/notes/archives/2005/05/fragment_progra_2.html +// http://petewarden.com/notes/archives/2005/06/fragment_progra_3.html + +// ext links + +// http://www.opengl.org/registry/specs/ARB/vertex_program.txt +// http://www.opengl.org/registry/specs/ARB/fragment_program.txt +// http://www.opengl.org/registry/specs/EXT/gpu_program_parameters.txt + + +//=============================================================================== + +// tokens not in the SDK headers + +//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT +// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +//#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; +class CGLMShaderPair; +class CGLMShaderPairCache; + +// CGLMProgram can contain two flavors of the same program, one in assembler, one in GLSL. +// these flavors are pretty different in terms of the API's that are used to activate them - +// for example, assembler programs can just get bound to the context, whereas GLSL programs +// have to be linked. To some extent we try to hide that detail inside GLM. + +// for now, make CGLMProgram a container, it does not set policy or hold a preference as to which +// flavor you want to use. GLMContext has to handle that. + +enum EGLMProgramType +{ + kGLMVertexProgram, + kGLMFragmentProgram, + + kGLMNumProgramTypes +}; + +enum EGLMProgramLang +{ + kGLMARB, + kGLMGLSL, + + kGLMNumProgramLangs +}; + +struct GLMShaderDesc +{ + union + { + GLuint arb; // ARB program object name + GLhandleARB glsl; // GLSL shader object handle (void*) + } m_object; + + // these can change if shader text is edited + bool m_textPresent; // is this flavor(lang) of text present in the buffer? + int m_textOffset; // where is it + int m_textLength; // how big + + bool m_compiled; // has this text been through a compile attempt + bool m_valid; // and if so, was the compile successful + + int m_slowMark; // has it been flagged during a non native draw batch before. increment every time it's slow. + + int m_highWater; // count of vec4's in the major uniform array ("vc" on vs, "pc" on ps) + // written by dxabstract.... gross! + int m_VSHighWaterBone; // count of vec4's in the bone-specific uniform array (only valid for vertex shaders) +}; + +GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target +GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target + +#define GL_SHADER_PAIR_CACHE_STATS 0 + +class CGLMProgram +{ +public: + friend class CGLMShaderPairCache; + friend class CGLMShaderPair; + friend class GLMContext; // only GLMContext can make CGLMProgram objects + friend class GLMTester; + friend struct IDirect3D9; + friend struct IDirect3DDevice9; + + //=============================== + + // constructor is very light, it just makes one empty program object per flavor. + CGLMProgram( GLMContext *ctx, EGLMProgramType type ); + ~CGLMProgram( ); + + void SetProgramText ( char *text ); // import text to GLM object - invalidate any prev compiled program + void SetShaderName ( const char *name ); // only used for debugging/telemetry markup + + bool CompileActiveSources ( void ); // compile only the flavors that were provided. + bool Compile ( EGLMProgramLang lang ); + bool CheckValidity ( EGLMProgramLang lang ); + + void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that + + void GetLabelIndexCombo ( char *labelOut, int labelOutMaxChars, int *indexOut, int *comboOut ); + void GetComboIndexNameString ( char *stringOut, int stringOutMaxChars ); // mmmmmmmm-nnnnnnnn-filename + +#if GLMDEBUG + bool PollForChanges( void ); // check mirror for changes. + void ReloadStringFromEditable( void ); // populate m_string from editable item (react to change) + bool SyncWithEditable( void ); +#endif + + //=============================== + + // common stuff + + GLMContext *m_ctx; // link back to parent context + + EGLMProgramType m_type; // vertex or pixel + + uint m_nHashTag; // serial number for hashing + + char *m_text; // copy of text passed into constructor. Can change if editable shaders is enabled. + // note - it can contain multiple flavors, so use CGLMTextSectioner to scan it and locate them +#if GLMDEBUG + CGLMEditableTextItem *m_editable; // editable text item for debugging +#endif + + GLMShaderDesc m_descs[ kGLMNumProgramLangs ]; + + uint m_samplerMask; // (1<> 16; + // Apply half pixel offset to output vertices to account for the pixel center difference between D3D9 and OpenGL. + // We output vertices in clip space, which ranges from [-1,1], so 1.0/width in clip space transforms into .5/width in screenspace, see: "Viewports and Clipping (Direct3D 9)" in the DXSDK + float v[4] = { 1.0f / nWidth, 1.0f / nHeight, nWidth, nHeight }; + if ( m_locVertexScreenParams >= 0 ) + gGL->glUniform4fv( m_locVertexScreenParams, 1, v ); + } + + //=============================== + + // common stuff + + GLMContext *m_ctx; // link back to parent context + + CGLMProgram *m_vertexProg; + CGLMProgram *m_fragmentProg; + + GLhandleARB m_program; // linked program object + + // need meta data for attribs / samplers / params + // actually we only need it for samplers and params. + // attributes are hardwired. + + // vertex stage uniforms + GLint m_locVertexParams; // "vc" per dx9asmtogl2 convention + GLint m_locVertexBoneParams; // "vcbones" + GLint m_locVertexInteger0; // "i0" + + GLint m_locVertexBool0; // "b0" + GLint m_locVertexBool1; // "b1" + GLint m_locVertexBool2; // "b2" + GLint m_locVertexBool3; // "b3" + bool m_bHasBoolOrIntUniforms; + + // fragment stage uniforms + GLint m_locFragmentParams; // "pc" per dx9asmtogl2 convention + + int m_NumUniformBufferParams[kGLMNumProgramTypes]; + GLint m_UniformBufferParams[kGLMNumProgramTypes][256]; + + GLint m_locFragmentFakeSRGBEnable; // "flSRGBWrite" - set to 1.0 to effect sRGB encoding on output + float m_fakeSRGBEnableValue; // shadow to avoid redundant sets of the m_locFragmentFakeSRGBEnable uniform + // init it to -1.0 at link or relink, so it will trip on any legit incoming value (0.0 or 1.0) + + GLint m_locSamplers[ 16 ]; // "sampler0 ... sampler1..." + + // other stuff + bool m_valid; // true on successful link + uint m_revision; // if this pair is relinked, bump this number. + + GLint m_locVertexScreenParams; // vcscreen + uint m_nScreenWidthHeight; + +}; + +//=============================================================================== + +// N-row, M-way associative cache with LRU per row. +// still needs some metric dump ability and some parameter tuning. +// extra credit would be to make an auto-tuner. + +struct CGLMPairCacheEntry +{ + long long m_lastMark; // a mark of zero means an empty entry + CGLMProgram *m_vertexProg; + CGLMProgram *m_fragmentProg; + uint m_extraKeyBits; + CGLMShaderPair *m_pair; +}; + +class CGLMShaderPairCache // cache for linked GLSL shader pairs +{ + +public: + +protected: + friend class CGLMShaderPair; + friend class CGLMProgram; + friend class GLMContext; + + //=============================== + + CGLMShaderPairCache( GLMContext *ctx ); + ~CGLMShaderPairCache( ); + + FORCEINLINE CGLMShaderPair *SelectShaderPair ( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ); + void QueryShaderPair ( int index, GLMShaderPairInfo *infoOut ); + + // shoot down linked pairs that use the program in the arg + // return true if any had to be skipped due to conflict with currently bound pair + bool PurgePairsWithShader( CGLMProgram *prog ); + + // purge everything (when would GLM know how to do this ? at context destroy time, but any other times?) + // return true if any had to be skipped due to conflict with currently bound pair + bool Purge ( void ); + + // stats + void DumpStats ( void ); + + //=============================== + + FORCEINLINE uint HashRowIndex( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) const; + FORCEINLINE CGLMPairCacheEntry* HashRowPtr( uint hashRowIndex ) const; + + FORCEINLINE void HashRowProbe( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int &hitway, int &emptyway, int &oldestway ); + + CGLMShaderPair *SelectShaderPairInternal( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int rowIndex ); + //=============================== + + // common stuff + + GLMContext *m_ctx; // link back to parent context + + long long m_mark; + + uint m_rowsLg2; + uint m_rows; + uint m_rowsMask; + + uint m_waysLg2; + uint m_ways; + + uint m_entryCount; + + CGLMPairCacheEntry *m_entries; // array[ m_rows ][ m_ways ] + + uint *m_evictions; // array[ m_rows ]; + +#if GL_SHADER_PAIR_CACHE_STATS + uint *m_hits; // array[ m_rows ]; +#endif +}; + +FORCEINLINE uint CGLMShaderPairCache::HashRowIndex( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) const +{ + return ( vp->m_nHashTag + fp->m_nHashTag + extraKeyBits * 7 ) & m_rowsMask; +} + +FORCEINLINE CGLMPairCacheEntry* CGLMShaderPairCache::HashRowPtr( uint hashRowIndex ) const +{ + return &m_entries[ hashRowIndex * m_ways ]; +} + +FORCEINLINE void CGLMShaderPairCache::HashRowProbe( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int& hitway, int& emptyway, int& oldestway ) +{ + hitway = -1; + emptyway = -1; + oldestway = -1; + + // scan this row to see if the desired pair is present + CGLMPairCacheEntry *cursor = row; + long long oldestmark = 0xFFFFFFFFFFFFFFFFLL; + + for( uint way = 0; way < m_ways; ++way ) + { + if ( cursor->m_lastMark != 0 ) // occupied slot + { + // check if this is the oldest one on the row - only occupied slots are checked + if ( cursor->m_lastMark < oldestmark ) + { + oldestway = way; + oldestmark = cursor->m_lastMark; + } + + if ( ( cursor->m_vertexProg == vp ) && ( cursor->m_fragmentProg == fp ) && ( cursor->m_extraKeyBits == extraKeyBits ) ) // match? + { + // found it + hitway = way; + break; + } + } + else + { + // empty way, log it if first one seen + if (emptyway<0) + { + emptyway = way; + } + } + cursor++; + } +} + +FORCEINLINE CGLMShaderPair *CGLMShaderPairCache::SelectShaderPair( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) +{ + // select row where pair would be found if it exists + uint rowIndex = HashRowIndex( vp, fp, extraKeyBits ); + + CGLMPairCacheEntry *pCursor = HashRowPtr( rowIndex ); + + if ( ( pCursor->m_fragmentProg != fp ) || ( pCursor->m_vertexProg != vp ) || ( pCursor->m_extraKeyBits != extraKeyBits ) ) + { + CGLMPairCacheEntry *pLastCursor = pCursor + m_ways; + + ++pCursor; + + while ( pCursor != pLastCursor ) + { + if ( ( pCursor->m_fragmentProg == fp ) && ( pCursor->m_vertexProg == vp ) && ( pCursor->m_extraKeyBits == extraKeyBits ) ) // match? + break; + ++pCursor; + }; + + if ( pCursor == pLastCursor ) + return SelectShaderPairInternal( vp, fp, extraKeyBits, rowIndex ); + } + + // found it. mark it and return + pCursor->m_lastMark = m_mark++; + +#if GL_SHADER_PAIR_CACHE_STATS + // count the hit + m_hits[ rowIndex ] ++; +#endif + + return pCursor->m_pair; +} + +#endif diff --git a/mp/src/public/togl/linuxwin/cglmquery.h b/mp/src/public/togl/linuxwin/cglmquery.h new file mode 100644 index 00000000..3cf6f79e --- /dev/null +++ b/mp/src/public/togl/linuxwin/cglmquery.h @@ -0,0 +1,90 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmquery.h +// GLMgr queries +// +//=============================================================================== + +#ifndef CGLMQUERY_H +#define CGLMQUERY_H + +#pragma once + +#ifdef OSX +#include "glmgr/glmgrbasics.h" +#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; +class CGLMQuery; + +//=============================================================================== + +enum EGLMQueryType +{ + EOcclusion, + EFence, + EGLMQueryCount +}; + +struct GLMQueryParams +{ + EGLMQueryType m_type; +}; + +class CGLMQuery +{ + // leave everything public til it's running +public: + friend class GLMContext; // only GLMContext can make CGLMTex objects + friend struct IDirect3DDevice9; + friend struct IDirect3DQuery9; + + GLMContext *m_ctx; // link back to parent context + GLMQueryParams m_params; // params created with + + GLuint m_name; // name of the query object per se - could be fence, could be query object ... NOT USED WITH GL_ARB_sync! +#ifdef HAVE_GL_ARB_SYNC + GLsync m_syncobj; // GL_ARB_sync object. NOT USED WITH GL_NV_fence or GL_APPLE_fence! +#else + GLuint m_syncobj; +#endif + + bool m_started; + bool m_stopped; + bool m_done; + + bool m_nullQuery; // was gl_nullqueries true at Start time - if so, continue to act like a null query through Stop/IsDone/Complete time + // restated - only Start should examine the convar. + static uint s_nTotalOcclusionQueryCreatesOrDeletes; + + CGLMQuery( GLMContext *ctx, GLMQueryParams *params ); + ~CGLMQuery( ); + + // for an occlusion query: + // Start = BeginQuery query-start goes into stream + // Stop = EndQuery query-end goes into stream - a fence is also set so we can probe for completion + // IsDone = TestFence use the added fence to ask if query-end has passed (i.e. will Complete block?) + // Complete = GetQueryObjectuivARB(uint id, enum pname, uint *params) - extract the sample count + + // for a fence query: + // Start = SetFence fence goes into command stream + // Stop = NOP fences are self finishing - no need to call Stop on a fence + // IsDone = TestFence ask if fence passed + // Complete = FinishFence + + void Start ( void ); + void Stop ( void ); + bool IsDone ( void ); + void Complete ( uint *result ); + + // accessors for the started/stopped state + bool IsStarted ( void ); + bool IsStopped ( void ); +}; + + +#endif diff --git a/mp/src/public/togl/linuxwin/cglmtex.h b/mp/src/public/togl/linuxwin/cglmtex.h new file mode 100644 index 00000000..bdb83776 --- /dev/null +++ b/mp/src/public/togl/linuxwin/cglmtex.h @@ -0,0 +1,502 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmtex.h +// GLMgr textures +// +//=============================================================================== + +#ifndef CGLMTEX_H +#define CGLMTEX_H + +#pragma once + +#ifdef OSX +#include "glmgr/glmgrbasics.h" +#endif +#include "tier1/utlhash.h" +#include "tier1/utlmap.h" + +//=============================================================================== + +// forward declarations + +class GLMContext; +class GLMTester; +class CGLMTexLayoutTable; +class CGLMTex; +class CGLMFBO; + +struct IDirect3DSurface9; + +#if GLMDEBUG +extern CGLMTex *g_pFirstCGMLTex; +#endif + +// For GL_EXT_texture_sRGB_decode +#ifndef GL_TEXTURE_SRGB_DECODE_EXT +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#endif + +#ifndef GL_DECODE_EXT +#define GL_DECODE_EXT 0x8A49 +#endif + +#ifndef GL_SKIP_DECODE_EXT +#define GL_SKIP_DECODE_EXT 0x8A4A +#endif + +//=============================================================================== + +struct GLMTexFormatDesc +{ + const char *m_formatSummary; // for debug visibility + + D3DFORMAT m_d3dFormat; // what D3D knows it as; see public/bitmap/imageformat.h + + GLenum m_glIntFormat; // GL internal format + GLenum m_glIntFormatSRGB; // internal format if SRGB flavor + GLenum m_glDataFormat; // GL data format + GLenum m_glDataType; // GL data type + + int m_chunkSize; // 1 or 4 - 4 is used for compressed textures + int m_bytesPerSquareChunk; // how many bytes for the smallest quantum (m_chunkSize x m_chunkSize) + // this description lets us calculate size cleanly without conditional logic for compression +}; +const GLMTexFormatDesc *GetFormatDesc( D3DFORMAT format ); + +//=============================================================================== + +// utility function for generating slabs of texels. mostly for test. +typedef struct +{ + // in + D3DFORMAT m_format; + void *m_dest; // dest address + int m_chunkCount; // square chunk count (single texels or compressed blocks) + int m_byteCountLimit; // caller expectation of max number of bytes to write out + float r,g,b,a; // color desired + + // out + int m_bytesWritten; +} GLMGenTexelParams; + +// return true if successful +bool GLMGenTexels( GLMGenTexelParams *params ); + + +//=============================================================================== + +struct GLMTexLayoutSlice +{ + int m_xSize,m_ySize,m_zSize; //texel dimensions of this slice + int m_storageOffset; //where in the storage slab does this slice live + int m_storageSize; //how much storage does this slice occupy +}; + +enum EGLMTexFlags +{ + kGLMTexMipped = 0x01, + kGLMTexMippedAuto = 0x02, + kGLMTexRenderable = 0x04, + kGLMTexIsStencil = 0x08, + kGLMTexIsDepth = 0x10, + kGLMTexSRGB = 0x20, + kGLMTexMultisampled = 0x40, // has an RBO backing it. Cannot combine with Mipped, MippedAuto. One slice maximum, only targeting GL_TEXTURE_2D. + // actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could + // have mipmaps generated. +}; + +//=============================================================================== + +struct GLMTexLayoutKey +{ + // input values: held const, these are the hash key for the form map + GLenum m_texGLTarget; // flavor of texture: GL_TEXTURE_2D, GL_TEXTURE_3D, GLTEXTURE_CUBE_MAP + D3DFORMAT m_texFormat; // D3D texel format + unsigned long m_texFlags; // mipped, autogen mips, render target, ... ? + unsigned long m_texSamples; // zero for a plain tex, 2/4/6/8 for "MSAA tex" (RBO backed) + int m_xSize,m_ySize,m_zSize; // size of base mip +}; + +bool LessFunc_GLMTexLayoutKey( const GLMTexLayoutKey &a, const GLMTexLayoutKey &b ); + +#define GLM_TEX_MAX_MIPS 14 +#define GLM_TEX_MAX_FACES 6 +#define GLM_TEX_MAX_SLICES (GLM_TEX_MAX_MIPS * GLM_TEX_MAX_FACES) + +#pragma warning( push ) +#pragma warning( disable : 4200 ) + +struct GLMTexLayout +{ + char *m_layoutSummary; // for debug visibility + + // const inputs used for hashing + GLMTexLayoutKey m_key; + + // refcount + int m_refCount; + + // derived values: + GLMTexFormatDesc *m_format; // format specific info + int m_mipCount; // derived by starying at base size and working down towards 1x1 + int m_faceCount; // 1 for 2d/3d, 6 for cubemap + int m_sliceCount; // product of faces and mips + int m_storageTotalSize; // size of storage slab required + + // slice array + GLMTexLayoutSlice m_slices[0]; // dynamically allocated 2-d array [faces][mips] +}; + +#pragma warning( pop ) + +class CGLMTexLayoutTable +{ +public: + CGLMTexLayoutTable(); + + GLMTexLayout *NewLayoutRef( GLMTexLayoutKey *pDesiredKey ); // pass in a pointer to layout key - receive ptr to completed layout + void DelLayoutRef( GLMTexLayout *layout ); // pass in pointer to completed layout. refcount is dropped. + + void DumpStats( void ); +protected: + CUtlMap< GLMTexLayoutKey, GLMTexLayout* > m_layoutMap; +}; + +//=============================================================================== + +// a sampler specifies desired state for drawing on a given sampler index +// this is the combination of a texture choice and a set of sampler parameters +// see http://msdn.microsoft.com/en-us/library/bb172602(VS.85).aspx + +struct GLMTexLockParams +{ + // input params which identify the slice of interest + CGLMTex *m_tex; + int m_face; + int m_mip; + + // identifies the region of the slice + GLMRegion m_region; + + // tells GLM to force re-read of the texels back from GL + // i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale" + bool m_readback; +}; + +struct GLMTexLockDesc +{ + GLMTexLockParams m_req; // form of the lock request + + bool m_active; // set true at lock time. cleared at unlock time. + + int m_sliceIndex; // which slice in the layout + int m_sliceBaseOffset; // where is that in the texture data + int m_sliceRegionOffset; // offset to the start (lowest address corner) of the region requested +}; + +//=============================================================================== + +#define GLM_SAMPLER_COUNT 16 + +typedef CBitVec CTexBindMask; + +enum EGLMTexSliceFlag +{ + kSliceValid = 0x01, // slice has been teximage'd in whole at least once - set to 0 initially + kSliceStorageValid = 0x02, // if backing store is available, this slice's data is a valid copy - set to 0 initially + kSliceLocked = 0x04, // are one or more locks outstanding on this slice + kSliceFullyDirty = 0x08, // does the slice need to be fully downloaded at unlock time (disregard dirty rects) +}; + +//=============================================================================== + +#define GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS (2) +#define GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS (2) +#define GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS (2) +#define GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS (2) +#define GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS (4) +#define GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS (5) +#define GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS (1) +#define GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS (1) + +struct GLMTexPackedSamplingParams +{ + uint32 m_addressU : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS; + uint32 m_addressV : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS; + uint32 m_addressW : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS; + + uint32 m_minFilter : GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS; + uint32 m_magFilter : GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS; + uint32 m_mipFilter : GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS; + + uint32 m_minLOD : GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS; + uint32 m_maxAniso : GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS; + uint32 m_compareMode : GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS; + uint32 m_srgb : GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS; + uint32 m_isValid : 1; +}; + +struct GLMTexSamplingParams +{ + union + { + GLMTexPackedSamplingParams m_packed; + uint32 m_bits; + }; + + uint32 m_borderColor; + + FORCEINLINE bool operator== (const GLMTexSamplingParams& rhs ) const + { + return ( m_bits == rhs.m_bits ) && ( m_borderColor == rhs.m_borderColor ); + } + + FORCEINLINE void SetToDefaults() + { + m_bits = 0; + m_borderColor = 0; + m_packed.m_addressU = D3DTADDRESS_WRAP; + m_packed.m_addressV = D3DTADDRESS_WRAP; + m_packed.m_addressW = D3DTADDRESS_WRAP; + m_packed.m_minFilter = D3DTEXF_POINT; + m_packed.m_magFilter = D3DTEXF_POINT; + m_packed.m_mipFilter = D3DTEXF_NONE; + m_packed.m_maxAniso = 1; + m_packed.m_isValid = true; + } + + FORCEINLINE void SetToSamplerObject( GLuint nSamplerObject ) const + { + static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 }; + static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR }; + static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter]. + { + /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT + /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling + }; + + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso ); + + float flBorderColor[4] = { 0, 0, 0, 0 }; + if ( m_borderColor ) + { + flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R + flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G + flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B + flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A + } + gGL->glSamplerParameterfv( nSamplerObject, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ); + if ( m_packed.m_compareMode ) + { + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); + } + if ( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) + { + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ); + } + } + + inline void DeltaSetToTarget( GLenum target, const GLMTexSamplingParams &curState ) + { + static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 }; + static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR }; + static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter]. + { + /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT + /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling + }; + + if ( m_packed.m_addressU != curState.m_packed.m_addressU ) + { + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] ); + } + + if ( m_packed.m_addressV != curState.m_packed.m_addressV ) + { + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] ); + } + + if ( m_packed.m_addressW != curState.m_packed.m_addressW ) + { + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] ); + } + + if ( ( m_packed.m_minFilter != curState.m_packed.m_minFilter ) || + ( m_packed.m_magFilter != curState.m_packed.m_magFilter ) || + ( m_packed.m_mipFilter != curState.m_packed.m_mipFilter ) || + ( m_packed.m_maxAniso != curState.m_packed.m_maxAniso ) ) + { + gGL->glTexParameteri( target, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] ); + gGL->glTexParameteri( target, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] ); + gGL->glTexParameteri( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso ); + } + + if ( m_borderColor != curState.m_borderColor ) + { + float flBorderColor[4] = { 0, 0, 0, 0 }; + if ( m_borderColor ) + { + flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R + flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G + flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B + flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A + } + + gGL->glTexParameterfv( target, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out + } + + if ( m_packed.m_minLOD != curState.m_packed.m_minLOD ) + { + gGL->glTexParameteri( target, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD ); + } + + if ( m_packed.m_compareMode != curState.m_packed.m_compareMode ) + { + gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ); + if ( m_packed.m_compareMode ) + { + gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); + } + } + + if ( ( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) && ( m_packed.m_srgb != curState.m_packed.m_srgb ) ) + { + gGL->glTexParameteri( target, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ); + } + } + + inline void SetToTargetTexture( GLenum target ) + { + static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 }; + static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR }; + static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter]. + { + /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT + /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling + }; + + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] ); + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] ); + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] ); + gGL->glTexParameteri( target, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] ); + gGL->glTexParameteri( target, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] ); + gGL->glTexParameteri( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso ); + + float flBorderColor[4] = { 0, 0, 0, 0 }; + if ( m_borderColor ) + { + flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R + flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G + flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B + flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A + } + gGL->glTexParameterfv( target, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out + gGL->glTexParameteri( target, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD ); + gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ); + if ( m_packed.m_compareMode ) + { + gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); + } + if ( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) + { + gGL->glTexParameteri( target, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ); + } + } +}; + +//=============================================================================== + +class CGLMTex +{ + +public: + + void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut ); + void Unlock( GLMTexLockParams *params ); + +protected: + friend class GLMContext; // only GLMContext can make CGLMTex objects + friend class GLMTester; + friend class CGLMFBO; + + friend struct IDirect3DDevice9; + friend struct IDirect3DBaseTexture9; + friend struct IDirect3DTexture9; + friend struct IDirect3DSurface9; + friend struct IDirect3DCubeTexture9; + friend struct IDirect3DVolumeTexture9; + + CGLMTex( GLMContext *ctx, GLMTexLayout *layout, const char *debugLabel = NULL ); + ~CGLMTex( ); + + int CalcSliceIndex( int face, int mip ); + void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut ); + + void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true ); + void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false ); + // last param lets us send NULL data ptr (only legal with uncompressed formats, beware) + // this helps out ResetSRGB. + + bool IsRBODirty() const; + void ForceRBONonDirty(); + void ForceRBODirty(); + + void AllocBacking(); + void ReleaseBacking(); + + // re-specify texture format to match desired sRGB form + // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's + + GLuint m_texName; // name of this texture in the context + GLenum m_texGLTarget; + uint m_nSamplerType; // SAMPLER_2D, etc. + GLMTexSamplingParams m_SamplingParams; + GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout) + + uint m_nLastResolvedBatchCounter; + + int m_minActiveMip;//index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. + int m_maxActiveMip;//index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. + int m_mipCount; + + GLMContext *m_ctx; // link back to parent context + + CGLMFBO *m_pBlitSrcFBO; + CGLMFBO *m_pBlitDstFBO; + + GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero) + + int m_rtAttachCount; // how many RT's have this texture attached somewhere + + char *m_pBacking; // backing storage if available + + int m_lockCount; // lock reqs are stored in the GLMContext for tracking + + CUtlVector m_sliceFlags; + + char *m_debugLabel; // strdup() of debugLabel passed in, or NULL + + bool m_texClientStorage; // was CS selected for texture + bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet + +#if GLMDEBUG + CGLMTex *m_pPrevTex; + CGLMTex *m_pNextTex; +#endif +}; + +#endif diff --git a/mp/src/public/togl/linuxwin/dxabstract.h b/mp/src/public/togl/linuxwin/dxabstract.h new file mode 100644 index 00000000..ab5940e5 --- /dev/null +++ b/mp/src/public/togl/linuxwin/dxabstract.h @@ -0,0 +1,1412 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// dxabstract.h +// +//================================================================================================== +#ifndef DXABSTRACT_H +#define DXABSTRACT_H + +#ifdef DX_TO_GL_ABSTRACTION + +#include "togl/rendermechanism.h" + +#include "tier0/platform.h" +#include "tier0/dbg.h" +#include "tier1/utlmap.h" + +// turn this on to get refcount logging from IUnknown +#define IUNKNOWN_ALLOC_SPEW 0 +#define IUNKNOWN_ALLOC_SPEW_MARK_ALL 0 + +TOGL_INTERFACE void toglGetClientRect( VD3DHWND hWnd, RECT *destRect ); + +struct TOGL_CLASS IUnknown +{ + int m_refcount[2]; + bool m_mark; + + IUnknown() + { + m_refcount[0] = 1; + m_refcount[1] = 0; + m_mark = (IUNKNOWN_ALLOC_SPEW_MARK_ALL != 0); // either all are marked, or only the ones that have SetMark(true) called on them + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUnew (%08x) refc -> (%d,%d) ",this,m_refcount[0],m_refcount[1])); + } + #endif + }; + + virtual ~IUnknown() + { + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUdel (%08x) ",this )); + } + #endif + }; + + void AddRef( int which=0, char *comment = NULL ) + { + Assert( which >= 0 ); + Assert( which < 2 ); + m_refcount[which]++; + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUAddRef (%08x,%d) refc -> (%d,%d) [%s]",this,which,m_refcount[0],m_refcount[1],comment?comment:"...")) ; + if (!comment) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + } + #endif + }; + + ULONG __stdcall Release( int which=0, char *comment = NULL ) + { + Assert( which >= 0 ); + Assert( which < 2 ); + + //int oldrefcs[2] = { m_refcount[0], m_refcount[1] }; + bool deleting = false; + + m_refcount[which]--; + if ( (!m_refcount[0]) && (!m_refcount[1]) ) + { + deleting = true; + } + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IURelease (%08x,%d) refc -> (%d,%d) [%s] %s",this,which,m_refcount[0],m_refcount[1],comment?comment:"...",deleting?"->DELETING":"")); + if (!comment) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + } + #endif + + if (deleting) + { + if (m_mark) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + delete this; + return 0; + } + else + { + return m_refcount[0]; + } + }; + + void SetMark( bool markValue, char *comment=NULL ) + { + #if IUNKNOWN_ALLOC_SPEW + if (!m_mark && markValue) // leading edge detect + { + // print the same thing that the constructor would have printed if it had been marked from the beginning + // i.e. it's anticipated that callers asking for marking will do so right at create time + GLMPRINTF(("-A- IUSetMark (%08x) refc -> (%d,%d) (%s) ",this,m_refcount[0],m_refcount[1],comment?comment:"...")); + } + #endif + + m_mark = markValue; + } +}; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// INTERFACES +// ------------------------------------------------------------------------------------------------------------------------------ // + +struct TOGL_CLASS IDirect3DResource9 : public IUnknown +{ + IDirect3DDevice9 *m_device; // parent device + D3DRESOURCETYPE m_restype; + + DWORD SetPriority(DWORD PriorityNew); +}; + +struct TOGL_CLASS IDirect3DBaseTexture9 : public IDirect3DResource9 // "A Texture.." +{ + D3DSURFACE_DESC m_descZero; // desc of top level. + CGLMTex *m_tex; // a CGLMTex can represent all forms of tex + int m_srgbFlipCount; + + virtual ~IDirect3DBaseTexture9(); + D3DRESOURCETYPE TOGLMETHODCALLTYPE GetType(); + DWORD TOGLMETHODCALLTYPE GetLevelCount(); + HRESULT TOGLMETHODCALLTYPE GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DTexture9 : public IDirect3DBaseTexture9 // "Texture 2D" +{ + IDirect3DSurface9 *m_surfZero; // surf of top level. + virtual ~IDirect3DTexture9(); + HRESULT TOGLMETHODCALLTYPE LockRect(UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); + HRESULT TOGLMETHODCALLTYPE UnlockRect(UINT Level); + HRESULT TOGLMETHODCALLTYPE GetSurfaceLevel(UINT Level,IDirect3DSurface9** ppSurfaceLevel); +}; + +struct TOGL_CLASS IDirect3DCubeTexture9 : public IDirect3DBaseTexture9 // "Texture Cube Map" +{ + IDirect3DSurface9 *m_surfZero[6]; // surfs of top level. + virtual ~IDirect3DCubeTexture9(); + HRESULT TOGLMETHODCALLTYPE GetCubeMapSurface(D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface); + HRESULT TOGLMETHODCALLTYPE GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DVolumeTexture9 : public IDirect3DBaseTexture9 // "Texture 3D" +{ + IDirect3DSurface9 *m_surfZero; // surf of top level. + D3DVOLUME_DESC m_volDescZero; // volume desc top level + virtual ~IDirect3DVolumeTexture9(); + HRESULT TOGLMETHODCALLTYPE LockBox(UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags); + HRESULT TOGLMETHODCALLTYPE UnlockBox(UINT Level); + HRESULT TOGLMETHODCALLTYPE GetLevelDesc( UINT level, D3DVOLUME_DESC *pDesc ); +}; + + +// for the moment, a "D3D surface" is modeled as a GLM tex, a face, and a mip. +// no Create method, these are filled in by the various create surface methods. + +struct TOGL_CLASS IDirect3DSurface9 : public IDirect3DResource9 +{ + virtual ~IDirect3DSurface9(); + HRESULT TOGLMETHODCALLTYPE LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); + HRESULT TOGLMETHODCALLTYPE UnlockRect(); + HRESULT TOGLMETHODCALLTYPE GetDesc(D3DSURFACE_DESC *pDesc); + + D3DSURFACE_DESC m_desc; + CGLMTex *m_tex; + int m_face; + int m_mip; +}; + +struct TOGL_CLASS IDirect3D9 : public IUnknown +{ + virtual ~IDirect3D9(); + + UINT TOGLMETHODCALLTYPE GetAdapterCount(); + + HRESULT TOGLMETHODCALLTYPE GetDeviceCaps (UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps); + HRESULT TOGLMETHODCALLTYPE GetAdapterIdentifier (UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier); + HRESULT TOGLMETHODCALLTYPE CheckDeviceFormat (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat); + UINT TOGLMETHODCALLTYPE GetAdapterModeCount (UINT Adapter,D3DFORMAT Format); + HRESULT TOGLMETHODCALLTYPE EnumAdapterModes (UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode); + HRESULT TOGLMETHODCALLTYPE CheckDeviceType (UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed); + HRESULT TOGLMETHODCALLTYPE GetAdapterDisplayMode (UINT Adapter,D3DDISPLAYMODE* pMode); + HRESULT TOGLMETHODCALLTYPE CheckDepthStencilMatch (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat); + HRESULT TOGLMETHODCALLTYPE CheckDeviceMultiSampleType (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels); + + HRESULT TOGLMETHODCALLTYPE CreateDevice (UINT Adapter,D3DDEVTYPE DeviceType,VD3DHWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface); +}; + +struct TOGL_CLASS IDirect3DVertexDeclaration9 : public IUnknown +{ + IDirect3DDevice9 *m_device; + uint m_elemCount; + D3DVERTEXELEMENT9_GL m_elements[ MAX_D3DVERTEXELEMENTS ]; + + uint8 m_VertexAttribDescToStreamIndex[256]; + + virtual ~IDirect3DVertexDeclaration9(); +}; + +struct TOGL_CLASS IDirect3DQuery9 : public IDirect3DResource9 //was IUnknown +{ + D3DQUERYTYPE m_type; // D3DQUERYTYPE_OCCLUSION or D3DQUERYTYPE_EVENT + GLMContext *m_ctx; + CGLMQuery *m_query; + + uint m_nIssueStartThreadID, m_nIssueEndThreadID; + uint m_nIssueStartDrawCallIndex, m_nIssueEndDrawCallIndex; + uint m_nIssueStartFrameIndex, m_nIssueEndFrameIndex; + uint m_nIssueStartQueryCreationCounter, m_nIssueEndQueryCreationCounter; + + virtual ~IDirect3DQuery9(); + + HRESULT Issue(DWORD dwIssueFlags); + HRESULT GetData(void* pData,DWORD dwSize,DWORD dwGetDataFlags); +}; + +struct TOGL_CLASS IDirect3DVertexBuffer9 : public IDirect3DResource9 //was IUnknown +{ + GLMContext *m_ctx; + CGLMBuffer *m_vtxBuffer; + D3DVERTEXBUFFER_DESC m_vtxDesc; // to satisfy GetDesc + + virtual ~IDirect3DVertexBuffer9(); + HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); + HRESULT Unlock(); + void UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); +}; + +struct TOGL_CLASS IDirect3DIndexBuffer9 : public IDirect3DResource9 //was IUnknown +{ + GLMContext *m_ctx; + CGLMBuffer *m_idxBuffer; + D3DINDEXBUFFER_DESC m_idxDesc; // to satisfy GetDesc + + virtual ~IDirect3DIndexBuffer9(); + + HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); + HRESULT Unlock(); + void UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); + + HRESULT GetDesc(D3DINDEXBUFFER_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DPixelShader9 : public IDirect3DResource9 //was IUnknown +{ + CGLMProgram *m_pixProgram; + uint m_pixHighWater; // count of active constant slots referenced by shader. + uint m_pixSamplerMask; // (1< CD3DMATRIXAllocator; + typedef class TOGL_CLASS CUtlVector CD3DMATRIXStack; +#else + typedef class CUtlMemory CD3DMATRIXAllocator; + typedef class CUtlVector CD3DMATRIXStack; +#endif + +struct TOGL_CLASS ID3DXMatrixStack //: public IUnknown +{ + int m_refcount[2]; + bool m_mark; + CD3DMATRIXStack m_stack; + int m_stackTop; // top of stack is at the highest index, this is that index. push increases, pop decreases. + + ID3DXMatrixStack(); + void AddRef( int which=0, char *comment = NULL ); + ULONG Release( int which=0, char *comment = NULL ); + + HRESULT Create( void ); + + D3DXMATRIX* GetTop(); + void Push(); + void Pop(); + void LoadIdentity(); + void LoadMatrix( const D3DXMATRIX *pMat ); + void MultMatrix( const D3DXMATRIX *pMat ); + void MultMatrixLocal( const D3DXMATRIX *pMat ); + HRESULT ScaleLocal(FLOAT x, FLOAT y, FLOAT z); + + // Left multiply the current matrix with the computed rotation + // matrix, counterclockwise about the given axis with the given angle. + // (rotation is about the local origin of the object) + HRESULT RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle); + + // Left multiply the current matrix with the computed translation + // matrix. (transformation is about the local origin of the object) + HRESULT TranslateLocal(FLOAT x, FLOAT y, FLOAT z); +}; + +typedef ID3DXMatrixStack* LPD3DXMATRIXSTACK; + +struct RenderTargetState_t +{ + void clear() { V_memset( this, 0, sizeof( *this ) ); } + + CGLMTex *m_pRenderTargets[4]; + CGLMTex *m_pDepthStencil; + + inline bool RefersTo( CGLMTex * pSurf ) const + { + for ( uint i = 0; i < 4; i++ ) + if ( m_pRenderTargets[i] == pSurf ) + return true; + + if ( m_pDepthStencil == pSurf ) + return true; + + return false; + } + + static inline bool LessFunc( const RenderTargetState_t &lhs, const RenderTargetState_t &rhs ) + { + COMPILE_TIME_ASSERT( sizeof( lhs.m_pRenderTargets[0] ) == sizeof( uint32 ) ); + uint64 lhs0 = reinterpret_cast(lhs.m_pRenderTargets)[0]; + uint64 rhs0 = reinterpret_cast(rhs.m_pRenderTargets)[0]; + if ( lhs0 < rhs0 ) + return true; + else if ( lhs0 == rhs0 ) + { + uint64 lhs1 = reinterpret_cast(lhs.m_pRenderTargets)[1]; + uint64 rhs1 = reinterpret_cast(rhs.m_pRenderTargets)[1]; + if ( lhs1 < rhs1 ) + return true; + else if ( lhs1 == rhs1 ) + { + return lhs.m_pDepthStencil < rhs.m_pDepthStencil; + } + } + return false; + } + + inline bool operator < ( const RenderTargetState_t &rhs ) const + { + return LessFunc( *this, rhs ); + } +}; + +typedef CUtlMap< RenderTargetState_t, CGLMFBO *> CGLMFBOMap; + +class simple_bitmap; + +struct TOGL_CLASS IDirect3DDevice9 : public IUnknown +{ + friend class GLMContext; + friend struct IDirect3DBaseTexture9; + friend struct IDirect3DTexture9; + friend struct IDirect3DCubeTexture9; + friend struct IDirect3DVolumeTexture9; + friend struct IDirect3DSurface9; + friend struct IDirect3DVertexBuffer9; + friend struct IDirect3DIndexBuffer9; + friend struct IDirect3DPixelShader9; + friend struct IDirect3DVertexShader9; + friend struct IDirect3DQuery9; + friend struct IDirect3DVertexDeclaration9; + + IDirect3DDevice9(); + virtual ~IDirect3DDevice9(); + + // Create call invoked from IDirect3D9 + HRESULT TOGLMETHODCALLTYPE Create( IDirect3DDevice9Params *params ); + + // + // Basics + // + HRESULT TOGLMETHODCALLTYPE Reset(D3DPRESENT_PARAMETERS* pPresentationParameters); + HRESULT TOGLMETHODCALLTYPE SetViewport(CONST D3DVIEWPORT9* pViewport); + HRESULT TOGLMETHODCALLTYPE BeginScene(); + HRESULT TOGLMETHODCALLTYPE Clear(DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil); + HRESULT TOGLMETHODCALLTYPE EndScene(); + HRESULT TOGLMETHODCALLTYPE Present(CONST RECT* pSourceRect,CONST RECT* pDestRect,VD3DHWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion); + + // textures + HRESULT TOGLMETHODCALLTYPE CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,VD3DHANDLE* pSharedHandle, char *debugLabel=NULL); + HRESULT TOGLMETHODCALLTYPE CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,VD3DHANDLE* pSharedHandle, char *debugLabel=NULL); + HRESULT TOGLMETHODCALLTYPE CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,VD3DHANDLE* pSharedHandle, char *debugLabel=NULL); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetTexture(DWORD Stage,IDirect3DBaseTexture9* pTexture); + HRESULT TOGLMETHODCALLTYPE SetTextureNonInline(DWORD Stage,IDirect3DBaseTexture9* pTexture); + + HRESULT TOGLMETHODCALLTYPE GetTexture(DWORD Stage,IDirect3DBaseTexture9** ppTexture); + + // render targets, color and depthstencil, surfaces, blit + HRESULT TOGLMETHODCALLTYPE CreateRenderTarget(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle, char *debugLabel=NULL); + HRESULT TOGLMETHODCALLTYPE SetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget); + HRESULT TOGLMETHODCALLTYPE GetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget); + + HRESULT TOGLMETHODCALLTYPE CreateOffscreenPlainSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle); + + HRESULT TOGLMETHODCALLTYPE CreateDepthStencilSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle); + HRESULT TOGLMETHODCALLTYPE SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil); + HRESULT TOGLMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface); + + HRESULT TOGLMETHODCALLTYPE GetRenderTargetData(IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface); // ? is anyone using this ? + HRESULT TOGLMETHODCALLTYPE GetFrontBufferData(UINT iSwapChain,IDirect3DSurface9* pDestSurface); + HRESULT TOGLMETHODCALLTYPE StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter); + + // pixel shaders + HRESULT TOGLMETHODCALLTYPE CreatePixelShader(CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader, const char *pShaderName, char *debugLabel = NULL, const uint32 *pCentroidMask = NULL ); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetPixelShader(IDirect3DPixelShader9* pShader); + HRESULT TOGLMETHODCALLTYPE SetPixelShaderNonInline(IDirect3DPixelShader9* pShader); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount); + HRESULT TOGLMETHODCALLTYPE SetPixelShaderConstantFNonInline(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount); + + HRESULT TOGLMETHODCALLTYPE SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount); + HRESULT TOGLMETHODCALLTYPE SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount); + + // vertex shaders + HRESULT TOGLMETHODCALLTYPE CreateVertexShader(CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader, const char *pShaderName, char *debugLabel = NULL); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexShader(IDirect3DVertexShader9* pShader); + HRESULT TOGLMETHODCALLTYPE SetVertexShaderNonInline(IDirect3DVertexShader9* pShader); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount); + HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantFNonInline(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount); + HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantBNonInline(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount); + HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantINonInline(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount); + + // POSIX only - preheating for a specific vertex/pixel shader pair - trigger GLSL link inside GLM + HRESULT TOGLMETHODCALLTYPE LinkShaderPair( IDirect3DVertexShader9* vs, IDirect3DPixelShader9* ps ); + HRESULT TOGLMETHODCALLTYPE QueryShaderPair( int index, GLMShaderPairInfo *infoOut ); + + // vertex buffers + HRESULT TOGLMETHODCALLTYPE CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl); + HRESULT TOGLMETHODCALLTYPE SetVertexDeclarationNonInline(IDirect3DVertexDeclaration9* pDecl); + + HRESULT TOGLMETHODCALLTYPE SetFVF(DWORD FVF); // we might not be using these ? + HRESULT TOGLMETHODCALLTYPE GetFVF(DWORD* pFVF); + + HRESULT CreateVertexBuffer(UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,VD3DHANDLE* pSharedHandle); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride); + HRESULT SetStreamSourceNonInline(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride); + + // index buffers + HRESULT TOGLMETHODCALLTYPE CreateIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,VD3DHANDLE* pSharedHandle); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetIndices(IDirect3DIndexBuffer9* pIndexData); + HRESULT TOGLMETHODCALLTYPE SetIndicesNonInline(IDirect3DIndexBuffer9* pIndexData); + + // State management. + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetRenderStateInline(D3DRENDERSTATETYPE State,DWORD Value); + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetRenderStateConstInline(D3DRENDERSTATETYPE State,DWORD Value); + HRESULT TOGLMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State,DWORD Value); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetSamplerState(DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value); + HRESULT TOGLMETHODCALLTYPE SetSamplerStateNonInline(DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value); + + FORCEINLINE void TOGLMETHODCALLTYPE SetSamplerStates(DWORD Sampler, DWORD AddressU, DWORD AddressV, DWORD AddressW, DWORD MinFilter, DWORD MagFilter, DWORD MipFilter ); + void TOGLMETHODCALLTYPE SetSamplerStatesNonInline(DWORD Sampler, DWORD AddressU, DWORD AddressV, DWORD AddressW, DWORD MinFilter, DWORD MagFilter, DWORD MipFilter ); + + // Draw. + HRESULT TOGLMETHODCALLTYPE DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount); + HRESULT TOGLMETHODCALLTYPE DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount); + HRESULT TOGLMETHODCALLTYPE DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride); + + // misc + BOOL TOGLMETHODCALLTYPE ShowCursor(BOOL bShow); + HRESULT TOGLMETHODCALLTYPE ValidateDevice(DWORD* pNumPasses); + HRESULT TOGLMETHODCALLTYPE SetMaterial(CONST D3DMATERIAL9* pMaterial); + HRESULT TOGLMETHODCALLTYPE LightEnable(DWORD Index,BOOL Enable); + HRESULT TOGLMETHODCALLTYPE SetScissorRect(CONST RECT* pRect); + HRESULT TOGLMETHODCALLTYPE CreateQuery(D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery); + HRESULT TOGLMETHODCALLTYPE GetDeviceCaps(D3DCAPS9* pCaps); + HRESULT TOGLMETHODCALLTYPE TestCooperativeLevel(); + HRESULT TOGLMETHODCALLTYPE EvictManagedResources(); + HRESULT TOGLMETHODCALLTYPE SetLight(DWORD Index,CONST D3DLIGHT9*); + void TOGLMETHODCALLTYPE SetGammaRamp(UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp); + + void TOGLMETHODCALLTYPE SaveGLState(); + void TOGLMETHODCALLTYPE RestoreGLState(); + + // Talk to JasonM about this one. It's tricky in GL. + HRESULT TOGLMETHODCALLTYPE SetClipPlane(DWORD Index,CONST float* pPlane); + + // + // + // **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. + // + // + HRESULT TOGLMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix); + HRESULT TOGLMETHODCALLTYPE SetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value); + + void TOGLMETHODCALLTYPE AcquireThreadOwnership( ); + void TOGLMETHODCALLTYPE ReleaseThreadOwnership( ); + inline DWORD TOGLMETHODCALLTYPE GetCurrentOwnerThreadId() const { return m_ctx->m_nCurOwnerThreadId; } + + FORCEINLINE void TOGLMETHODCALLTYPE SetMaxUsedVertexShaderConstantsHint( uint nMaxReg ); + void TOGLMETHODCALLTYPE SetMaxUsedVertexShaderConstantsHintNonInline( uint nMaxReg ); + + void DumpStatsToConsole( const CCommand *pArgs ); + +#if GLMDEBUG + void DumpTextures( const CCommand *pArgs ); +#endif + +private: + IDirect3DDevice9( const IDirect3DDevice9& ); + IDirect3DDevice9& operator= ( const IDirect3DDevice9& ); + + // Flushing changes to GL + void FlushClipPlaneEquation(); + void InitStates(); + void FullFlushStates(); + void UpdateBoundFBO(); + void ResetFBOMap(); + void ScrubFBOMap( CGLMTex *pTex ); + + // response to retired objects (when refcount goes to zero and they self-delete..) + void ReleasedVertexDeclaration( IDirect3DVertexDeclaration9 *pDecl ); + void ReleasedTexture( IDirect3DBaseTexture9 *baseTex ); // called from texture destructor - need to scrub samplers + void ReleasedCGLMTex( CGLMTex *pTex ); + void ReleasedSurface( IDirect3DSurface9 *surface ); // called from any surface destructor - need to scrub RT table if an RT + void ReleasedPixelShader( IDirect3DPixelShader9 *pixelShader ); // called from IDirect3DPixelShader9 destructor + void ReleasedVertexShader( IDirect3DVertexShader9 *vertexShader ); // called from IDirect3DVertexShader9 destructor + void ReleasedVertexBuffer( IDirect3DVertexBuffer9 *vertexBuffer ); // called from IDirect3DVertexBuffer9 destructor + void ReleasedIndexBuffer( IDirect3DIndexBuffer9 *indexBuffer ); // called from IDirect3DIndexBuffer9 destructor + void ReleasedQuery( IDirect3DQuery9 *query ); // called from IDirect3DQuery9 destructor + + // Member variables + + DWORD m_nValidMarker; + + IDirect3DDevice9Params m_params; // mirror of the creation inputs + + // D3D flavor stuff + IDirect3DSurface9 *m_pRenderTargets[4]; + IDirect3DSurface9 *m_pDepthStencil; + + IDirect3DSurface9 *m_pDefaultColorSurface; // default color surface. + IDirect3DSurface9 *m_pDefaultDepthStencilSurface; // queried by GetDepthStencilSurface. + + IDirect3DVertexDeclaration9 *m_pVertDecl; // Set by SetVertexDeclaration... + D3DStreamDesc m_streams[ D3D_MAX_STREAMS ]; // Set by SetStreamSource.. + CGLMBuffer *m_vtx_buffers[ D3D_MAX_STREAMS ]; + CGLMBuffer *m_pDummy_vtx_buffer; + D3DIndexDesc m_indices; // Set by SetIndices.. + + IDirect3DVertexShader9 *m_vertexShader; // Set by SetVertexShader... + IDirect3DPixelShader9 *m_pixelShader; // Set by SetPixelShader... + + IDirect3DBaseTexture9 *m_textures[16]; // set by SetTexture... NULL if stage inactive + D3DSamplerDesc m_samplers[16]; // set by SetSamplerState.. + // GLM flavor stuff + GLMContext *m_ctx; + CGLMFBOMap *m_pFBOs; + bool m_bFBODirty; + + struct ObjectStats_t + { + int m_nTotalFBOs; + int m_nTotalVertexShaders; + int m_nTotalPixelShaders; + int m_nTotalVertexDecls; + int m_nTotalIndexBuffers; + int m_nTotalVertexBuffers; + int m_nTotalRenderTargets; + int m_nTotalTextures; + int m_nTotalSurfaces; + int m_nTotalQueries; + + void clear() { V_memset( this, 0, sizeof(* this ) ); } + + ObjectStats_t &operator -= ( const ObjectStats_t &rhs ) + { + m_nTotalFBOs -= rhs.m_nTotalFBOs; + m_nTotalVertexShaders -= rhs.m_nTotalVertexShaders; + m_nTotalPixelShaders -= rhs.m_nTotalPixelShaders; + m_nTotalVertexDecls -= rhs.m_nTotalVertexDecls; + m_nTotalIndexBuffers -= rhs.m_nTotalIndexBuffers; + m_nTotalVertexBuffers -= rhs.m_nTotalVertexBuffers; + m_nTotalRenderTargets -= rhs.m_nTotalRenderTargets; + m_nTotalTextures -= rhs.m_nTotalTextures; + m_nTotalSurfaces -= rhs.m_nTotalSurfaces; + m_nTotalQueries -= m_nTotalQueries; + return *this; + } + }; + ObjectStats_t m_ObjectStats; + ObjectStats_t m_PrevObjectStats; + void PrintObjectStats( const ObjectStats_t &stats ); + + // GL state + struct + { + // render state buckets + GLAlphaTestEnable_t m_AlphaTestEnable; + GLAlphaTestFunc_t m_AlphaTestFunc; + + GLAlphaToCoverageEnable_t m_AlphaToCoverageEnable; + + GLDepthTestEnable_t m_DepthTestEnable; + GLDepthMask_t m_DepthMask; + GLDepthFunc_t m_DepthFunc; + + GLClipPlaneEnable_t m_ClipPlaneEnable[kGLMUserClipPlanes]; + GLClipPlaneEquation_t m_ClipPlaneEquation[kGLMUserClipPlanes]; + + GLColorMaskSingle_t m_ColorMaskSingle; + GLColorMaskMultiple_t m_ColorMaskMultiple; + + GLCullFaceEnable_t m_CullFaceEnable; + GLCullFrontFace_t m_CullFrontFace; + GLPolygonMode_t m_PolygonMode; + GLDepthBias_t m_DepthBias; + GLScissorEnable_t m_ScissorEnable; + GLScissorBox_t m_ScissorBox; + GLViewportBox_t m_ViewportBox; + GLViewportDepthRange_t m_ViewportDepthRange; + + GLBlendEnable_t m_BlendEnable; + GLBlendFactor_t m_BlendFactor; + GLBlendEquation_t m_BlendEquation; + GLBlendColor_t m_BlendColor; + GLBlendEnableSRGB_t m_BlendEnableSRGB; + + GLStencilTestEnable_t m_StencilTestEnable; + GLStencilFunc_t m_StencilFunc; + GLStencilOp_t m_StencilOp; + GLStencilWriteMask_t m_StencilWriteMask; + + GLClearColor_t m_ClearColor; + GLClearDepth_t m_ClearDepth; + GLClearStencil_t m_ClearStencil; + + bool m_FogEnable; // not really pushed to GL, just latched here + + // samplers + GLMTexSamplingParams m_samplers[ 16 ]; + } gl; + +#if GL_BATCH_PERF_ANALYSIS + simple_bitmap *m_pBatch_vis_bitmap; + uint m_nBatchVisY; + uint m_nBatchVisFrameIndex, m_nBatchVisFileIdx; + uint m_nNumProgramChanges; + + uint m_nTotalD3DCalls; + double m_flTotalD3DTime; + uint m_nTotalGLCalls; + double m_flTotalGLTime; + uint m_nTotalPrims; + + uint m_nOverallProgramChanges; + uint m_nOverallDraws; + uint m_nOverallPrims; + uint m_nOverallD3DCalls; + double m_flOverallD3DTime; + uint m_nOverallGLCalls; + double m_flOverallGLTime; + + double m_flOverallPresentTime; + double m_flOverallPresentTimeSquared; + double m_flOverallSwapWindowTime; + double m_flOverallSwapWindowTimeSquared; + uint m_nOverallPresents; +#endif +}; + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value ) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetSamplerStateNonInline( Sampler, Type, Value ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + Assert( Sampler < 16 ); + + m_ctx->SetSamplerDirty( Sampler ); + + switch( Type ) + { + case D3DSAMP_ADDRESSU: + m_ctx->SetSamplerAddressU( Sampler, Value ); + break; + case D3DSAMP_ADDRESSV: + m_ctx->SetSamplerAddressV( Sampler, Value ); + break; + case D3DSAMP_ADDRESSW: + m_ctx->SetSamplerAddressW( Sampler, Value ); + break; + case D3DSAMP_BORDERCOLOR: + m_ctx->SetSamplerBorderColor( Sampler, Value ); + break; + case D3DSAMP_MAGFILTER: + m_ctx->SetSamplerMagFilter( Sampler, Value ); + break; + case D3DSAMP_MIPFILTER: + m_ctx->SetSamplerMipFilter( Sampler, Value ); + break; + case D3DSAMP_MINFILTER: + m_ctx->SetSamplerMinFilter( Sampler, Value ); + break; + case D3DSAMP_MIPMAPLODBIAS: + m_ctx->SetSamplerMipMapLODBias( Sampler, Value ); + break; + case D3DSAMP_MAXMIPLEVEL: + m_ctx->SetSamplerMaxMipLevel( Sampler, Value); + break; + case D3DSAMP_MAXANISOTROPY: + m_ctx->SetSamplerMaxAnisotropy( Sampler, Value); + break; + case D3DSAMP_SRGBTEXTURE: + m_samplers[ Sampler ].m_srgb = Value; + m_ctx->SetSamplerSRGBTexture(Sampler, Value); + break; + case D3DSAMP_SHADOWFILTER: + m_ctx->SetShadowFilter(Sampler, Value); + break; + + default: DXABSTRACT_BREAK_ON_ERROR(); break; + } + return S_OK; +#endif +} + +FORCEINLINE void TOGLMETHODCALLTYPE IDirect3DDevice9::SetSamplerStates( + DWORD Sampler, DWORD AddressU, DWORD AddressV, DWORD AddressW, + DWORD MinFilter, DWORD MagFilter, DWORD MipFilter ) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + SetSamplerStatesNonInline( Sampler, AddressU, AddressV, AddressW, MinFilter, MagFilter, MipFilter ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + Assert( Sampler < 16); + + m_ctx->SetSamplerDirty( Sampler ); + + m_ctx->SetSamplerStates( Sampler, AddressU, AddressV, AddressW, MinFilter, MagFilter, MipFilter ); +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetTexture(DWORD Stage,IDirect3DBaseTexture9* pTexture) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetTextureNonInline( Stage, pTexture ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_textures[Stage] = pTexture; + m_ctx->SetSamplerTex( Stage, pTexture ? pTexture->m_tex : NULL ); + return S_OK; +#endif +} + +inline GLenum D3DCompareFuncToGL( DWORD function ) +{ + switch ( function ) + { + case D3DCMP_NEVER : return GL_NEVER; // Always fail the test. + case D3DCMP_LESS : return GL_LESS; // Accept the new pixel if its value is less than the value of the current pixel. + case D3DCMP_EQUAL : return GL_EQUAL; // Accept the new pixel if its value equals the value of the current pixel. + case D3DCMP_LESSEQUAL : return GL_LEQUAL; // Accept the new pixel if its value is less than or equal to the value of the current pixel. ** + case D3DCMP_GREATER : return GL_GREATER; // Accept the new pixel if its value is greater than the value of the current pixel. + case D3DCMP_NOTEQUAL : return GL_NOTEQUAL; // Accept the new pixel if its value does not equal the value of the current pixel. + case D3DCMP_GREATEREQUAL: return GL_GEQUAL; // Accept the new pixel if its value is greater than or equal to the value of the current pixel. + case D3DCMP_ALWAYS : return GL_ALWAYS; // Always pass the test. + default : DXABSTRACT_BREAK_ON_ERROR(); return 0xFFFFFFFF; + } +} + +FORCEINLINE GLenum D3DBlendOperationToGL( DWORD operation ) +{ + switch (operation) + { + case D3DBLENDOP_ADD : return GL_FUNC_ADD; // The result is the destination added to the source. Result = Source + Destination + + /* not covered by dxabstract.h.. + case D3DBLENDOP_SUBTRACT : return GL_FUNC_SUBTRACT; // The result is the destination subtracted from to the source. Result = Source - Destination + case D3DBLENDOP_REVSUBTRACT : return GL_FUNC_REVERSE_SUBTRACT; // The result is the source subtracted from the destination. Result = Destination - Source + case D3DBLENDOP_MIN : return GL_MIN; // The result is the minimum of the source and destination. Result = MIN(Source, Destination) + case D3DBLENDOP_MAX : return GL_MAX; // The result is the maximum of the source and destination. Result = MAX(Source, Destination) + */ + default: + DXABSTRACT_BREAK_ON_ERROR(); + return 0xFFFFFFFF; + break; + } +} + +FORCEINLINE GLenum D3DBlendFactorToGL( DWORD equation ) +{ + switch (equation) + { + case D3DBLEND_ZERO : return GL_ZERO; // Blend factor is (0, 0, 0, 0). + case D3DBLEND_ONE : return GL_ONE; // Blend factor is (1, 1, 1, 1). + case D3DBLEND_SRCCOLOR : return GL_SRC_COLOR; // Blend factor is (Rs, Gs, Bs, As). + case D3DBLEND_INVSRCCOLOR : return GL_ONE_MINUS_SRC_COLOR; // Blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As). + case D3DBLEND_SRCALPHA : return GL_SRC_ALPHA; // Blend factor is (As, As, As, As). + case D3DBLEND_INVSRCALPHA : return GL_ONE_MINUS_SRC_ALPHA; // Blend factor is ( 1 - As, 1 - As, 1 - As, 1 - As). + case D3DBLEND_DESTALPHA : return GL_DST_ALPHA; // Blend factor is (Ad Ad Ad Ad). + case D3DBLEND_INVDESTALPHA : return GL_ONE_MINUS_DST_ALPHA; // Blend factor is (1 - Ad 1 - Ad 1 - Ad 1 - Ad). + case D3DBLEND_DESTCOLOR : return GL_DST_COLOR; // Blend factor is (Rd, Gd, Bd, Ad). + case D3DBLEND_INVDESTCOLOR : return GL_ONE_MINUS_DST_COLOR; // Blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad). + case D3DBLEND_SRCALPHASAT : return GL_SRC_ALPHA_SATURATE; // Blend factor is (f, f, f, 1); where f = min(As, 1 - Ad). + + /* + // these are weird.... break if we hit them + case D3DBLEND_BOTHSRCALPHA : Assert(0); return GL_ZERO; // Obsolete. Starting with DirectX 6, you can achieve the same effect by setting the source and destination blend factors to D3DBLEND_SRCALPHA and D3DBLEND_INVSRCALPHA in separate calls. + case D3DBLEND_BOTHINVSRCALPHA: Assert(0); return GL_ZERO; // Source blend factor is (1 - As, 1 - As, 1 - As, 1 - As), and destination blend factor is (As, As, As, As); the destination blend selection is overridden. This blend mode is supported only for the D3DRS_SRCBLEND render state. + case D3DBLEND_BLENDFACTOR : Assert(0); return GL_ZERO; // Constant color blending factor used by the frame-buffer blender. This blend mode is supported only if D3DPBLENDCAPS_BLENDFACTOR is set in the SrcBlendCaps or DestBlendCaps members of D3DCAPS9. + + dxabstract.h has not heard of these, so let them hit the debugger if they come through + case D3DBLEND_INVBLENDFACTOR: //Inverted constant color-blending factor used by the frame-buffer blender. This blend mode is supported only if the D3DPBLENDCAPS_BLENDFACTOR bit is set in the SrcBlendCaps or DestBlendCaps members of D3DCAPS9. + case D3DBLEND_SRCCOLOR2: // Blend factor is (PSOutColor[1]r, PSOutColor[1]g, PSOutColor[1]b, not used). This flag is available in Direct3D 9Ex only. + case D3DBLEND_INVSRCCOLOR2: // Blend factor is (1 - PSOutColor[1]r, 1 - PSOutColor[1]g, 1 - PSOutColor[1]b, not used)). This flag is available in Direct3D 9Ex only. + */ + default: + DXABSTRACT_BREAK_ON_ERROR(); + return 0xFFFFFFFF; + break; + } +} + + +FORCEINLINE GLenum D3DStencilOpToGL( DWORD operation ) +{ + switch( operation ) + { + case D3DSTENCILOP_KEEP : return GL_KEEP; + case D3DSTENCILOP_ZERO : return GL_ZERO; + case D3DSTENCILOP_REPLACE : return GL_REPLACE; + case D3DSTENCILOP_INCRSAT : return GL_INCR; + case D3DSTENCILOP_DECRSAT : return GL_DECR; + case D3DSTENCILOP_INVERT : return GL_INVERT; + case D3DSTENCILOP_INCR : return GL_INCR_WRAP_EXT; + case D3DSTENCILOP_DECR : return GL_DECR_WRAP_EXT; + default : DXABSTRACT_BREAK_ON_ERROR(); return 0xFFFFFFFF; + } +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetRenderStateInline( D3DRENDERSTATETYPE State, DWORD Value ) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetRenderState( State, Value ); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + + switch (State) + { + case D3DRS_ZENABLE: // kGLDepthTestEnable + { + gl.m_DepthTestEnable.enable = Value; + m_ctx->WriteDepthTestEnable( &gl.m_DepthTestEnable ); + break; + } + case D3DRS_ZWRITEENABLE: // kGLDepthMask + { + gl.m_DepthMask.mask = Value; + m_ctx->WriteDepthMask( &gl.m_DepthMask ); + break; + } + case D3DRS_ZFUNC: + { + // kGLDepthFunc + GLenum func = D3DCompareFuncToGL( Value ); + gl.m_DepthFunc.func = func; + m_ctx->WriteDepthFunc( &gl.m_DepthFunc ); + break; + } + case D3DRS_COLORWRITEENABLE: // kGLColorMaskSingle + { + gl.m_ColorMaskSingle.r = ((Value & D3DCOLORWRITEENABLE_RED) != 0) ? 0xFF : 0x00; + gl.m_ColorMaskSingle.g = ((Value & D3DCOLORWRITEENABLE_GREEN)!= 0) ? 0xFF : 0x00; + gl.m_ColorMaskSingle.b = ((Value & D3DCOLORWRITEENABLE_BLUE) != 0) ? 0xFF : 0x00; + gl.m_ColorMaskSingle.a = ((Value & D3DCOLORWRITEENABLE_ALPHA)!= 0) ? 0xFF : 0x00; + m_ctx->WriteColorMaskSingle( &gl.m_ColorMaskSingle ); + break; + } + case D3DRS_CULLMODE: // kGLCullFaceEnable / kGLCullFrontFace + { + switch (Value) + { + case D3DCULL_NONE: + { + gl.m_CullFaceEnable.enable = false; + gl.m_CullFrontFace.value = GL_CCW; //doesn't matter + + m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable ); + m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace ); + break; + } + + case D3DCULL_CW: + { + gl.m_CullFaceEnable.enable = true; + gl.m_CullFrontFace.value = GL_CW; //origGL_CCW; + + m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable ); + m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace ); + break; + } + case D3DCULL_CCW: + { + gl.m_CullFaceEnable.enable = true; + gl.m_CullFrontFace.value = GL_CCW; //origGL_CW; + + m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable ); + m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace ); + break; + } + default: + { + DXABSTRACT_BREAK_ON_ERROR(); + break; + } + } + break; + } + //-------------------------------------------------------------------------------------------- alphablend stuff + case D3DRS_ALPHABLENDENABLE: // kGLBlendEnable + { + gl.m_BlendEnable.enable = Value; + m_ctx->WriteBlendEnable( &gl.m_BlendEnable ); + break; + } + case D3DRS_BLENDOP: // kGLBlendEquation // D3D blend-op ==> GL blend equation + { + GLenum equation = D3DBlendOperationToGL( Value ); + gl.m_BlendEquation.equation = equation; + m_ctx->WriteBlendEquation( &gl.m_BlendEquation ); + break; + } + case D3DRS_SRCBLEND: // kGLBlendFactor // D3D blend-factor ==> GL blend factor + case D3DRS_DESTBLEND: // kGLBlendFactor + { + GLenum factor = D3DBlendFactorToGL( Value ); + + if (State==D3DRS_SRCBLEND) + { + gl.m_BlendFactor.srcfactor = factor; + } + else + { + gl.m_BlendFactor.dstfactor = factor; + } + m_ctx->WriteBlendFactor( &gl.m_BlendFactor ); + break; + } + case D3DRS_SRGBWRITEENABLE: // kGLBlendEnableSRGB + { + gl.m_BlendEnableSRGB.enable = Value; + m_ctx->WriteBlendEnableSRGB( &gl.m_BlendEnableSRGB ); + break; + } + //-------------------------------------------------------------------------------------------- alphatest stuff + case D3DRS_ALPHATESTENABLE: + { + gl.m_AlphaTestEnable.enable = Value; + m_ctx->WriteAlphaTestEnable( &gl.m_AlphaTestEnable ); + break; + } + case D3DRS_ALPHAREF: + { + gl.m_AlphaTestFunc.ref = Value / 255.0f; + m_ctx->WriteAlphaTestFunc( &gl.m_AlphaTestFunc ); + break; + } + case D3DRS_ALPHAFUNC: + { + GLenum func = D3DCompareFuncToGL( Value );; + gl.m_AlphaTestFunc.func = func; + m_ctx->WriteAlphaTestFunc( &gl.m_AlphaTestFunc ); + break; + } + //-------------------------------------------------------------------------------------------- stencil stuff + case D3DRS_STENCILENABLE: // GLStencilTestEnable_t + { + gl.m_StencilTestEnable.enable = Value; + m_ctx->WriteStencilTestEnable( &gl.m_StencilTestEnable ); + break; + } + case D3DRS_STENCILFAIL: // GLStencilOp_t "what do you do if stencil test fails" + { + GLenum stencilop = D3DStencilOpToGL( Value ); + gl.m_StencilOp.sfail = stencilop; + + m_ctx->WriteStencilOp( &gl.m_StencilOp,0 ); + m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this + break; + } + case D3DRS_STENCILZFAIL: // GLStencilOp_t "what do you do if stencil test passes *but* depth test fails, if depth test happened" + { + GLenum stencilop = D3DStencilOpToGL( Value ); + gl.m_StencilOp.dpfail = stencilop; + + m_ctx->WriteStencilOp( &gl.m_StencilOp,0 ); + m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this + break; + } + case D3DRS_STENCILPASS: // GLStencilOp_t "what do you do if stencil test and depth test both pass" + { + GLenum stencilop = D3DStencilOpToGL( Value ); + gl.m_StencilOp.dppass = stencilop; + + m_ctx->WriteStencilOp( &gl.m_StencilOp,0 ); + m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this + break; + } + case D3DRS_STENCILFUNC: // GLStencilFunc_t + { + GLenum stencilfunc = D3DCompareFuncToGL( Value ); + gl.m_StencilFunc.frontfunc = gl.m_StencilFunc.backfunc = stencilfunc; + + m_ctx->WriteStencilFunc( &gl.m_StencilFunc ); + break; + } + case D3DRS_STENCILREF: // GLStencilFunc_t + { + gl.m_StencilFunc.ref = Value; + m_ctx->WriteStencilFunc( &gl.m_StencilFunc ); + break; + } + case D3DRS_STENCILMASK: // GLStencilFunc_t + { + gl.m_StencilFunc.mask = Value; + m_ctx->WriteStencilFunc( &gl.m_StencilFunc ); + break; + } + case D3DRS_STENCILWRITEMASK: // GLStencilWriteMask_t + { + gl.m_StencilWriteMask.mask = Value; + m_ctx->WriteStencilWriteMask( &gl.m_StencilWriteMask ); + break; + } + case D3DRS_FOGENABLE: // none of these are implemented yet... erk + { + gl.m_FogEnable = (Value != 0); + GLMPRINTF(("-D- fogenable = %d",Value )); + break; + } + case D3DRS_SCISSORTESTENABLE: // kGLScissorEnable + { + gl.m_ScissorEnable.enable = Value; + m_ctx->WriteScissorEnable( &gl.m_ScissorEnable ); + break; + } + case D3DRS_DEPTHBIAS: // kGLDepthBias + { + // the value in the dword is actually a float + float fvalue = *(float*)&Value; + gl.m_DepthBias.units = fvalue; + + m_ctx->WriteDepthBias( &gl.m_DepthBias ); + break; + } + // good ref on these: http://aras-p.info/blog/2008/06/12/depth-bias-and-the-power-of-deceiving-yourself/ + case D3DRS_SLOPESCALEDEPTHBIAS: + { + // the value in the dword is actually a float + float fvalue = *(float*)&Value; + gl.m_DepthBias.factor = fvalue; + + m_ctx->WriteDepthBias( &gl.m_DepthBias ); + break; + } + // Alpha to coverage + case D3DRS_ADAPTIVETESS_Y: + { + gl.m_AlphaToCoverageEnable.enable = Value; + m_ctx->WriteAlphaToCoverageEnable( &gl.m_AlphaToCoverageEnable ); + break; + } + case D3DRS_CLIPPLANEENABLE: // kGLClipPlaneEnable + { + // d3d packs all the enables into one word. + // we break that out so we don't do N glEnable calls to sync - + // GLM is tracking one unique enable per plane. + for( int i=0; iWriteClipPlaneEnable( &gl.m_ClipPlaneEnable[x], x ); + break; + } + //-------------------------------------------------------------------------------------------- polygon/fill mode + case D3DRS_FILLMODE: + { + GLuint mode = 0; + switch(Value) + { + case D3DFILL_POINT: mode = GL_POINT; break; + case D3DFILL_WIREFRAME: mode = GL_LINE; break; + case D3DFILL_SOLID: mode = GL_FILL; break; + default: DXABSTRACT_BREAK_ON_ERROR(); break; + } + gl.m_PolygonMode.values[0] = gl.m_PolygonMode.values[1] = mode; + m_ctx->WritePolygonMode( &gl.m_PolygonMode ); + break; + } + } + + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetRenderStateConstInline( D3DRENDERSTATETYPE State, DWORD Value ) +{ + // State is a compile time constant - luckily no need to do anything special to get the compiler to optimize this case. + return SetRenderStateInline( State, Value ); +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetIndices(IDirect3DIndexBuffer9* pIndexData) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetIndicesNonInline( pIndexData ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + // just latch it. + m_indices.m_idxBuffer = pIndexData; + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetStreamSourceNonInline( StreamNumber, pStreamData, OffsetInBytes, Stride ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + Assert( StreamNumber < D3D_MAX_STREAMS ); + Assert( ( Stride & 3 ) == 0 ); // we support non-DWORD aligned strides, but on some drivers (like AMD's) perf goes off a cliff + + // perfectly legal to see a vertex buffer of NULL get passed in here. + // so we need an array to track these. + // OK, we are being given the stride, we don't need to calc it.. + + GLMPRINTF(("-X- IDirect3DDevice9::SetStreamSource setting stream #%d to D3D buf %p (GL name %d); offset %d, stride %d", StreamNumber, pStreamData, (pStreamData) ? pStreamData->m_vtxBuffer->m_name: -1, OffsetInBytes, Stride)); + + if ( !pStreamData ) + { + OffsetInBytes = 0; + Stride = 0; + + m_vtx_buffers[ StreamNumber ] = m_pDummy_vtx_buffer; + } + else + { + // We do not support strides of 0 + Assert( Stride > 0 ); + m_vtx_buffers[ StreamNumber ] = pStreamData->m_vtxBuffer; + } + + m_streams[ StreamNumber ].m_vtxBuffer = pStreamData; + m_streams[ StreamNumber ].m_offset = OffsetInBytes; + m_streams[ StreamNumber ].m_stride = Stride; + + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) // groups of 4 floats! +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexShaderConstantFNonInline( StartRegister, pConstantData, Vector4fCount ); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetProgramParametersF( kGLMVertexProgram, StartRegister, (float *)pConstantData, Vector4fCount ); + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexShaderConstantBNonInline( StartRegister, pConstantData, BoolCount ); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetProgramParametersB( kGLMVertexProgram, StartRegister, (int *)pConstantData, BoolCount ); + return S_OK; +#endif +} + +FORCEINLINE HRESULT IDirect3DDevice9::SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) // groups of 4 ints! +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexShaderConstantINonInline( StartRegister, pConstantData, Vector4iCount ); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetProgramParametersI( kGLMVertexProgram, StartRegister, (int *)pConstantData, Vector4iCount ); + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetPixelShaderConstantFNonInline(StartRegister, pConstantData, Vector4fCount); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetProgramParametersF( kGLMFragmentProgram, StartRegister, (float *)pConstantData, Vector4fCount ); + return S_OK; +#endif +} + +HRESULT IDirect3DDevice9::SetVertexShader(IDirect3DVertexShader9* pShader) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexShaderNonInline(pShader); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetVertexProgram( pShader ? pShader->m_vtxProgram : NULL ); + m_vertexShader = pShader; + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetPixelShader(IDirect3DPixelShader9* pShader) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetPixelShaderNonInline(pShader); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetFragmentProgram( pShader ? pShader->m_pixProgram : NULL ); + m_pixelShader = pShader; + return S_OK; +#endif +} + +FORCEINLINE HRESULT IDirect3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexDeclarationNonInline(pDecl); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_pVertDecl = pDecl; + return S_OK; +#endif +} + +FORCEINLINE void IDirect3DDevice9::SetMaxUsedVertexShaderConstantsHint( uint nMaxReg ) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetMaxUsedVertexShaderConstantsHintNonInline( nMaxReg ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetMaxUsedVertexShaderConstantsHint( nMaxReg ); +#endif +} + +// ------------------------------------------------------------------------------------------------------------------------------ // +// D3DX +// ------------------------------------------------------------------------------------------------------------------------------ // +struct ID3DXInclude +{ + virtual HRESULT Open(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes); + virtual HRESULT Close(LPCVOID pData); +}; +typedef ID3DXInclude* LPD3DXINCLUDE; + + +struct TOGL_CLASS ID3DXBuffer : public IUnknown +{ + void* GetBufferPointer(); + DWORD GetBufferSize(); +}; + +typedef ID3DXBuffer* LPD3DXBUFFER; + +class ID3DXConstantTable : public IUnknown +{ +}; +typedef ID3DXConstantTable* LPD3DXCONSTANTTABLE; + +TOGL_INTERFACE const char* D3DXGetPixelShaderProfile( IDirect3DDevice9 *pDevice ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); +TOGL_INTERFACE D3DXVECTOR3* D3DXVec3TransformCoord( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack); +TOGL_INTERFACE void D3DXMatrixIdentity( D3DXMATRIX * ); + +TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Subtract( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + return pOut; +} + +TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Cross( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + D3DXVECTOR3 v; + + v.x = pV1->y * pV2->z - pV1->z * pV2->y; + v.y = pV1->z * pV2->x - pV1->x * pV2->z; + v.z = pV1->x * pV2->y - pV1->y * pV2->x; + + *pOut = v; + return pOut; +} + +TOGL_INTERFACE D3DXINLINE FLOAT D3DXVec3Dot( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; +} + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP); + +TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM ); + + +TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z ); + +// Build an ortho projection matrix. (right-handed) +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf ); + +// Transform a plane by a matrix. The vector (a,b,c) must be normal. +// M should be the inverse transpose of the transformation desired. +TOGL_INTERFACE D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE IDirect3D9 *Direct3DCreate9(UINT SDKVersion); + +TOGL_INTERFACE void D3DPERF_SetOptions( DWORD dwOptions ); + +TOGL_INTERFACE HRESULT D3DXCompileShader( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +// fake D3D usage constant for SRGB tex creation +#define D3DUSAGE_TEXTURE_SRGB (0x80000000L) + +#else + + //USE_ACTUAL_DX + #ifndef WIN32 + #error sorry man + #endif + + #ifdef _X360 + #include "d3d9.h" + #include "d3dx9.h" + #else + #include + #include "../../dx9sdk/include/d3d9.h" + #include "../../dx9sdk/include/d3dx9.h" + #endif + typedef HWND VD3DHWND; + +#endif // DX_TO_GL_ABSTRACTION + +#endif // DXABSTRACT_H diff --git a/mp/src/public/togl/linuxwin/dxabstract_types.h b/mp/src/public/togl/linuxwin/dxabstract_types.h new file mode 100644 index 00000000..c021ca78 --- /dev/null +++ b/mp/src/public/togl/linuxwin/dxabstract_types.h @@ -0,0 +1,1712 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// dxabstract_types.h +// +//================================================================================================== +#ifndef DXABSTRACT_TYPES_H +#define DXABSTRACT_TYPES_H + +#pragma once + +#if GL_BATCH_PERF_ANALYSIS + class simple_bitmap; +#endif + +struct IUnknown; +struct IDirect3D9; +struct IDirect3DDevice9; +struct IDirect3DResource9; +struct IDirect3DBaseTexture9; +struct IDirect3DTexture9; +struct IDirect3DCubeTexture9; +struct IDirect3DVolumeTexture9; +struct IDirect3DSurface9; +struct IDirect3DVertexDeclaration9; +struct IDirect3DQuery9; +struct IDirect3DVertexBuffer9; +struct IDirect3DIndexBuffer9; +struct IDirect3DPixelShader9; +struct IDirect3DVertexShader9; +struct IDirect3DDevice9Params; + +class GLMContext; +struct GLMRect; +struct GLMShaderPairInfo; +class CGLMBuffer; +class CGLMQuery; +class CGLMTex; +class CGLMProgram; +class CGLMFBO; + +#ifdef TOGL_DLL_EXPORT + #define TOGL_INTERFACE DLL_EXPORT + #define TOGL_OVERLOAD DLL_GLOBAL_EXPORT + #define TOGL_CLASS DLL_CLASS_EXPORT + #define TOGL_GLOBAL DLL_GLOBAL_EXPORT +#else + #define TOGL_INTERFACE DLL_IMPORT + #define TOGL_OVERLOAD DLL_GLOBAL_IMPORT + #define TOGL_CLASS DLL_CLASS_IMPORT + #define TOGL_GLOBAL DLL_GLOBAL_IMPORT +#endif + +#ifdef OSX +#error "Do not use this header's types on OSX until togo is ported to Mac!" +#endif + +#define TOGLMETHODCALLTYPE __stdcall +//#define TOGLMETHODCALLTYPE + +#define DXABSTRACT_BREAK_ON_ERROR() DebuggerBreak() + +typedef void* VD3DHWND; +typedef void* VD3DHANDLE; + +#define MAKEFOURCC(ch0, ch1, ch2, ch3) ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) + +// +// +// Stuff that would be in windows.h +// +// +#if !defined(_WINNT_) + + typedef int INT; + typedef unsigned long ULONG; + typedef long LONG; + typedef float FLOAT; + typedef unsigned int DWORD; + typedef unsigned short WORD; + typedef long long LONGLONG; + typedef unsigned int UINT; + typedef long HRESULT; + typedef unsigned char BYTE; + #define CONST const + + #if defined(POSIX) + typedef size_t ULONG_PTR; + #else + typedef unsigned long ULONG_PTR; + #endif + + typedef ULONG_PTR SIZE_T; + + typedef const char* LPCSTR; + typedef char* LPSTR; + typedef DWORD* LPDWORD; + + #define ZeroMemory RtlZeroMemory + #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length)) + + typedef union _LARGE_INTEGER + { + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + LONGLONG QuadPart; + } LARGE_INTEGER; + + typedef struct _GUID + { + bool operator==( const struct _GUID &other ) const; + + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; + } GUID; + + typedef struct _RECT + { + int left; + int top; + int right; + int bottom; + } RECT; + + typedef struct tagPOINT + { + LONG x; + LONG y; + } POINT, *PPOINT, *LPPOINT; + + typedef struct _MEMORYSTATUS + { + DWORD dwLength; + SIZE_T dwTotalPhys; + } MEMORYSTATUS, *LPMEMORYSTATUS; + + typedef DWORD COLORREF; + #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) + + #define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + + #define S_FALSE ((HRESULT)0x00000001L) + #define S_OK 0 + #define E_FAIL ((HRESULT)0x80004005L) + #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) + + #define FAILED(hr) ((HRESULT)(hr) < 0) + #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) + + struct RGNDATA + { + }; + + typedef const void* LPCVOID; +#endif + +//----------------------------------------------------------------------------- + +typedef enum _D3DFORMAT D3DFORMAT; + +#define D3DSI_OPCODE_MASK 0x0000FFFF +#define D3DSP_TEXTURETYPE_MASK 0x78000000 + +#define D3DUSAGE_AUTOGENMIPMAP 0x00000400L +#define D3DSP_DCL_USAGE_MASK 0x0000000f + +#define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000 +#define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16 + + +/* Flags to construct D3DRS_COLORWRITEENABLE */ +#define D3DCOLORWRITEENABLE_RED (1L<<0) +#define D3DCOLORWRITEENABLE_GREEN (1L<<1) +#define D3DCOLORWRITEENABLE_BLUE (1L<<2) +#define D3DCOLORWRITEENABLE_ALPHA (1L<<3) + +#define D3DSGR_NO_CALIBRATION 0x00000000L + +#define D3DXINLINE inline + +#define D3D_SDK_VERSION 32 + +#define _FACD3D 0x876 +#define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) + +#define D3DERR_NOTFOUND MAKE_D3DHRESULT(2150) +#define D3DERR_DEVICELOST MAKE_D3DHRESULT(2152) +#define D3DERR_NOTAVAILABLE MAKE_D3DHRESULT(2154) +#define D3DERR_DEVICENOTRESET MAKE_D3DHRESULT(2153) +#define D3DERR_INVALIDCALL MAKE_D3DHRESULT(2156) +#define D3DERR_DRIVERINTERNALERROR MAKE_D3DHRESULT(2087) +#define D3DERR_OUTOFVIDEOMEMORY MAKE_D3DHRESULT(380) +#define D3D_OK S_OK + +#define D3DPRESENT_RATE_DEFAULT 0x00000000 + +// +// DevCaps +// +// we need to see who in Source land is interested in these values, as dxabstract is currently reporting zero for the whole Caps word +#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ +#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ +#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ +#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */ +#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */ +#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */ +#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */ +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */ +#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */ +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ +#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */ +#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */ +#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */ + +// +// PrimitiveMiscCaps +// +#define D3DPMISCCAPS_MASKZ 0x00000002L +#define D3DPMISCCAPS_CULLNONE 0x00000010L +#define D3DPMISCCAPS_CULLCW 0x00000020L +#define D3DPMISCCAPS_CULLCCW 0x00000040L +#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L +#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */ +#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */ +#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */ +#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */ +#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */ +#define D3DPMISCCAPS_PERSTAGECONSTANT 0x00008000L /* Device supports per-stage constants */ +#define D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS 0x00040000L /* Device supports different bit depths for MRT */ +#define D3DPMISCCAPS_FOGVERTEXCLAMPED 0x00100000L /* Device clamps fog blend factor per vertex */ + +// Flags field for Issue +#define D3DISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled". +#define D3DISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginng of a query. + + +#define D3DPRESENT_INTERVAL_ONE 0x00000001L +#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L + +/* + * Options for clearing + */ +#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ +#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ +#define D3DCLEAR_STENCIL 0x00000004l /* Clear stencil planes */ + + +#define D3DENUM_WHQL_LEVEL 0x00000002L + + + + +#define D3DPTEXTURECAPS_NOPROJECTEDBUMPENV 0x00200000L /* Device does not support projected bump env lookup operation + in programmable and fixed function pixel shaders */ +#define D3DDEVCAPS2_STREAMOFFSET 0x00000001L /* Device supports offsets in streams. Must be set by DX9 drivers */ + +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ + +#define D3DCREATE_PUREDEVICE 0x00000010L +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0x00000020L +#define D3DCREATE_HARDWARE_VERTEXPROCESSING 0x00000040L +#define D3DCREATE_FPU_PRESERVE 0x00000002L +#define D3DPRASTERCAPS_FOGRANGE 0x00010000L +#define D3DPRASTERCAPS_FOGTABLE 0x00000100L +#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L +#define D3DPRASTERCAPS_WFOG 0x00100000L +#define D3DPRASTERCAPS_ZFOG 0x00200000L +#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L +#define D3DPRASTERCAPS_WBUFFER 0x00040000L +#define D3DPRASTERCAPS_ZTEST 0x00000010L + +// +// Caps2 +// +#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L +#define D3DPRASTERCAPS_SCISSORTEST 0x01000000L +#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */ +#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */ +#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */ +#define D3DCREATE_MULTITHREADED 0x00000004L +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L +#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L +#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */ +#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */ +#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L +#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */ +#define D3DTEXOPCAPS_ADD 0x00000040L +#define D3DTEXOPCAPS_MODULATE2X 0x00000010L +#define D3DPRASTERCAPS_DEPTHBIAS 0x04000000L +#define D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS 0x02000000L +#define D3DVTXPCAPS_TEXGEN_SPHEREMAP 0x00000100L /* device supports D3DTSS_TCI_SPHEREMAP */ +#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L + +// The following usages are valid only for querying CheckDeviceFormat +#define D3DUSAGE_QUERY_SRGBREAD (0x00010000L) +#define D3DUSAGE_QUERY_FILTER (0x00020000L) +#define D3DUSAGE_QUERY_SRGBWRITE (0x00040000L) +#define D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING (0x00080000L) +#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) + +/* Usages for Vertex/Index buffers */ +#define D3DUSAGE_WRITEONLY (0x00000008L) +#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) +#define D3DUSAGE_DONOTCLIP (0x00000020L) +#define D3DUSAGE_POINTS (0x00000040L) +#define D3DUSAGE_RTPATCHES (0x00000080L) +#define D3DUSAGE_NPATCHES (0x00000100L) + + +// Flags field for GetData +#define D3DGETDATA_FLUSH (1 << 0) // Tells the runtime to flush if the query is outstanding. + +#define D3DFVF_XYZ 0x002 + + +#define D3DTA_SELECTMASK 0x0000000f // mask for arg selector +#define D3DTA_DIFFUSE 0x00000000 // select diffuse color (read only) +#define D3DTA_CURRENT 0x00000001 // select stage destination register (read/write) +#define D3DTA_TEXTURE 0x00000002 // select texture color (read only) +#define D3DTA_TFACTOR 0x00000003 // select D3DRS_TEXTUREFACTOR (read only) +#define D3DTA_SPECULAR 0x00000004 // select specular color (read only) +#define D3DTA_TEMP 0x00000005 // select temporary register color (read/write) +#define D3DTA_CONSTANT 0x00000006 // select texture stage constant +#define D3DTA_COMPLEMENT 0x00000010 // take 1.0 - x (read modifier) +#define D3DTA_ALPHAREPLICATE 0x00000020 // replicate alpha to color components (read modifier) + + +#define D3DUSAGE_RENDERTARGET (0x00000001L) +#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) +#define D3DUSAGE_QUERY_FILTER (0x00020000L) +#define D3DUSAGE_DEPTHSTENCIL (0x00000002L) +#define D3DUSAGE_WRITEONLY (0x00000008L) +#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) +#define D3DUSAGE_DYNAMIC (0x00000200L) + +#define D3DSI_INSTLENGTH_MASK 0x0F000000 +#define D3DSI_INSTLENGTH_SHIFT 24 +#define D3DSP_TEXTURETYPE_SHIFT 27 +#define D3DSP_REGTYPE_SHIFT 28 +#define D3DSP_REGTYPE_SHIFT2 8 +#define D3DSP_REGTYPE_MASK 0x70000000 +#define D3DSP_REGTYPE_MASK2 0x00001800 + +#define D3DSP_REGNUM_MASK 0x000007FF + +#define D3DSP_DSTMOD_SHIFT 20 +#define D3DSP_DSTMOD_MASK 0x00F00000 +#define D3DSPDM_MSAMPCENTROID (4<>8)&0xFF) +#define D3DSHADER_VERSION_MINOR(_Version) (((_Version)>>0)&0xFF) + +#define D3DSHADER_ADDRESSMODE_SHIFT 13 +#define D3DSHADER_ADDRESSMODE_MASK (1 << D3DSHADER_ADDRESSMODE_SHIFT) + +#define D3DPS_END() 0x0000FFFF + +// ps_2_0 texld controls +#define D3DSI_TEXLD_PROJECT (0x01 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) +#define D3DSI_TEXLD_BIAS (0x02 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) + + +// destination parameter write mask +#define D3DSP_WRITEMASK_0 0x00010000 // Component 0 (X;Red) +#define D3DSP_WRITEMASK_1 0x00020000 // Component 1 (Y;Green) +#define D3DSP_WRITEMASK_2 0x00040000 // Component 2 (Z;Blue) +#define D3DSP_WRITEMASK_3 0x00080000 // Component 3 (W;Alpha) +#define D3DSP_WRITEMASK_ALL 0x000F0000 // All Components + +#define D3DVS_SWIZZLE_SHIFT 16 +#define D3DVS_SWIZZLE_MASK 0x00FF0000 + +// The following bits define where to take component X from: + +#define D3DVS_X_X (0 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_Y (1 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_Z (2 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_W (3 << D3DVS_SWIZZLE_SHIFT) + +// The following bits define where to take component Y from: + +#define D3DVS_Y_X (0 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_Y (1 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_Z (2 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_W (3 << (D3DVS_SWIZZLE_SHIFT + 2)) + +// The following bits define where to take component Z from: + +#define D3DVS_Z_X (0 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_Y (1 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_Z (2 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_W (3 << (D3DVS_SWIZZLE_SHIFT + 4)) + +// The following bits define where to take component W from: + +#define D3DVS_W_X (0 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_Y (1 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_Z (2 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_W (3 << (D3DVS_SWIZZLE_SHIFT + 6)) + +// source parameter modifiers +#define D3DSP_SRCMOD_SHIFT 24 +#define D3DSP_SRCMOD_MASK 0x0F000000 + +// ------------------------------------------------------------------------------------------------------------------------------ // +// ENUMS +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef enum _D3DSHADER_PARAM_SRCMOD_TYPE +{ + D3DSPSM_NONE = 0<= 2.0 + + + D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 + D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) + D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) + D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) + D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) + D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) + D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) + D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) + D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values + D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. +} D3DDECLTYPE; + +typedef enum _D3DDECLMETHOD +{ + D3DDECLMETHOD_DEFAULT = 0, + D3DDECLMETHOD_PARTIALU, + D3DDECLMETHOD_PARTIALV, + D3DDECLMETHOD_CROSSUV, // Normal + D3DDECLMETHOD_UV, + D3DDECLMETHOD_LOOKUP, // Lookup a displacement map + D3DDECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map +} D3DDECLMETHOD; + +typedef enum _D3DDECLUSAGE +{ + D3DDECLUSAGE_POSITION = 0, + D3DDECLUSAGE_BLENDWEIGHT = 1, + D3DDECLUSAGE_BLENDINDICES = 2, + D3DDECLUSAGE_NORMAL = 3, + D3DDECLUSAGE_PSIZE = 4, + D3DDECLUSAGE_TEXCOORD = 5, + D3DDECLUSAGE_TANGENT = 6, + D3DDECLUSAGE_BINORMAL = 7, + D3DDECLUSAGE_TESSFACTOR = 8, + D3DDECLUSAGE_PLUGH = 9, // mystery value + D3DDECLUSAGE_COLOR = 10, + D3DDECLUSAGE_FOG = 11, + D3DDECLUSAGE_DEPTH = 12, + D3DDECLUSAGE_SAMPLE = 13, +} D3DDECLUSAGE; + +typedef enum _D3DPRIMITIVETYPE +{ + D3DPT_POINTLIST = 1, + D3DPT_LINELIST = 2, + D3DPT_TRIANGLELIST = 4, + D3DPT_TRIANGLESTRIP = 5, + D3DPT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DPRIMITIVETYPE; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// STRUCTURES +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef struct TOGL_CLASS D3DXPLANE +{ + float& operator[]( int i ); + bool operator==( const D3DXPLANE &o ); + bool operator!=( const D3DXPLANE &o ); + operator float*(); + operator const float*() const; + + float a, b, c, d; +} D3DXPLANE; + +typedef enum _D3DVERTEXBLENDFLAGS +{ + D3DVBF_DISABLE = 0, // Disable vertex blending + D3DVBF_1WEIGHTS = 1, // 2 matrix blending + D3DVBF_2WEIGHTS = 2, // 3 matrix blending + D3DVBF_3WEIGHTS = 3, // 4 matrix blending + D3DVBF_TWEENING = 255, // blending using D3DRS_TWEENFACTOR + D3DVBF_0WEIGHTS = 256, // one matrix is used with weight 1.0 + D3DVBF_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} D3DVERTEXBLENDFLAGS; + +typedef struct _D3DINDEXBUFFER_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + UINT Size; +} D3DINDEXBUFFER_DESC; + +typedef struct _D3DVERTEXELEMENT9 +{ + WORD Stream; // Stream index + WORD Offset; // Offset in the stream in bytes + BYTE Type; // Data type + BYTE Method; // Processing method + BYTE Usage; // Semantics + BYTE UsageIndex; // Semantic index +} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; + + +#define MAX_DEVICE_IDENTIFIER_STRING 512 +typedef struct _D3DADAPTER_IDENTIFIER9 +{ + char Driver[MAX_DEVICE_IDENTIFIER_STRING]; + char Description[MAX_DEVICE_IDENTIFIER_STRING]; + char DeviceName[32]; /* Device name for GDI (ex. \\.\DISPLAY1) */ + + LARGE_INTEGER DriverVersion; /* Defined for 32 bit components */ + + DWORD VendorId; + DWORD DeviceId; + DWORD SubSysId; + DWORD Revision; + DWORD VideoMemory; + +} D3DADAPTER_IDENTIFIER9; + +typedef struct _D3DCOLORVALUE +{ + float r; + float g; + float b; + float a; +} D3DCOLORVALUE; + +typedef struct _D3DMATERIAL9 +{ + D3DCOLORVALUE Diffuse; /* Diffuse color RGBA */ + D3DCOLORVALUE Ambient; /* Ambient color RGB */ + D3DCOLORVALUE Specular; /* Specular 'shininess' */ + D3DCOLORVALUE Emissive; /* Emissive color RGB */ + float Power; /* Sharpness if specular highlight */ +} D3DMATERIAL9; + +typedef struct _D3DVOLUME_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + + UINT Width; + UINT Height; + UINT Depth; +} D3DVOLUME_DESC; + +typedef struct _D3DVIEWPORT9 +{ + DWORD X; + DWORD Y; /* Viewport Top left */ + DWORD Width; + DWORD Height; /* Viewport Dimensions */ + float MinZ; /* Min/max of clip Volume */ + float MaxZ; +} D3DVIEWPORT9; + +typedef struct _D3DPSHADERCAPS2_0 +{ + DWORD Caps; + INT DynamicFlowControlDepth; + INT NumTemps; + INT StaticFlowControlDepth; + INT NumInstructionSlots; +} D3DPSHADERCAPS2_0; + +typedef struct _D3DCAPS9 +{ + /* Device Info */ + D3DDEVTYPE DeviceType; + + /* Caps from DX7 Draw */ + DWORD Caps; + DWORD Caps2; + + /* Cursor Caps */ + DWORD CursorCaps; + + /* 3D Device Caps */ + DWORD DevCaps; + + DWORD PrimitiveMiscCaps; + DWORD RasterCaps; + DWORD TextureCaps; + DWORD TextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DTexture9's + + DWORD MaxTextureWidth, MaxTextureHeight; + DWORD MaxVolumeExtent; + + DWORD MaxTextureAspectRatio; + DWORD MaxAnisotropy; + + DWORD TextureOpCaps; + DWORD MaxTextureBlendStages; + DWORD MaxSimultaneousTextures; + + DWORD VertexProcessingCaps; + DWORD MaxActiveLights; + DWORD MaxUserClipPlanes; + DWORD MaxVertexBlendMatrices; + DWORD MaxVertexBlendMatrixIndex; + + DWORD MaxPrimitiveCount; // max number of primitives per DrawPrimitive call + DWORD MaxStreams; + + DWORD VertexShaderVersion; + DWORD MaxVertexShaderConst; // number of vertex shader constant registers + + DWORD PixelShaderVersion; + + // Here are the DX9 specific ones + DWORD DevCaps2; + D3DPSHADERCAPS2_0 PS20Caps; + + DWORD NumSimultaneousRTs; // Will be at least 1 + DWORD MaxVertexShader30InstructionSlots; + DWORD MaxPixelShader30InstructionSlots; + + // only on Posix/GL + DWORD FakeSRGBWrite; // 1 for parts which can't support SRGB writes due to driver issues - 0 for others + DWORD MixedSizeTargets; // 1 for parts which can mix attachment sizes (RT's color vs depth) + DWORD CanDoSRGBReadFromRTs; // 0 when we're on Leopard, 1 when on Snow Leopard +} D3DCAPS9; + +typedef struct _D3DDISPLAYMODE +{ + UINT Width; + UINT Height; + UINT RefreshRate; + D3DFORMAT Format; +} D3DDISPLAYMODE; + +typedef struct _D3DGAMMARAMP +{ + WORD red [256]; + WORD green[256]; + WORD blue [256]; +} D3DGAMMARAMP; + + +/* Resize Optional Parameters */ +typedef struct _D3DPRESENT_PARAMETERS_ +{ + UINT BackBufferWidth; + UINT BackBufferHeight; + D3DFORMAT BackBufferFormat; + UINT BackBufferCount; + + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + + D3DSWAPEFFECT SwapEffect; + VD3DHWND hDeviceWindow; + BOOL Windowed; + BOOL EnableAutoDepthStencil; + D3DFORMAT AutoDepthStencilFormat; + DWORD Flags; + + /* FullScreen_RefreshRateInHz must be zero for Windowed mode */ + UINT FullScreen_RefreshRateInHz; + UINT PresentationInterval; +} D3DPRESENT_PARAMETERS; + +typedef struct _D3DDEVICE_CREATION_PARAMETERS +{ + UINT AdapterOrdinal; + D3DDEVTYPE DeviceType; + VD3DHWND hFocusWindow; + DWORD BehaviorFlags; +} D3DDEVICE_CREATION_PARAMETERS; + +/* Structures for LockBox */ +typedef struct _D3DBOX +{ + UINT Left; + UINT Top; + UINT Right; + UINT Bottom; + UINT Front; + UINT Back; +} D3DBOX; + +typedef struct _D3DLOCKED_BOX +{ + INT RowPitch; + INT SlicePitch; + void* pBits; +} D3DLOCKED_BOX; + +typedef struct _D3DSURFACE_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + UINT Width; + UINT Height; +} D3DSURFACE_DESC; + + +typedef struct _D3DLOCKED_RECT +{ + INT Pitch; + void* pBits; +} D3DLOCKED_RECT; + + +typedef struct _D3DRASTER_STATUS +{ + BOOL InVBlank; + UINT ScanLine; +} D3DRASTER_STATUS; + +typedef enum _D3DLIGHTTYPE +{ + D3DLIGHT_POINT = 1, + D3DLIGHT_SPOT = 2, + D3DLIGHT_DIRECTIONAL = 3, + D3DLIGHT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DLIGHTTYPE; + +typedef struct TOGL_CLASS _D3DVECTOR +{ + float x; + float y; + float z; +} D3DVECTOR; + +class TOGL_CLASS D3DXVECTOR2 +{ +public: + operator FLOAT* (); + operator CONST FLOAT* () const; + + float x,y; +}; + +class TOGL_CLASS D3DXVECTOR3 : public D3DVECTOR +{ +public: + D3DXVECTOR3() {} + D3DXVECTOR3( float a, float b, float c ); + operator FLOAT* (); + operator CONST FLOAT* () const; +}; + +typedef enum _D3DXINCLUDE_TYPE +{ + D3DXINC_LOCAL, + + // force 32-bit size enum + D3DXINC_FORCE_DWORD = 0x7fffffff + +} D3DXINCLUDE_TYPE; + +typedef struct _D3DLIGHT9 +{ + D3DLIGHTTYPE Type; /* Type of light source */ + D3DCOLORVALUE Diffuse; /* Diffuse color of light */ + D3DCOLORVALUE Specular; /* Specular color of light */ + D3DCOLORVALUE Ambient; /* Ambient color of light */ + D3DVECTOR Position; /* Position in world space */ + D3DVECTOR Direction; /* Direction in world space */ + float Range; /* Cutoff range */ + float Falloff; /* Falloff */ + float Attenuation0; /* Constant attenuation */ + float Attenuation1; /* Linear attenuation */ + float Attenuation2; /* Quadratic attenuation */ + float Theta; /* Inner angle of spotlight cone */ + float Phi; /* Outer angle of spotlight cone */ +} D3DLIGHT9; + +class TOGL_CLASS D3DXVECTOR4 +{ +public: + D3DXVECTOR4() {} + D3DXVECTOR4( float a, float b, float c, float d ); + + float x,y,z,w; +}; + +//---------------------------------------------------------------------------- +// D3DXMACRO: +// ---------- +// Preprocessor macro definition. The application pass in a NULL-terminated +// array of this structure to various D3DX APIs. This enables the application +// to #define tokens at runtime, before the file is parsed. +//---------------------------------------------------------------------------- + +typedef struct _D3DXMACRO +{ + LPCSTR Name; + LPCSTR Definition; + +} D3DXMACRO, *LPD3DXMACRO; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// ------------------------------------------------------------------------------------------------------------------------------ // +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +// +// Also look for any functions marked with "**** FIXED FUNCTION STUFF" +// +// It's only laying around here so we don't have to chop up the shader system a lot to strip out the fixed function code paths. +// ------------------------------------------------------------------------------------------------------------------------------ // +// ------------------------------------------------------------------------------------------------------------------------------ // + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTRANSFORMSTATETYPE +{ + D3DTS_VIEW = 2, + D3DTS_PROJECTION = 3, + D3DTS_TEXTURE0 = 16, + D3DTS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTRANSFORMSTATETYPE; + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTEXTUREOP +{ + // Control + D3DTOP_DISABLE = 1, // disables stage + D3DTOP_SELECTARG1 = 2, // the default + D3DTOP_SELECTARG2 = 3, + + // Modulate + D3DTOP_MODULATE = 4, // multiply args together + D3DTOP_MODULATE2X = 5, // multiply and 1 bit + D3DTOP_MODULATE4X = 6, // multiply and 2 bits + + // Add + D3DTOP_ADD = 7, // add arguments together + D3DTOP_ADDSIGNED = 8, // add with -0.5 bias + D3DTOP_ADDSIGNED2X = 9, // as above but left 1 bit + D3DTOP_SUBTRACT = 10, // Arg1 - Arg2, with no saturation + D3DTOP_ADDSMOOTH = 11, // add 2 args, subtract product + // Arg1 + Arg2 - Arg1*Arg2 + // = Arg1 + (1-Arg1)*Arg2 + + // Linear alpha blend: Arg1*(Alpha) + Arg2*(1-Alpha) + D3DTOP_BLENDDIFFUSEALPHA = 12, // iterated alpha + D3DTOP_BLENDTEXTUREALPHA = 13, // texture alpha + D3DTOP_BLENDFACTORALPHA = 14, // alpha from D3DRS_TEXTUREFACTOR + + // Linear alpha blend with pre-multiplied arg1 input: Arg1 + Arg2*(1-Alpha) + D3DTOP_BLENDTEXTUREALPHAPM = 15, // texture alpha + D3DTOP_BLENDCURRENTALPHA = 16, // by alpha of current color + + // Specular mapping + D3DTOP_PREMODULATE = 17, // modulate with next texture before use + D3DTOP_MODULATEALPHA_ADDCOLOR = 18, // Arg1.RGB + Arg1.A*Arg2.RGB + // COLOROP only + D3DTOP_MODULATECOLOR_ADDALPHA = 19, // Arg1.RGB*Arg2.RGB + Arg1.A + // COLOROP only + D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20, // (1-Arg1.A)*Arg2.RGB + Arg1.RGB + // COLOROP only + D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21, // (1-Arg1.RGB)*Arg2.RGB + Arg1.A + // COLOROP only + + // Bump mapping + D3DTOP_BUMPENVMAP = 22, // per pixel env map perturbation + D3DTOP_BUMPENVMAPLUMINANCE = 23, // with luminance channel + + // This can do either diffuse or specular bump mapping with correct input. + // Performs the function (Arg1.R*Arg2.R + Arg1.G*Arg2.G + Arg1.B*Arg2.B) + // where each component has been scaled and offset to make it signed. + // The result is replicated into all four (including alpha) channels. + // This is a valid COLOROP only. + D3DTOP_DOTPRODUCT3 = 24, + + // Triadic ops + D3DTOP_MULTIPLYADD = 25, // Arg0 + Arg1*Arg2 + D3DTOP_LERP = 26, // (Arg0)*Arg1 + (1-Arg0)*Arg2 + + D3DTOP_FORCE_DWORD = 0x7fffffff, +} D3DTEXTUREOP; + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTEXTURESTAGESTATETYPE +{ + D3DTSS_COLOROP = 1, /* D3DTEXTUREOP - per-stage blending controls for color channels */ + D3DTSS_COLORARG1 = 2, /* D3DTA_* (texture arg) */ + D3DTSS_COLORARG2 = 3, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAOP = 4, /* D3DTEXTUREOP - per-stage blending controls for alpha channel */ + D3DTSS_ALPHAARG1 = 5, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAARG2 = 6, /* D3DTA_* (texture arg) */ + D3DTSS_BUMPENVMAT00 = 7, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT01 = 8, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT10 = 9, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT11 = 10, /* float (bump mapping matrix) */ + D3DTSS_TEXCOORDINDEX = 11, /* identifies which set of texture coordinates index this texture */ + D3DTSS_BUMPENVLOFFSET = 23, /* float offset for bump map luminance */ + D3DTSS_TEXTURETRANSFORMFLAGS = 24, /* D3DTEXTURETRANSFORMFLAGS controls texture transform */ + D3DTSS_COLORARG0 = 26, /* D3DTA_* third arg for triadic ops */ + D3DTSS_RESULTARG = 28, /* D3DTA_* arg for result (CURRENT or TEMP) */ + + + D3DTSS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTEXTURESTAGESTATETYPE; + +//===========================================================================// + +enum GLMVertexAttributeIndex +{ + kGLMGenericAttr00 = 0, + kGLMGenericAttr01, + kGLMGenericAttr02, + kGLMGenericAttr03, + kGLMGenericAttr04, + kGLMGenericAttr05, + kGLMGenericAttr06, + kGLMGenericAttr07, + kGLMGenericAttr08, + kGLMGenericAttr09, + kGLMGenericAttr10, + kGLMGenericAttr11, + kGLMGenericAttr12, + kGLMGenericAttr13, + kGLMGenericAttr14, + kGLMGenericAttr15, + + kGLMVertexAttributeIndexMax // ideally < 32 +}; + +struct GLMVertexAttributeDesc // all the info you need to do vertex setup for one attribute +{ + CGLMBuffer *m_pBuffer; // NULL allowed in which case m_offset is the full 32-bit pointer.. so you can draw from plain RAM if desired + GLuint m_nCompCount; // comp count of the attribute (1-4) + GLenum m_datatype; // data type of the attribute (GL_FLOAT, GL_UNSIGNED_BYTE, etc) + GLuint m_stride; + GLuint m_offset; // net offset to attribute 'zero' within the buffer. + GLuint m_streamOffset; // net offset to attribute 'zero' within the buffer. + GLboolean m_normalized; // apply to any fixed point data that needs normalizing, esp color bytes + + inline uint GetDataTypeSizeInBytes() const + { + switch ( m_datatype ) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return 1; + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_HALF_FLOAT: + return 2; + case GL_INT: + case GL_FLOAT: + return 4; + default: + Assert( 0 ); + break; + } + return 0; + } + + inline uint GetTotalAttributeSizeInBytes() const { Assert( m_nCompCount ); return m_nCompCount * GetDataTypeSizeInBytes(); } + + // may need a seed value at some point to be able to disambiguate re-lifed buffers holding same pointer + // simpler alternative is to do shoot-down inside the vertex/index buffer free calls. + // I'd rather not have to have each attribute fiddling a ref count on the buffer to which it refers.. + +//#define EQ(fff) ( (src.fff) == (fff) ) + // test in decreasing order of likelihood of difference, but do not include the buffer revision as caller is not supplying it.. + //inline bool operator== ( const GLMVertexAttributeDesc& src ) const { return EQ( m_pBuffer ) && EQ( m_offset ) && EQ( m_stride ) && EQ( m_datatype ) && EQ( m_normalized ) && EQ( m_nCompCount ); } +//#undef EQ + + uint m_bufferRevision; // only set in GLM context's copy, to disambiguate references that are same offset / same buffer but cross an orphan event +}; + +#define MAX_D3DVERTEXELEMENTS 16 + +struct D3DVERTEXELEMENT9_GL +{ + // fields right out of the original decl element (copied) + D3DVERTEXELEMENT9 m_dxdecl; // d3d info + // WORD Stream; // Stream index + // WORD Offset; // Offset in the stream in bytes + // BYTE Type; // Data type + // BYTE Method; // Processing method + // BYTE Usage; // Semantics + // BYTE UsageIndex; // Semantic index + + GLMVertexAttributeDesc m_gldecl; + // CGLMBuffer *m_buffer; // late-dropped from selected stream desc (left NULL, will replace with stream source buffer at sync time) + // GLuint m_datasize; // component count (1,2,3,4) of the attrib + // GLenum m_datatype; // data type of the attribute (GL_FLOAT et al) + // GLuint m_stride; // late-dropped from stream desc + // GLuint m_offset; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. + // GLuint m_normalized; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. +}; + +struct IDirect3DDevice9Params +{ + UINT m_adapter; + D3DDEVTYPE m_deviceType; + VD3DHWND m_focusWindow; + DWORD m_behaviorFlags; + D3DPRESENT_PARAMETERS m_presentationParameters; +}; + +#define D3D_MAX_STREAMS 4 +struct D3DStreamDesc +{ + IDirect3DVertexBuffer9 *m_vtxBuffer; + uint m_offset; + uint m_stride; +}; + +struct D3DIndexDesc +{ + IDirect3DIndexBuffer9 *m_idxBuffer; +}; + +// we latch sampler values until draw time and then convert them all to GL form +// note these are similar in name to the fields of a GLMTexSamplingParams but contents are not +// particularly in the texture filtering area + +struct D3DSamplerDesc +{ + DWORD m_srgb; // D3DSAMP_SRGBTEXTURE 0 = no SRGB sampling +}; + +// Tracking and naming sampler dimensions +#define SAMPLER_TYPE_2D 0 +#define SAMPLER_TYPE_CUBE 1 +#define SAMPLER_TYPE_3D 2 +#define SAMPLER_TYPE_UNUSED 3 + +#endif // DXABSTRACT_TYPES_H diff --git a/mp/src/public/togl/linuxwin/glbase.h b/mp/src/public/togl/linuxwin/glbase.h new file mode 100644 index 00000000..445d3665 --- /dev/null +++ b/mp/src/public/togl/linuxwin/glbase.h @@ -0,0 +1,104 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glbase.h +// +//=============================================================================== + +#ifndef GLBASE_H +#define GLBASE_H + +#ifdef DX_TO_GL_ABSTRACTION + +#undef HAVE_GL_ARB_SYNC + +#ifndef OSX + #define HAVE_GL_ARB_SYNC 1 +#endif + +#ifdef OSX + #include + #include + #include + #include + #include + #include + #include + #include +#elif defined(DX_TO_GL_ABSTRACTION) + #include + #include +#else + #error +#endif + +#ifdef DX_TO_GL_ABSTRACTION + #ifndef WIN32 + #define Debugger DebuggerBreak + #endif + #undef CurrentTime + + // prevent some conflicts in SDL headers... + #undef M_PI + #include + #ifndef _STDINT_H_ + #define _STDINT_H_ 1 + #endif +#endif + +//=============================================================================== +// glue to call out to Obj-C land (these are in glmgrcocoa.mm) +#ifdef OSX + bool NewNSGLContext( unsigned long *attribs, PseudoNSGLContextPtr nsglShareCtx, PseudoNSGLContextPtr *nsglCtxOut, CGLContextObj *cglCtxOut ); + CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx ); + void DelNSGLContext( PseudoNSGLContextPtr nsglCtx ); +#endif + +// Set TOGL_SUPPORT_NULL_DEVICE to 1 to support the NULL ref device +#define TOGL_SUPPORT_NULL_DEVICE 0 + +#if TOGL_SUPPORT_NULL_DEVICE + #define TOGL_NULL_DEVICE_CHECK if( m_params.m_deviceType == D3DDEVTYPE_NULLREF ) return S_OK; + #define TOGL_NULL_DEVICE_CHECK_RET_VOID if( m_params.m_deviceType == D3DDEVTYPE_NULLREF ) return; +#else + #define TOGL_NULL_DEVICE_CHECK + #define TOGL_NULL_DEVICE_CHECK_RET_VOID +#endif + +// GL_ENABLE_INDEX_VERIFICATION enables index range verification on all dynamic IB/VB's (obviously slow) +#define GL_ENABLE_INDEX_VERIFICATION 0 + +// GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION (currently win32 only) - If 1, VirtualAlloc/VirtualProtect is used to detect cases where the app locks a buffer, copies the ptr away, unlocks, then tries to later write to the buffer. +#define GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION 0 + +#define GL_BATCH_TELEMETRY_ZONES 0 + +// GL_BATCH_PERF_ANALYSIS - Enables gl_batch_vis, and various per-batch telemetry statistics messages. +#define GL_BATCH_PERF_ANALYSIS 0 +#define GL_BATCH_PERF_ANALYSIS_WRITE_PNGS 0 + +// GL_TELEMETRY_ZONES - Causes every single OpenGL call to generate a telemetry event +#define GL_TELEMETRY_ZONES 0 + +// GL_DUMP_ALL_API_CALLS - Causes a debug message to be printed for every API call if s_bDumpCalls bool is set to 1 +#define GL_DUMP_ALL_API_CALLS 0 + +// Must also enable PIX_ENABLE to use GL_TELEMETRY_GPU_ZONES. +#define GL_TELEMETRY_GPU_ZONES 0 + +// Records global # of OpenGL calls/total cycles spent inside GL +#define GL_TRACK_API_TIME GL_BATCH_PERF_ANALYSIS + +#define GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS ( GL_TELEMETRY_ZONES || GL_TRACK_API_TIME || GL_DUMP_ALL_API_CALLS ) + +#if GL_BATCH_PERF_ANALYSIS + #define GL_BATCH_PERF(...) __VA_ARGS__ +#else + #define GL_BATCH_PERF(...) +#endif + +#define kGLMUserClipPlanes 2 +#define kGLMScratchFBOCount 4 + +#endif // DX_TO_GL_ABSTRACTION + +#endif // GLBASE_H diff --git a/mp/src/public/togl/linuxwin/glentrypoints.h b/mp/src/public/togl/linuxwin/glentrypoints.h new file mode 100644 index 00000000..d1347175 --- /dev/null +++ b/mp/src/public/togl/linuxwin/glentrypoints.h @@ -0,0 +1,378 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glentrypoints.h +// +//=============================================================================== + +#ifndef GLENTRYPOINTS_H +#define GLENTRYPOINTS_H + +#pragma once + +#ifdef DX_TO_GL_ABSTRACTION + +#include "tier0/platform.h" +#include "tier0/dynfunction.h" +#include "tier0/vprof_telemetry.h" +#include "interface.h" + +#include "togl/rendermechanism.h" + +void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback=NULL); + +#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS +class CGLExecuteHelperBase +{ +public: + inline void StartCall(const char *pName); + inline void StopCall(const char *pName); +#if GL_TRACK_API_TIME + TmU64 m_nStartTime; +#endif +}; + +template < class FunctionType, typename Result > +class CGLExecuteHelper : public CGLExecuteHelperBase +{ +public: + inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } + + inline operator Result() const { return m_Result; } + inline operator char*() const { return (char*)m_Result; } + + FunctionType m_pFn; + + Result m_Result; +}; + +template < class FunctionType> +class CGLExecuteHelper : public CGLExecuteHelperBase +{ +public: + inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } + + FunctionType m_pFn; +}; +#endif + +template < class FunctionType, typename Result > +class CDynamicFunctionOpenGLBase +{ +public: + // Construct with a NULL function pointer. You must manually call + // Lookup() before you can call a dynamic function through this interface. + CDynamicFunctionOpenGLBase() : m_pFn(NULL) {} + + // Construct and do a lookup right away. You will need to make sure that + // the lookup actually succeeded, as the gl library might have failed to load + // or (fn) might not exist in it. + CDynamicFunctionOpenGLBase(const char *fn, FunctionType fallback=NULL) : m_pFn(NULL) + { + Lookup(fn, fallback); + } + + // Construct and do a lookup right away. See comments in Lookup() about what (okay) does. + CDynamicFunctionOpenGLBase(const char *fn, bool &okay, FunctionType fallback=NULL) : m_pFn(NULL) + { + Lookup(fn, okay, fallback); + } + + // Load library if necessary, look up symbol. Returns true and sets + // m_pFn on successful lookup, returns false otherwise. If the + // function pointer is already looked up, this return true immediately. + // Use Reset() first if you want to look up the symbol again. + // This function will return false immediately unless (okay) is true. + // This allows you to chain lookups like this: + // bool okay = true; + // x.Lookup(lib, "x", okay); + // y.Lookup(lib, "y", okay); + // z.Lookup(lib, "z", okay); + // if (okay) { printf("All functions were loaded successfully!\n"); } + // If you supply a fallback, it'll be used if the lookup fails (and if + // non-NULL, means this will always return (okay)). + bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) + { + if (!okay) + return false; + else if (this->m_pFn == NULL) + { + this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, false, (void *) fallback); + this->SetFuncName( fn ); + } + okay = m_pFn != NULL; + return okay; + } + + // Load library if necessary, look up symbol. Returns true and sets + // m_pFn on successful lookup, returns false otherwise. If the + // function pointer is already looked up, this return true immediately. + // Use Reset() first if you want to look up the symbol again. + // This function will return false immediately unless (okay) is true. + // If you supply a fallback, it'll be used if the lookup fails (and if + // non-NULL, means this will always return true). + bool Lookup(const char *fn, FunctionType fallback=NULL) + { + bool okay = true; + return Lookup(fn, okay, fallback); + } + + // Invalidates the current lookup. Makes the function pointer NULL. You + // will need to call Lookup() before you can call a dynamic function + // through this interface again. + void Reset() { m_pFn = NULL; } + + // Force this to be a specific function pointer. + void Force(FunctionType ptr) { m_pFn = ptr; } + + // Retrieve the actual function pointer. + FunctionType Pointer() const { return m_pFn; } + +#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS + #if GL_TELEMETRY_ZONES || GL_DUMP_ALL_API_CALLS + #define GL_FUNC_NAME m_szName + #else + #define GL_FUNC_NAME "" + #endif + + inline CGLExecuteHelper operator() () const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME ); } + + template + inline CGLExecuteHelper operator() (T a) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a); } + + template + inline CGLExecuteHelper operator() (T a, U b) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c ) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i, C j) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i, j); } +#else + operator FunctionType() const { return m_pFn; } +#endif + + // Can be used to verify that we have an actual function looked up and + // ready to call: if (!MyDynFunc) { printf("Function not found!\n"); } + operator bool () const { return m_pFn != NULL; } + bool operator !() const { return m_pFn == NULL; } + +protected: + FunctionType m_pFn; + +#if GL_TELEMETRY_ZONES || GL_DUMP_ALL_API_CALLS + char m_szName[32]; + inline void SetFuncName(const char *pFn) { V_strncpy( m_szName, pFn, sizeof( m_szName ) ); } +#else + inline void SetFuncName(const char *pFn) { (void)pFn; } +#endif +}; + +// This works a lot like CDynamicFunctionMustInit, but we use SDL_GL_GetProcAddress(). +template < const bool bRequired, class FunctionType, typename Result > +class CDynamicFunctionOpenGL : public CDynamicFunctionOpenGLBase< FunctionType, Result > +{ +private: // forbid default constructor. + CDynamicFunctionOpenGL() {} + +public: + CDynamicFunctionOpenGL(const char *fn, FunctionType fallback=NULL) + { + bool okay = true; + Lookup(fn, okay, fallback); + this->SetFuncName( fn ); + } + + CDynamicFunctionOpenGL(const char *fn, bool &okay, FunctionType fallback=NULL) + { + Lookup(fn, okay, fallback); + this->SetFuncName( fn ); + } + + // Please note this is not virtual. + // !!! FIXME: we might want to fall back and try "EXT" or "ARB" versions in some case. + bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) + { + if (this->m_pFn == NULL) + { + this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, bRequired, (void *) fallback); + this->SetFuncName( fn ); + } + return okay; + } +}; + +enum GLDriverStrings_t +{ + cGLVendorString, + cGLRendererString, + cGLVersionString, + cGLExtensionsString, + + cGLTotalDriverStrings +}; + +enum GLDriverProvider_t +{ + cGLDriverProviderUnknown, + cGLDriverProviderNVIDIA, + cGLDriverProviderAMD, + cGLDriverProviderIntel, + cGLDriverProviderIntelOpenSource, + cGLDriverProviderApple, + + cGLTotalDriverProviders +}; + +// This provides all the entry points for a given OpenGL context. +// ENTRY POINTS ARE ONLY VALID FOR THE CONTEXT THAT WAS CURRENT WHEN +// YOU LOOKED THEM UP. 99% of the time, this is not a problem, but +// that 1% is really hard to track down. Always access the GL +// through this class! +class COpenGLEntryPoints +{ + COpenGLEntryPoints( const COpenGLEntryPoints & ); + COpenGLEntryPoints &operator= ( const COpenGLEntryPoints & ); + +public: + // The GL context you are looking up entry points for must be current when you construct this object! + COpenGLEntryPoints(); + ~COpenGLEntryPoints(); + + void ClearEntryPoints(); + + uint64 m_nTotalGLCycles, m_nTotalGLCalls; + + int m_nOpenGLVersionMajor; // if GL_VERSION is 2.1.0, this will be set to 2. + int m_nOpenGLVersionMinor; // if GL_VERSION is 2.1.0, this will be set to 1. + int m_nOpenGLVersionPatch; // if GL_VERSION is 2.1.0, this will be set to 0. + bool m_bHave_OpenGL; + + char *m_pGLDriverStrings[cGLTotalDriverStrings]; + GLDriverProvider_t m_nDriverProvider; + + #define GL_EXT(x,glmajor,glminor) bool m_bHave_##x; + #define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn; + #define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn; + #include "togl/glfuncs.inl" + #undef GL_FUNC_VOID + #undef GL_FUNC + #undef GL_EXT + + bool HasSwapTearExtension() const + { +#ifdef _WIN32 + return m_bHave_WGL_EXT_swap_control_tear; +#else + return m_bHave_GLX_EXT_swap_control_tear; +#endif + } +}; + +// This will be set to the current OpenGL context's entry points. +extern COpenGLEntryPoints *gGL; +typedef void * (*GL_GetProcAddressCallbackFunc_t)(const char *, bool &, const bool, void *); + +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); + DLL_EXPORT void ToGLDisconnectLibraries(); + DLL_EXPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); + DLL_EXPORT void ClearOpenGLEntryPoints(); +#else + DLL_IMPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); + DLL_IMPORT void ToGLDisconnectLibraries(); + DLL_IMPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); + DLL_IMPORT void ClearOpenGLEntryPoints(); +#endif + +#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS +inline void CGLExecuteHelperBase::StartCall(const char *pName) +{ + (void)pName; + +#if GL_TELEMETRY_ZONES + tmEnter( TELEMETRY_LEVEL3, TMZF_NONE, pName ); +#endif + +#if GL_TRACK_API_TIME + m_nStartTime = tmFastTime(); +#endif + +#if GL_DUMP_ALL_API_CALLS + static bool s_bDumpCalls; + if ( s_bDumpCalls ) + { + char buf[128]; + buf[0] = 'G'; + buf[1] = 'L'; + buf[2] = ':'; + size_t l = strlen( pName ); + memcpy( buf + 3, pName, l ); + buf[3 + l] = '\n'; + buf[4 + l] = '\0'; + Plat_DebugString( buf ); + } +#endif +} + +inline void CGLExecuteHelperBase::StopCall(const char *pName) +{ +#if GL_TRACK_API_TIME + uint64 nTotalCycles = tmFastTime() - m_nStartTime; +#endif + +#if GL_TELEMETRY_ZONES + tmLeave( TELEMETRY_LEVEL3 ); +#endif + +#if GL_TRACK_API_TIME + //double flMilliseconds = g_Telemetry.flRDTSCToMilliSeconds * nTotalCycles; + if (gGL) + { + gGL->m_nTotalGLCycles += nTotalCycles; + gGL->m_nTotalGLCalls++; + } +#endif +} +#endif + +#endif // DX_TO_GL_ABSTRACTION + +#endif // GLENTRYPOINTS_H diff --git a/mp/src/public/togl/linuxwin/glfuncs.h b/mp/src/public/togl/linuxwin/glfuncs.h new file mode 100644 index 00000000..3ef3772c --- /dev/null +++ b/mp/src/public/togl/linuxwin/glfuncs.h @@ -0,0 +1,236 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// !!! FIXME: Some of these aren't base OpenGL...pick out the extensions. +// !!! FIXME: Also, look up these -1, -1 versions numbers. +GL_FUNC(OpenGL,true,GLenum,glGetError,(void),()) +GL_FUNC_VOID(OpenGL,true,glActiveTexture,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glAlphaFunc,(GLenum a,GLclampf b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glAttachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBegin,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glBindAttribLocationARB,(GLhandleARB a,GLuint b,const GLcharARB *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glBindBufferARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindProgramARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindTexture,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBlendColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glBlendEquation,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glBlendFunc,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBufferDataARB,(GLenum a,GLsizeiptrARB b,const GLvoid *c,GLenum d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glClear,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glClearColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glClearDepth,(GLclampd a),(a)) +GL_FUNC_VOID(OpenGL,true,glClearStencil,(GLint a),(a)) +GL_FUNC_VOID(OpenGL,true,glClipPlane,(GLenum a,const GLdouble *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glColorMask,(GLboolean a,GLboolean b,GLboolean c,GLboolean d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glCompileShaderARB,(GLhandleARB a),(a)) +GL_FUNC_VOID(OpenGL,true,glCompressedTexImage2D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLint f,GLsizei g,const GLvoid *h),(a,b,c,d,e,f,g,h)) +GL_FUNC_VOID(OpenGL,true,glCompressedTexImage3D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLsizei h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC(OpenGL,true,GLhandleARB,glCreateProgramObjectARB,(void),()) +GL_FUNC(OpenGL,true,GLhandleARB,glCreateShaderObjectARB,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteBuffersARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteObjectARB,(GLhandleARB a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteProgramsARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteQueriesARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteShader,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteTextures,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDepthFunc,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDepthMask,(GLboolean a),(a)) +GL_FUNC_VOID(OpenGL,true,glDepthRange,(GLclampd a,GLclampd b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDetachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDisable,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDisableVertexAttribArray,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawArrays,(GLenum a,GLint b,GLsizei c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glDrawBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawRangeElements,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glDrawRangeElementsBaseVertex,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f, GLenum g),(a,b,c,d,e,f,g)) +GL_FUNC_VOID(OpenGL,true,glEnable,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glEnableVertexAttribArray,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glEnd,(void),()) +GL_FUNC_VOID(OpenGL,true,glFinish,(void),()) +GL_FUNC_VOID(OpenGL,true,glFlush,(void),()) +GL_FUNC_VOID(OpenGL,true,glFrontFace,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glGenBuffersARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenProgramsARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenQueriesARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenTextures,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetBooleanv,(GLenum a,GLboolean *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetCompressedTexImage,(GLenum a,GLint b,GLvoid *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGetDoublev,(GLenum a,GLdouble *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetFloatv,(GLenum a,GLfloat *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetInfoLogARB,(GLhandleARB a,GLsizei b,GLsizei *c,GLcharARB *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glGetIntegerv,(GLenum a,GLint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetObjectParameterivARB,(GLhandleARB a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGetProgramivARB,(GLenum a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC(OpenGL,true,const GLubyte *,glGetString,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glGetTexImage,(GLenum a,GLint b,GLenum c,GLenum d,GLvoid *e),(a,b,c,d,e)) +GL_FUNC(OpenGL,true,GLint,glGetUniformLocationARB,(GLhandleARB a,const GLcharARB *b),(a,b)) +GL_FUNC(OpenGL,true,GLboolean,glIsEnabled,(GLenum a),(a)) +GL_FUNC(OpenGL,true,GLboolean,glIsTexture,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glLinkProgramARB,(GLhandleARB a),(a)) +GL_FUNC(OpenGL,true,GLvoid*,glMapBufferARB,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glOrtho,(GLdouble a,GLdouble b,GLdouble c,GLdouble d,GLdouble e,GLdouble f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glPixelStorei,(GLenum a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPolygonMode,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPolygonOffset,(GLfloat a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPopAttrib,(void),()) +GL_FUNC_VOID(OpenGL,true,glProgramStringARB,(GLenum a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glPushAttrib,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glReadBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glScissor,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glShaderSourceARB,(GLhandleARB a,GLsizei b,const GLcharARB **c,const GLint *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glStencilFunc,(GLenum a,GLint b,GLuint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glStencilMask,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glStencilOp,(GLenum a,GLenum b,GLenum c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexCoord2f,(GLfloat a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glTexImage2D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLint f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC_VOID(OpenGL,true,glTexImage3D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLenum h,GLenum i,const GLvoid *j),(a,b,c,d,e,f,g,h,i,j)) +GL_FUNC_VOID(OpenGL,true,glTexParameterfv,(GLenum a,GLenum b,const GLfloat *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexParameteri,(GLenum a,GLenum b,GLint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexSubImage2D,(GLenum a,GLint b,GLint c,GLint d,GLsizei e,GLsizei f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC_VOID(OpenGL,true,glUniform1f,(GLint a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform1i,(GLint a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform1iARB,(GLint a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform4fv,(GLint a,GLsizei b,const GLfloat *c),(a,b,c)) +GL_FUNC(OpenGL,true,GLboolean,glUnmapBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glUseProgram,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glVertex3f,(GLfloat a,GLfloat b,GLfloat c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glVertexAttribPointer,(GLuint a,GLint b,GLenum c,GLboolean d,GLsizei e,const GLvoid *f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glViewport,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glEnableClientState,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDisableClientState,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glClientActiveTexture,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glVertexPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glTexCoordPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glProgramEnvParameters4fvEXT,(GLenum a,GLuint b,GLsizei c,const GLfloat *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glColor4sv,(const GLshort *a),(a)) +GL_FUNC_VOID(OpenGL,true,glStencilOpSeparate,(GLenum a,GLenum b,GLenum c,GLenum d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glStencilFuncSeparate,(GLenum a,GLenum b,GLint c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glGetTexLevelParameteriv,(GLenum a,GLint b,GLenum c,GLint *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glColor4f,(GLfloat a,GLfloat b,GLfloat c,GLfloat d),(a,b,c,d)) +GL_EXT(GL_EXT_framebuffer_object,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindFramebufferEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindRenderbufferEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC(GL_EXT_framebuffer_object,false,GLenum,glCheckFramebufferStatusEXT,(GLenum a),(a)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteRenderbuffersEXT,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferRenderbufferEXT,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture2DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture3DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenFramebuffersEXT,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenRenderbuffersEXT,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteFramebuffersEXT,(GLsizei a,const GLuint *b),(a,b)) +GL_EXT(GL_EXT_framebuffer_blit,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_blit,false,glBlitFramebufferEXT,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) +GL_EXT(GL_EXT_framebuffer_multisample,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_multisample,false,glRenderbufferStorageMultisampleEXT,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) +GL_EXT(GL_APPLE_fence,-1,-1) +GL_FUNC(GL_APPLE_fence,false,GLboolean,glTestFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glSetFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glFinishFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glDeleteFencesAPPLE,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_APPLE_fence,false,glGenFencesAPPLE,(GLsizei a,GLuint *b),(a,b)) +GL_EXT(GL_NV_fence,-1,-1) +GL_FUNC(GL_NV_fence,false,GLboolean,glTestFenceNV,(GLuint a),(a)) +GL_FUNC_VOID(GL_NV_fence,false,glSetFenceNV,(GLuint a,GLenum b),(a,b)) +GL_FUNC_VOID(GL_NV_fence,false,glFinishFenceNV,(GLuint a),(a)) +GL_FUNC_VOID(GL_NV_fence,false,glDeleteFencesNV,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_NV_fence,false,glGenFencesNV,(GLsizei a,GLuint *b),(a,b)) +GL_EXT(GL_ARB_sync,3,2) +#ifdef HAVE_GL_ARB_SYNC +GL_FUNC_VOID(GL_ARB_sync,false,glGetSynciv,(GLsync a, GLenum b, GLsizei c, GLsizei *d, GLint *e),(a,b,c,d,e)) +GL_FUNC(GL_ARB_sync,false,GLenum,glClientWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_sync,false,glWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_sync,false,glDeleteSync,(GLsync a),(a)) +GL_FUNC(GL_ARB_sync,false,GLsync,glFenceSync,(GLenum a, GLbitfield b),(a,b)) +#endif +GL_EXT(GL_EXT_draw_buffers2,-1,-1) +GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glColorMaskIndexedEXT,(GLuint a,GLboolean b,GLboolean c,GLboolean d,GLboolean e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glEnableIndexedEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glDisableIndexedEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glGetBooleanIndexedvEXT,(GLenum a,GLuint b,GLboolean *c),(a,b,c)) +GL_EXT(GL_EXT_bindable_uniform,-1,-1) +GL_FUNC_VOID(GL_EXT_bindable_uniform,false,glUniformBufferEXT,(GLuint a,GLint b,GLuint c),(a,b,c)) +GL_FUNC(GL_EXT_bindable_uniform,false,int,glGetUniformBufferSizeEXT,(GLenum a, GLenum b),(a,b)) +GL_FUNC(GL_EXT_bindable_uniform,false,GLintptr,glGetUniformOffsetEXT,(GLenum a, GLenum b),(a,b)) +GL_EXT(GL_APPLE_flush_buffer_range,-1,-1) +GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glBufferParameteriAPPLE,(GLenum a,GLenum b,GLint c),(a,b,c)) +GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glFlushMappedBufferRangeAPPLE,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) +GL_EXT(GL_ARB_map_buffer_range,-1,-1) +GL_FUNC(GL_ARB_map_buffer_range,false,void*,glMapBufferRange,(GLenum a,GLintptr b,GLsizeiptr c,GLbitfield d),(a,b,c,d)) +GL_FUNC_VOID(GL_ARB_map_buffer_range,false,glFlushMappedBufferRange,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) +GL_EXT(GL_ARB_vertex_buffer_object,-1,-1) +GL_FUNC_VOID(GL_ARB_vertex_buffer_object,true,glBufferSubData,(GLenum a,GLintptr b,GLsizeiptr c,const GLvoid *d),(a,b,c,d)) +GL_EXT(GL_ARB_occlusion_query,-1,-1) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glBeginQueryARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glEndQueryARB,(GLenum a),(a)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectivARB,(GLuint a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectuivARB,(GLuint a,GLenum b,GLuint *c),(a,b,c)) +GL_EXT(GL_APPLE_texture_range,-1,-1) +GL_FUNC_VOID(GL_APPLE_texture_range,false,glTextureRangeAPPLE,(GLenum a,GLsizei b,void *c),(a,b,c)) +GL_FUNC_VOID(GL_APPLE_texture_range,false,glGetTexParameterPointervAPPLE,(GLenum a,GLenum b,void* *c),(a,b,c)) +GL_EXT(GL_APPLE_client_storage,-1,-1) +GL_EXT(GL_ARB_uniform_buffer,-1,-1) +GL_EXT(GL_ARB_vertex_array_bgra,-1,-1) +GL_EXT(GL_EXT_vertex_array_bgra,-1,-1) +GL_EXT(GL_ARB_framebuffer_object,3,0) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindFramebuffer,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindRenderbuffer,(GLenum a,GLuint b),(a,b)) +GL_FUNC(GL_ARB_framebuffer_object,false,GLenum,glCheckFramebufferStatus,(GLenum a),(a)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteRenderbuffers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferRenderbuffer,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture2D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture3D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenFramebuffers,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenRenderbuffers,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteFramebuffers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBlitFramebuffer,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glRenderbufferStorageMultisample,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) +GL_EXT(GL_GREMEDY_string_marker,-1,-1) +GL_FUNC_VOID(GL_GREMEDY_string_marker,false,glStringMarkerGREMEDY,(GLsizei a,const void *b),(a,b)) +GL_EXT(GL_ARB_debug_output,-1,-1) +GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageCallbackARB,(void (APIENTRY *a)(GLenum, GLenum , GLuint , GLenum , GLsizei , const GLchar* , GLvoid*) ,void* b),(a,b)) +GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageControlARB,(GLenum a, GLenum b, GLenum c, GLsizei d, const GLuint* e, GLboolean f),(a,b,c,d,e,f)) +GL_EXT(GL_EXT_direct_state_access,-1,-1) +GL_FUNC_VOID(GL_EXT_direct_state_access,false,glBindMultiTextureEXT,(GLenum a,GLuint b, GLuint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGenSamplers,(GLuint a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteSamplers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindSampler,(GLuint a, GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glSamplerParameteri,(GLuint a, GLenum b, GLint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glSamplerParameterf,(GLuint a, GLenum b, GLfloat c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glSamplerParameterfv,(GLuint a, GLenum b, const GLfloat *c),(a,b,c)) +GL_EXT(GL_NV_bindless_texture,-1,-1) +GL_FUNC(GL_NV_bindless_texture, false, GLuint64, glGetTextureHandleNV, (GLuint texture), (texture)) +GL_FUNC(GL_NV_bindless_texture, false, GLuint64, glGetTextureSamplerHandleNV, (GLuint texture, GLuint sampler), (texture, sampler)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glMakeTextureHandleResidentNV, (GLuint64 handle), (handle)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glMakeTextureHandleNonResidentNV, (GLuint64 handle), (handle)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glUniformHandleui64NV, (GLint location, GLuint64 value), (location, value)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glUniformHandleui64vNV, (int location, GLsizei count, const GLuint64 *value), (location count, value)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glProgramUniformHandleui64NV, (GLuint program, GLint location, GLuint64 value), (program, location, value)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glProgramUniformHandleui64vNV, (GLuint program, GLint location, GLsizei count, const GLuint64 *values), (program, location, count, values)) +GL_FUNC(GL_NV_bindless_texture, false, GLboolean, glIsTextureHandleResidentNV, (GLuint64 handle), (handle)) +GL_FUNC_VOID(OpenGL,true,glGenQueries,(GLsizei n, GLuint *ids), (n, ids)) +GL_FUNC_VOID(OpenGL,true,glDeleteQueries,(GLsizei n, const GLuint *ids),(n, ids)) +GL_FUNC_VOID(OpenGL,true,glBeginQuery,(GLenum target, GLuint id), (target, id)) +GL_FUNC_VOID(OpenGL,true,glEndQuery,(GLenum target), (target)) +GL_FUNC_VOID(OpenGL,true,glQueryCounter,(GLuint id, GLenum target), (id, target)) +GL_FUNC_VOID(OpenGL,true,glGetQueryObjectiv,(GLuint id, GLenum pname, GLint *params), (id, pname, params)) +GL_FUNC_VOID(OpenGL,true,glGetQueryObjectui64v,(GLuint id, GLenum pname, GLuint64 *params), (id, pname, params)) +GL_FUNC_VOID(OpenGL,true,glCopyBufferSubData,(GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size),(readtarget, writetarget, readoffset, writeoffset, size)) +GL_EXT(GL_AMD_pinned_memory,-1,-1) +GL_EXT(GL_EXT_framebuffer_multisample_blit_scaled,-1,-1) +GL_FUNC_VOID(OpenGL,true,glGenVertexArrays,(GLsizei n, GLuint *arrays),(n, arrays)) +GL_FUNC_VOID(OpenGL,true,glDeleteVertexArrays,(GLsizei n, GLuint *arrays),(n, arrays)) +GL_FUNC_VOID(OpenGL,true,glBindVertexArray,(GLuint a),(a)) +GL_EXT(GL_EXT_texture_sRGB_decode,-1,-1) +GL_FUNC_VOID(OpenGL,true,glPushClientAttrib,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glPopClientAttrib,(void),()) +GL_EXT(GL_NVX_gpu_memory_info,-1,-1) +GL_EXT(GL_ATI_meminfo,-1,-1) +GL_EXT(GL_EXT_texture_compression_s3tc,-1,-1) +GL_EXT(GL_EXT_texture_compression_dxt1,-1,-1) +GL_EXT(GL_ANGLE_texture_compression_dxt3,-1,-1) +GL_EXT(GL_ANGLE_texture_compression_dxt5,-1,-1) + +// This one is an OS extension. We'll add a little helper function to look for it. +#ifdef _WIN32 + GL_EXT(WGL_EXT_swap_control_tear,-1,-1) +#else + GL_EXT(GLX_EXT_swap_control_tear,-1,-1) +#endif diff --git a/mp/src/public/togl/linuxwin/glmdebug.h b/mp/src/public/togl/linuxwin/glmdebug.h new file mode 100644 index 00000000..80df86f1 --- /dev/null +++ b/mp/src/public/togl/linuxwin/glmdebug.h @@ -0,0 +1,160 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef GLMDEBUG_H +#define GLMDEBUG_H + +#include "tier0/platform.h" + +// include this anywhere you need to be able to compile-out code related specifically to GLM debugging. + +// we expect DEBUG to be driven by the build system so you can include this header anywhere. +// when we come out, GLMDEBUG will be defined to a value - 0, 1, or 2 +// 0 means no GLM debugging is possible +// 1 means it's possible and resulted from being a debug build +// 2 means it's possible and resulted from being manually forced on for a release build + +#ifdef POSIX + #ifndef GLMDEBUG + #ifdef DEBUG + #define GLMDEBUG 1 // normally 1 here, testing + #else + // #define GLMDEBUG 2 // don't check this in enabled.. + #endif + + #ifndef GLMDEBUG + #define GLMDEBUG 0 + #endif + #endif +#else + #ifndef GLMDEBUG + #define GLMDEBUG 0 + #endif +#endif + + +//=============================================================================== +// debug channels + +enum EGLMDebugChannel +{ + ePrintf, + eDebugger, + eGLProfiler +}; + +#if GLMDEBUG + // make all these prototypes disappear in non GLMDEBUG + void GLMDebugInitialize( bool forceReinit=false ); + + bool GLMDetectOGLP( void ); + bool GLMDetectGDB( void ); + uint GLMDetectAvailableChannels( void ); + + uint GLMDebugChannelMask( uint *newValue = NULL ); + // note that GDB and OGLP can both come and go during run - forceCheck will allow that to be detected. + // mask returned is in form of 1< < + eComment, // 3 one off messages --- + eMatrixData, // 4 matrix data -M- + eShaderData, // 5 shader data (params) -S- + eFrameBufData, // 6 FBO data (attachments) -F- + eDXStuff, // 7 dxabstract spew -X- + eAllocations, // 8 tracking allocs and frees -A- + eSlowness, // 9 slow things happening (srgb flips..) -Z- + eDefaultFlavor, // not specified (no marker) + eFlavorCount +}; +uint GLMDebugFlavorMask( uint *newValue = NULL ); + +// make all these prototypes disappear in non GLMDEBUG +#if GLMDEBUG + // these are unconditional outputs, they don't interrogate the string + void GLMStringOut( const char *string ); + void GLMStringOutIndented( const char *string, int indentColumns ); + + #ifdef TOGL_DLL_EXPORT + // these will look at the string to guess its flavor: <, >, ---, -M-, -S- + DLL_EXPORT void GLMPrintfVA( const char *fmt, va_list vargs ); + DLL_EXPORT void GLMPrintf( const char *fmt, ... ); + #else + DLL_IMPORT void GLMPrintfVA( const char *fmt, va_list vargs ); + DLL_IMPORT void GLMPrintf( const char *fmt, ... ); + #endif + + // these take an explicit flavor with a default value + void GLMPrintStr( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor ); + + #define GLMPRINTTEXT_NUMBEREDLINES 0x80000000 + void GLMPrintText( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor, uint options=0 ); // indent each newline + + int GLMIncIndent( int indentDelta ); + int GLMGetIndent( void ); + void GLMSetIndent( int indent ); + +#endif + +// helpful macro if you are in a position to call GLM functions directly (i.e. you live in materialsystem / shaderapidx9) +#if GLMDEBUG + #define GLMPRINTF(args) GLMPrintf args + #define GLMPRINTSTR(args) GLMPrintStr args + #define GLMPRINTTEXT(args) GLMPrintText args +#else + #define GLMPRINTF(args) + #define GLMPRINTSTR(args) + #define GLMPRINTTEXT(args) +#endif + + +//=============================================================================== +// knob twiddling +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value + DLL_EXPORT float GLMKnobToggle( char *knobname ); +#else + DLL_IMPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value + DLL_IMPORT float GLMKnobToggle( char *knobname ); +#endif + +//=============================================================================== +// other stuff + +#if GLMDEBUG +void GLMTriggerDebuggerBreak(); +inline void GLMDebugger( void ) +{ + if (GLMDebugChannelMask() & (1< +#include +#include +#include +#include +#include +#include +#elif defined(DX_TO_GL_ABSTRACTION) +#include +#include +#include "tier0/platform.h" +#else +#error +#endif + +typedef void _PseudoNSGLContext; // aka NSOpenGLContext +typedef _PseudoNSGLContext *PseudoNSGLContextPtr; + +struct GLMDisplayModeInfoFields +{ + uint m_modePixelWidth; + uint m_modePixelHeight; + uint m_modeRefreshHz; + // are we even going to talk about bit depth... not yet +}; + +struct GLMDisplayInfoFields +{ +#ifdef OSX + CGDirectDisplayID m_cgDisplayID; + CGOpenGLDisplayMask m_glDisplayMask; // result of CGDisplayIDToOpenGLDisplayMask on the cg_displayID. +#endif + uint m_displayPixelWidth; + uint m_displayPixelHeight; +}; + +struct GLMRendererInfoFields +{ + /*properties of interest and their desired values. + + kCGLRPFullScreen = 54, true + kCGLRPAccelerated = 73, true + kCGLRPWindow = 80, true + + kCGLRPRendererID = 70, informational + kCGLRPDisplayMask = 84, informational + kCGLRPBufferModes = 100, informational + kCGLRPColorModes = 103, informational + kCGLRPAccumModes = 104, informational + kCGLRPDepthModes = 105, informational + kCGLRPStencilModes = 106, informational + kCGLRPMaxAuxBuffers = 107, informational + kCGLRPMaxSampleBuffers = 108, informational + kCGLRPMaxSamples = 109, informational + kCGLRPSampleModes = 110, informational + kCGLRPSampleAlpha = 111, informational + kCGLRPVideoMemory = 120, informational + kCGLRPTextureMemory = 121, informational + kCGLRPRendererCount = 128 number of renderers in the CGLRendererInfoObj under examination + + kCGLRPOffScreen = 53, D/C + kCGLRPRobust = 75, FALSE or D/C - aka we're asking for no-fallback + kCGLRPBackingStore = 76, D/C + kCGLRPMPSafe = 78, D/C + kCGLRPMultiScreen = 81, D/C + kCGLRPCompliant = 83, D/C + */ + + + //--------------------------- info we have from CGL renderer queries, IOKit, Gestalt + //--------------------------- these are set up in the displayDB by CocoaMgr + GLint m_fullscreen; + GLint m_accelerated; + GLint m_windowed; + + GLint m_rendererID; + GLint m_displayMask; + GLint m_bufferModes; + GLint m_colorModes; + GLint m_accumModes; + GLint m_depthModes; + GLint m_stencilModes; + + GLint m_maxAuxBuffers; + GLint m_maxSampleBuffers; + GLint m_maxSamples; + GLint m_sampleModes; + GLint m_sampleAlpha; + + GLint m_vidMemory; + GLint m_texMemory; + + uint m_pciVendorID; + uint m_pciDeviceID; + char m_pciModelString[64]; + char m_driverInfoString[64]; + + //--------------------------- OS version related - set up by CocoaMgr + + // OS version found + uint m_osComboVersion; // 0x00XXYYZZ : XX major, YY minor, ZZ minor minor : 10.6.3 --> 0x000A0603. 10.5.8 --> 0x000A0508. + + //--------------------------- shorthands - also set up by CocoaMgr - driven by vendorid / deviceid + + bool m_ati; + bool m_atiR5xx; + bool m_atiR6xx; + bool m_atiR7xx; + bool m_atiR8xx; + bool m_atiNewer; + + bool m_intel; + bool m_intel95x; + bool m_intel3100; + bool m_intelNewer; + + bool m_nv; + bool m_nvG7x; + bool m_nvG8x; + bool m_nvNewer; + + //--------------------------- context query results - left blank in the display DB - but valid in a GLMContext (call ctx->Caps() to get a const ref) + + // booleans + bool m_hasGammaWrites; // aka glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT) / glEnable(GL_FRAMEBUFFER_SRGB_EXT) + bool m_hasMixedAttachmentSizes; // aka ARB_fbo in 10.6.3 - test for min OS vers, then exported ext string + bool m_hasBGRA; // aka GL_BGRA vertex attribs in 10.6.3 - - test for min OS vers, then exported ext string + bool m_hasNewFullscreenMode; // aka 10.6.x "big window" fullscreen mode + bool m_hasNativeClipVertexMode; // aka GLSL gl_ClipVertex does not fall back to SW- OS version and folklore-based + bool m_hasOcclusionQuery; // occlusion query: do you speak it ?! + bool m_hasFramebufferBlit; // framebuffer blit: know what I'm sayin?! + bool m_hasPerfPackage1; // means new MTGL, fast OQ, fast uniform upload, NV can resolve flipped (late summer 2010 post 10.6.4 update) + + // counts + int m_maxAniso; // aniso limit - context query + + // other exts + bool m_hasBindableUniforms; + int m_maxVertexBindableUniforms; + int m_maxFragmentBindableUniforms; + int m_maxBindableUniformSize; + + bool m_hasUniformBuffers; + + // runtime options that aren't negotiable once set + bool m_hasDualShaders; // must supply CLI arg "-glmdualshaders" or we go GLSL only + + //--------------------------- " can'ts " - specific problems that need to be worked around + + bool m_cantBlitReliably; // Intel chipsets have problems blitting sRGB sometimes + bool m_cantAttachSRGB; // NV G8x on 10.5.8 can't have srgb tex on FBO color - separate issue from hasGammaWrites + bool m_cantResolveFlipped; // happens on NV in 10.6.4 and prior - console variable "gl_can_resolve_flipped" can overrule + bool m_cantResolveScaled; // happens everywhere per GL spec but may be relaxed some day - console variable "gl_can_resolve_scaled" can overrule + bool m_costlyGammaFlips; // this means that sRGB sampling state affects shader code gen, resulting in state-dependent code regen + + + //--------------------------- " bads " - known bad drivers + bool m_badDriver1064NV; // this is the bad NVIDIA driver on 10.6.4 - stutter, tex corruption, black screen issues +}; + + + +#endif diff --git a/mp/src/public/togl/linuxwin/glmdisplaydb.h b/mp/src/public/togl/linuxwin/glmdisplaydb.h new file mode 100644 index 00000000..7f78f910 --- /dev/null +++ b/mp/src/public/togl/linuxwin/glmdisplaydb.h @@ -0,0 +1,92 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef GLMDISPLAYDB_H +#define GLMDISPLAYDB_H + +#include "tier1/utlvector.h" + +//=============================================================================== +// modes, displays, and renderers +//=============================================================================== + +// GLMDisplayModeInfoFields is in glmdisplay.h + +class GLMDisplayMode +{ +public: + GLMDisplayModeInfoFields m_info; + + GLMDisplayMode( uint width, uint height, uint refreshHz ); + GLMDisplayMode() { }; + ~GLMDisplayMode( void ); + + void Init( uint width, uint height, uint refreshHz ); + void Dump( int which ); +}; + +//=============================================================================== + +// GLMDisplayInfoFields is in glmdisplay.h + +class GLMDisplayInfo +{ +public: + GLMDisplayInfoFields m_info; + CUtlVector< GLMDisplayMode* > *m_modes; // starts out NULL, set by PopulateModes + + GLMDisplayInfo( void ); + ~GLMDisplayInfo( void ); + + void PopulateModes( void ); + + void Dump( int which ); +}; + +//=============================================================================== + +// GLMRendererInfoFields is in glmdisplay.h + +class GLMRendererInfo +{ +public: + GLMRendererInfoFields m_info; + GLMDisplayInfo *m_display; + + GLMRendererInfo (); + ~GLMRendererInfo ( void ); + + void Init( GLMRendererInfoFields *info ); + void PopulateDisplays(); + void Dump( int which ); +}; + +//=============================================================================== + +class GLMDisplayDB +{ +public: + GLMRendererInfo m_renderer; + + GLMDisplayDB ( void ); + ~GLMDisplayDB ( void ); + + virtual void PopulateRenderers( void ); + virtual void PopulateFakeAdapters( uint realRendererIndex ); // fake adapters = one real adapter times however many displays are on it + virtual void Populate( void ); + + // The info-get functions return false on success. + virtual int GetFakeAdapterCount( void ); + virtual bool GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut ); + + virtual int GetRendererCount( void ); + virtual bool GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut ); + + virtual int GetDisplayCount( int rendererIndex ); + virtual bool GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut ); + + virtual int GetModeCount( int rendererIndex, int displayIndex ); + virtual bool GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut ); + + virtual void Dump( void ); +}; + +#endif // GLMDISPLAYDB_H diff --git a/mp/src/public/togl/linuxwin/glmgr.h b/mp/src/public/togl/linuxwin/glmgr.h new file mode 100644 index 00000000..cc828636 --- /dev/null +++ b/mp/src/public/togl/linuxwin/glmgr.h @@ -0,0 +1,2259 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgr.h +// singleton class, common basis for managing GL contexts +// responsible for tracking adapters and contexts +// +//=============================================================================== + +#ifndef GLMGR_H +#define GLMGR_H + +#pragma once + +#include "glbase.h" +#include "glentrypoints.h" +#include "glmdebug.h" +#include "glmdisplay.h" +#include "glmgrext.h" +#include "glmgrbasics.h" +#include "cglmtex.h" +#include "cglmfbo.h" +#include "cglmprogram.h" +#include "cglmbuffer.h" +#include "cglmquery.h" + +#include "tier0/vprof_telemetry.h" +#include "materialsystem/IShader.h" +#include "dxabstract_types.h" +#include "tier0/icommandline.h" + +//=============================================================================== + +#define GLM_OPENGL_VENDOR_ID 1 +#define GLM_OPENGL_DEFAULT_DEVICE_ID 1 +#define GLM_OPENGL_LOW_PERF_DEVICE_ID 2 + +extern void GLMDebugPrintf( const char *pMsg, ... ); + +extern uint g_nTotalDrawsOrClears, g_nTotalVBLockBytes, g_nTotalIBLockBytes; + +#if GL_TELEMETRY_GPU_ZONES +struct TelemetryGPUStats_t +{ + uint m_nTotalBufferLocksAndUnlocks; + uint m_nTotalTexLocksAndUnlocks; + uint m_nTotalBlit2; + uint m_nTotalResolveTex; + uint m_nTotalPresent; + + inline void Clear() { memset( this, 0, sizeof( *this ) ); } + inline uint GetTotal() const { return m_nTotalBufferLocksAndUnlocks + m_nTotalTexLocksAndUnlocks + m_nTotalBlit2 + m_nTotalResolveTex + m_nTotalPresent; } +}; +extern TelemetryGPUStats_t g_TelemetryGPUStats; +#endif + +struct GLMRect; +typedef void *PseudoGLContextPtr; + +// parrot the D3D present parameters, more or less... "adapter" translates into "active display index" per the m_activeDisplayCount below. +class GLMDisplayParams +{ + public: + + // presumption, these indices are in sync with the current display DB that GLMgr has handy + //int m_rendererIndex; // index of renderer (-1 if root context) + //int m_displayIndex; // index of display in renderer - for FS + //int m_modeIndex; // index of mode in display - for FS + + void *m_focusWindow; // (VD3DHWND aka WindowRef) - what window does this context display into + + bool m_fsEnable; // fullscreen on or not + bool m_vsyncEnable; // vsync on or not + + // height and width have to match the display mode info if full screen. + + uint m_backBufferWidth; // pixel width (aka screen h-resolution if full screen) + uint m_backBufferHeight; // pixel height (aka screen v-resolution if full screen) + D3DFORMAT m_backBufferFormat; // pixel format + uint m_multiSampleCount; // 0 means no MSAA, 2 means 2x MSAA, etc + // uint m_multiSampleQuality; // no MSAA quality control yet + + bool m_enableAutoDepthStencil; // generally set to 'TRUE' per CShaderDeviceDx8::SetPresentParameters + D3DFORMAT m_autoDepthStencilFormat; + + uint m_fsRefreshHz; // if full screen, this refresh rate (likely 0 for LCD's) + + //uint m_rootRendererID; // only used if m_rendererIndex is -1. + //uint m_rootDisplayMask; // only used if m_rendererIndex is -1. + + bool m_mtgl; // enable multi threaded GL driver +}; + +//=============================================================================== + +class GLMgr +{ +public: + + //=========================================================================== + // class methods - singleton + static void NewGLMgr( void ); // instantiate singleton.. + static GLMgr *aGLMgr( void ); // return singleton.. + static void DelGLMgr( void ); // tear down singleton.. + + //=========================================================================== + // plain methods + + #if 0 // turned all these off while new approach is coded + void RefreshDisplayDB( void ); // blow away old display DB, make a new one + GLMDisplayDB *GetDisplayDB( void ); // get a ptr to the one GLMgr keeps. only valid til next refresh. + + // eligible renderers will be ranked by desirability starting at index 0 within the db + // within each renderer, eligible displays will be ranked some kind of desirability (area? dist from menu bar?) + // within each display, eligible modes will be ranked by descending areas + + // calls supplying indices are implicitly making reference to the current DB + bool CaptureDisplay( int rendIndex, int displayIndex, bool captureAll ); // capture one display or all displays + void ReleaseDisplays( void ); // release all captures + + int GetDisplayMode( int rendIndex, int displayIndex ); // retrieve current display res (returns modeIndex) + void SetDisplayMode( GLMDisplayParams *params ); // set the display res (only useful for FS) + #endif + + GLMContext *NewContext( IDirect3DDevice9 *pDevice, GLMDisplayParams *params ); // this will have to change + void DelContext( GLMContext *context ); + + // with usage of CGLMacro.h we could dispense with the "current context" thing + // and just declare a member variable of GLMContext, allowing each glXXX call to be routed directly + // to the correct context + void SetCurrentContext( GLMContext *context ); // make current in calling thread only + GLMContext *GetCurrentContext( void ); + +protected: + friend class GLMContext; + + GLMgr(); + ~GLMgr(); +}; + + +//===========================================================================// + +// helper function to do enable or disable in one step +FORCEINLINE void glSetEnable( GLenum which, bool enable ) +{ + if (enable) + gGL->glEnable(which); + else + gGL->glDisable(which); +} + +// helper function for int vs enum clarity +FORCEINLINE void glGetEnumv( GLenum which, GLenum *dst ) +{ + gGL->glGetIntegerv( which, (int*)dst ); +} + +//===========================================================================// +// +// types to support the GLMContext +// +//===========================================================================// + +// Each state set/get path we are providing caching for, needs its own struct and a comparison operator. +// we also provide an enum of how many such types there are, handy for building dirty masks etc. + +// shorthand macros +#define EQ(fff) ( (src.fff) == (fff) ) + +//rasterizer +struct GLAlphaTestEnable_t { GLint enable; inline bool operator==(const GLAlphaTestEnable_t& src) const { return EQ(enable); } }; +struct GLAlphaTestFunc_t { GLenum func; GLclampf ref; inline bool operator==(const GLAlphaTestFunc_t& src) const { return EQ(func) && EQ(ref); } }; +struct GLCullFaceEnable_t { GLint enable; inline bool operator==(const GLCullFaceEnable_t& src) const { return EQ(enable); } }; +struct GLCullFrontFace_t { GLenum value; inline bool operator==(const GLCullFrontFace_t& src) const { return EQ(value); } }; +struct GLPolygonMode_t { GLenum values[2]; inline bool operator==(const GLPolygonMode_t& src) const { return EQ(values[0]) && EQ(values[1]); } }; +struct GLDepthBias_t { GLfloat factor; GLfloat units; inline bool operator==(const GLDepthBias_t& src) const { return EQ(factor) && EQ(units); } }; +struct GLScissorEnable_t { GLint enable; inline bool operator==(const GLScissorEnable_t& src) const { return EQ(enable); } }; +struct GLScissorBox_t { GLint x,y; GLsizei width, height; inline bool operator==(const GLScissorBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; +struct GLAlphaToCoverageEnable_t{ GLint enable; inline bool operator==(const GLAlphaToCoverageEnable_t& src) const { return EQ(enable); } }; +struct GLViewportBox_t { GLint x,y; GLsizei width, height; uint widthheight; inline bool operator==(const GLViewportBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; +struct GLViewportDepthRange_t { GLdouble flNear,flFar; inline bool operator==(const GLViewportDepthRange_t& src) const { return EQ(flNear) && EQ(flFar); } }; +struct GLClipPlaneEnable_t { GLint enable; inline bool operator==(const GLClipPlaneEnable_t& src) const { return EQ(enable); } }; +struct GLClipPlaneEquation_t { GLfloat x,y,z,w; inline bool operator==(const GLClipPlaneEquation_t& src) const { return EQ(x) && EQ(y) && EQ(z) && EQ(w); } }; + +//blend +struct GLColorMaskSingle_t { char r,g,b,a; inline bool operator==(const GLColorMaskSingle_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLColorMaskMultiple_t { char r,g,b,a; inline bool operator==(const GLColorMaskMultiple_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLBlendEnable_t { GLint enable; inline bool operator==(const GLBlendEnable_t& src) const { return EQ(enable); } }; +struct GLBlendFactor_t { GLenum srcfactor,dstfactor; inline bool operator==(const GLBlendFactor_t& src) const { return EQ(srcfactor) && EQ(dstfactor); } }; +struct GLBlendEquation_t { GLenum equation; inline bool operator==(const GLBlendEquation_t& src) const { return EQ(equation); } }; +struct GLBlendColor_t { GLfloat r,g,b,a; inline bool operator==(const GLBlendColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLBlendEnableSRGB_t { GLint enable; inline bool operator==(const GLBlendEnableSRGB_t& src) const { return EQ(enable); } }; + +//depth +struct GLDepthTestEnable_t { GLint enable; inline bool operator==(const GLDepthTestEnable_t& src) const { return EQ(enable); } }; +struct GLDepthFunc_t { GLenum func; inline bool operator==(const GLDepthFunc_t& src) const { return EQ(func); } }; +struct GLDepthMask_t { char mask; inline bool operator==(const GLDepthMask_t& src) const { return EQ(mask); } }; + +//stencil +struct GLStencilTestEnable_t { GLint enable; inline bool operator==(const GLStencilTestEnable_t& src) const { return EQ(enable); } }; +struct GLStencilFunc_t { GLenum frontfunc, backfunc; GLint ref; GLuint mask; inline bool operator==(const GLStencilFunc_t& src) const { return EQ(frontfunc) && EQ(backfunc) && EQ(ref) && EQ(mask); } }; +struct GLStencilOp_t { GLenum sfail; GLenum dpfail; GLenum dppass; inline bool operator==(const GLStencilOp_t& src) const { return EQ(sfail) && EQ(dpfail) && EQ(dppass); } }; +struct GLStencilWriteMask_t { GLint mask; inline bool operator==(const GLStencilWriteMask_t& src) const { return EQ(mask); } }; + +//clearing +struct GLClearColor_t { GLfloat r,g,b,a; inline bool operator==(const GLClearColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLClearDepth_t { GLdouble d; inline bool operator==(const GLClearDepth_t& src) const { return EQ(d); } }; +struct GLClearStencil_t { GLint s; inline bool operator==(const GLClearStencil_t& src) const { return EQ(s); } }; + +#undef EQ + +enum EGLMStateBlockType +{ + kGLAlphaTestEnable, + kGLAlphaTestFunc, + + kGLCullFaceEnable, + kGLCullFrontFace, + + kGLPolygonMode, + + kGLDepthBias, + + kGLScissorEnable, + kGLScissorBox, + + kGLViewportBox, + kGLViewportDepthRange, + + kGLClipPlaneEnable, + kGLClipPlaneEquation, + + kGLColorMaskSingle, + kGLColorMaskMultiple, + + kGLBlendEnable, + kGLBlendFactor, + kGLBlendEquation, + kGLBlendColor, + kGLBlendEnableSRGB, + + kGLDepthTestEnable, + kGLDepthFunc, + kGLDepthMask, + + kGLStencilTestEnable, + kGLStencilFunc, + kGLStencilOp, + kGLStencilWriteMask, + + kGLClearColor, + kGLClearDepth, + kGLClearStencil, + + kGLAlphaToCoverageEnable, + + kGLMStateBlockLimit +}; + +//===========================================================================// + +// templated functions representing GL R/W bottlenecks +// one set of set/get/getdefault is instantiated for each of the GL*** types above. + +// use these from the non array state objects +template void GLContextSet( T *src ); +template void GLContextGet( T *dst ); +template void GLContextGetDefault( T *dst ); + +// use these from the array state objects +template void GLContextSetIndexed( T *src, int index ); +template void GLContextGetIndexed( T *dst, int index ); +template void GLContextGetDefaultIndexed( T *dst, int index ); + +//=============================================================================== +// template specializations for each type of state + +// --- GLAlphaTestEnable --- +FORCEINLINE void GLContextSet( GLAlphaTestEnable_t *src ) +{ + glSetEnable( GL_ALPHA_TEST, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLAlphaTestEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_ALPHA_TEST ); +} + +FORCEINLINE void GLContextGetDefault( GLAlphaTestEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + +// --- GLAlphaTestFunc --- +FORCEINLINE void GLContextSet( GLAlphaTestFunc_t *src ) +{ + gGL->glAlphaFunc( src->func, src->ref ); +} + +FORCEINLINE void GLContextGet( GLAlphaTestFunc_t *dst ) +{ + glGetEnumv( GL_ALPHA_TEST_FUNC, &dst->func ); + gGL->glGetFloatv( GL_ALPHA_TEST_REF, &dst->ref ); +} + +FORCEINLINE void GLContextGetDefault( GLAlphaTestFunc_t *dst ) +{ + dst->func = GL_ALWAYS; + dst->ref = 0.0f; +} + +// --- GLAlphaToCoverageEnable --- +FORCEINLINE void GLContextSet( GLAlphaToCoverageEnable_t *src ) +{ + glSetEnable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLAlphaToCoverageEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ); +} + +FORCEINLINE void GLContextGetDefault( GLAlphaToCoverageEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + +// --- GLCullFaceEnable --- +FORCEINLINE void GLContextSet( GLCullFaceEnable_t *src ) +{ + glSetEnable( GL_CULL_FACE, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLCullFaceEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_CULL_FACE ); +} + +FORCEINLINE void GLContextGetDefault( GLCullFaceEnable_t *dst ) +{ + dst->enable = GL_TRUE; +} + + +// --- GLCullFrontFace --- +FORCEINLINE void GLContextSet( GLCullFrontFace_t *src ) +{ + gGL->glFrontFace( src->value ); // legal values are GL_CW or GL_CCW +} + +FORCEINLINE void GLContextGet( GLCullFrontFace_t *dst ) +{ + glGetEnumv( GL_FRONT_FACE, &dst->value ); +} + +FORCEINLINE void GLContextGetDefault( GLCullFrontFace_t *dst ) +{ + dst->value = GL_CCW; +} + + +// --- GLPolygonMode --- +FORCEINLINE void GLContextSet( GLPolygonMode_t *src ) +{ + gGL->glPolygonMode( GL_FRONT, src->values[0] ); + gGL->glPolygonMode( GL_BACK, src->values[1] ); +} + +FORCEINLINE void GLContextGet( GLPolygonMode_t *dst ) +{ + glGetEnumv( GL_POLYGON_MODE, &dst->values[0] ); + +} + +FORCEINLINE void GLContextGetDefault( GLPolygonMode_t *dst ) +{ + dst->values[0] = dst->values[1] = GL_FILL; +} + + +// --- GLDepthBias --- +// note the implicit enable / disable. +// if you set non zero values, it is enabled, otherwise not. +FORCEINLINE void GLContextSet( GLDepthBias_t *src ) +{ + bool enable = (src->factor != 0.0f) || (src->units != 0.0f); + + glSetEnable( GL_POLYGON_OFFSET_FILL, enable ); + gGL->glPolygonOffset( src->factor, src->units ); +} + +FORCEINLINE void GLContextGet( GLDepthBias_t *dst ) +{ + gGL->glGetFloatv ( GL_POLYGON_OFFSET_FACTOR, &dst->factor ); + gGL->glGetFloatv ( GL_POLYGON_OFFSET_UNITS, &dst->units ); +} + +FORCEINLINE void GLContextGetDefault( GLDepthBias_t *dst ) +{ + dst->factor = 0.0; + dst->units = 0.0; +} + + +// --- GLScissorEnable --- +FORCEINLINE void GLContextSet( GLScissorEnable_t *src ) +{ + glSetEnable( GL_SCISSOR_TEST, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLScissorEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_SCISSOR_TEST ); +} + +FORCEINLINE void GLContextGetDefault( GLScissorEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLScissorBox --- +FORCEINLINE void GLContextSet( GLScissorBox_t *src ) +{ + gGL->glScissor ( src->x, src->y, src->width, src->height ); +} + +FORCEINLINE void GLContextGet( GLScissorBox_t *dst ) +{ + gGL->glGetIntegerv ( GL_SCISSOR_BOX, &dst->x ); +} + +FORCEINLINE void GLContextGetDefault( GLScissorBox_t *dst ) +{ + // hmmmm, good question? we can't really know a good answer so we pick a silly one + // and the client better come back with a better answer later. + dst->x = dst->y = 0; + dst->width = dst->height = 16; +} + + +// --- GLViewportBox --- + +FORCEINLINE void GLContextSet( GLViewportBox_t *src ) +{ + Assert( src->width == (int)( src->widthheight & 0xFFFF ) ); + Assert( src->height == (int)( src->widthheight >> 16 ) ); + gGL->glViewport (src->x, src->y, src->width, src->height ); +} + +FORCEINLINE void GLContextGet( GLViewportBox_t *dst ) +{ + gGL->glGetIntegerv ( GL_VIEWPORT, &dst->x ); + dst->widthheight = dst->width | ( dst->height << 16 ); +} + +FORCEINLINE void GLContextGetDefault( GLViewportBox_t *dst ) +{ + // as with the scissor box, we don't know yet, so pick a silly one and change it later + dst->x = dst->y = 0; + dst->width = dst->height = 16; + dst->widthheight = dst->width | ( dst->height << 16 ); +} + + +// --- GLViewportDepthRange --- +FORCEINLINE void GLContextSet( GLViewportDepthRange_t *src ) +{ + gGL->glDepthRange ( src->flNear, src->flFar ); +} + +FORCEINLINE void GLContextGet( GLViewportDepthRange_t *dst ) +{ + gGL->glGetDoublev ( GL_DEPTH_RANGE, &dst->flNear ); +} + +FORCEINLINE void GLContextGetDefault( GLViewportDepthRange_t *dst ) +{ + dst->flNear = 0.0; + dst->flFar = 1.0; +} + +// --- GLClipPlaneEnable --- +FORCEINLINE void GLContextSetIndexed( GLClipPlaneEnable_t *src, int index ) +{ +#if GLMDEBUG + if (CommandLine()->FindParm("-caps_noclipplanes")) + { + if (GLMKnob("caps-key",NULL) > 0.0) + { + // caps ON means NO clipping + src->enable = false; + } + } +#endif + glSetEnable( GL_CLIP_PLANE0 + index, src->enable != 0 ); +} + +FORCEINLINE void GLContextGetIndexed( GLClipPlaneEnable_t *dst, int index ) +{ + dst->enable = gGL->glIsEnabled( GL_CLIP_PLANE0 + index ); +} + +FORCEINLINE void GLContextGetDefaultIndexed( GLClipPlaneEnable_t *dst, int index ) +{ + dst->enable = 0; +} + + + +// --- GLClipPlaneEquation --- +FORCEINLINE void GLContextSetIndexed( GLClipPlaneEquation_t *src, int index ) +{ + // shove into glGlipPlane + GLdouble coeffs[4] = { src->x, src->y, src->z, src->w }; + + gGL->glClipPlane( GL_CLIP_PLANE0 + index, coeffs ); +} + +FORCEINLINE void GLContextGetIndexed( GLClipPlaneEquation_t *dst, int index ) +{ + DebuggerBreak(); // do this later + // glClipPlane( GL_CLIP_PLANE0 + index, coeffs ); + // GLdouble coeffs[4] = { src->x, src->y, src->z, src->w }; +} + +FORCEINLINE void GLContextGetDefaultIndexed( GLClipPlaneEquation_t *dst, int index ) +{ + dst->x = 1.0; + dst->y = 0.0; + dst->z = 0.0; + dst->w = 0.0; +} + + +// --- GLColorMaskSingle --- +FORCEINLINE void GLContextSet( GLColorMaskSingle_t *src ) +{ + gGL->glColorMask( src->r, src->g, src->b, src->a ); +} + +FORCEINLINE void GLContextGet( GLColorMaskSingle_t *dst ) +{ + gGL->glGetBooleanv( GL_COLOR_WRITEMASK, (GLboolean*)&dst->r); +} + +FORCEINLINE void GLContextGetDefault( GLColorMaskSingle_t *dst ) +{ + dst->r = dst->g = dst->b = dst->a = 1; +} + + +// --- GLColorMaskMultiple --- +FORCEINLINE void GLContextSetIndexed( GLColorMaskMultiple_t *src, int index ) +{ + gGL->glColorMaskIndexedEXT ( index, src->r, src->g, src->b, src->a ); +} + +FORCEINLINE void GLContextGetIndexed( GLColorMaskMultiple_t *dst, int index ) +{ + gGL->glGetBooleanIndexedvEXT ( GL_COLOR_WRITEMASK, index, (GLboolean*)&dst->r ); +} + +FORCEINLINE void GLContextGetDefaultIndexed( GLColorMaskMultiple_t *dst, int index ) +{ + dst->r = dst->g = dst->b = dst->a = 1; +} + + +// --- GLBlendEnable --- +FORCEINLINE void GLContextSet( GLBlendEnable_t *src ) +{ + glSetEnable( GL_BLEND, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLBlendEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_BLEND ); +} + +FORCEINLINE void GLContextGetDefault( GLBlendEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLBlendFactor --- +FORCEINLINE void GLContextSet( GLBlendFactor_t *src ) +{ + gGL->glBlendFunc ( src->srcfactor, src->dstfactor ); +} + +FORCEINLINE void GLContextGet( GLBlendFactor_t *dst ) +{ + glGetEnumv ( GL_BLEND_SRC, &dst->srcfactor ); + glGetEnumv ( GL_BLEND_DST, &dst->dstfactor ); +} + +FORCEINLINE void GLContextGetDefault( GLBlendFactor_t *dst ) +{ + dst->srcfactor = GL_ONE; + dst->dstfactor = GL_ZERO; +} + + +// --- GLBlendEquation --- +FORCEINLINE void GLContextSet( GLBlendEquation_t *src ) +{ + gGL->glBlendEquation ( src->equation ); +} + +FORCEINLINE void GLContextGet( GLBlendEquation_t *dst ) +{ + glGetEnumv ( GL_BLEND_EQUATION, &dst->equation ); +} + +FORCEINLINE void GLContextGetDefault( GLBlendEquation_t *dst ) +{ + dst->equation = GL_FUNC_ADD; +} + + +// --- GLBlendColor --- +FORCEINLINE void GLContextSet( GLBlendColor_t *src ) +{ + gGL->glBlendColor ( src->r, src->g, src->b, src->a ); +} + +FORCEINLINE void GLContextGet( GLBlendColor_t *dst ) +{ + gGL->glGetFloatv ( GL_BLEND_COLOR, &dst->r ); +} + +FORCEINLINE void GLContextGetDefault( GLBlendColor_t *dst ) +{ + //solid white + dst->r = dst->g = dst->b = dst->a = 1.0; +} + + +// --- GLBlendEnableSRGB --- + +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_COLOR_ATTACHMENT0 0x8CE0 + +FORCEINLINE void GLContextSet( GLBlendEnableSRGB_t *src ) +{ +#if GLMDEBUG + // just check in debug... this is too expensive to look at on MTGL + if (src->enable) + { + GLboolean srgb_capable = false; + gGL->glGetBooleanv( GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable); + + if (src->enable && !srgb_capable) + { + GLMPRINTF(("-Z- srgb-state-set FBO conflict: attempt to enable SRGB on non SRGB capable FBO config")); + } + } +#endif + // this query is not useful unless you have the ARB_framebuffer_srgb ext. + //GLint encoding = 0; + //pfnglGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encoding ); + + glSetEnable( GL_FRAMEBUFFER_SRGB_EXT, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLBlendEnableSRGB_t *dst ) +{ + //dst->enable = glIsEnabled( GL_FRAMEBUFFER_SRGB_EXT ); + dst->enable = true; // wtf ? +} + +FORCEINLINE void GLContextGetDefault( GLBlendEnableSRGB_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLDepthTestEnable --- +FORCEINLINE void GLContextSet( GLDepthTestEnable_t *src ) +{ + glSetEnable( GL_DEPTH_TEST, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLDepthTestEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_DEPTH_TEST ); +} + +FORCEINLINE void GLContextGetDefault( GLDepthTestEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLDepthFunc --- +FORCEINLINE void GLContextSet( GLDepthFunc_t *src ) +{ + gGL->glDepthFunc ( src->func ); +} + +FORCEINLINE void GLContextGet( GLDepthFunc_t *dst ) +{ + glGetEnumv ( GL_DEPTH_FUNC, &dst->func ); +} + +FORCEINLINE void GLContextGetDefault( GLDepthFunc_t *dst ) +{ + dst->func = GL_GEQUAL; +} + + +// --- GLDepthMask --- +FORCEINLINE void GLContextSet( GLDepthMask_t *src ) +{ + gGL->glDepthMask ( src->mask ); +} + +FORCEINLINE void GLContextGet( GLDepthMask_t *dst ) +{ + gGL->glGetBooleanv ( GL_DEPTH_WRITEMASK, (GLboolean*)&dst->mask ); +} + +FORCEINLINE void GLContextGetDefault( GLDepthMask_t *dst ) +{ + dst->mask = GL_TRUE; +} + + +// --- GLStencilTestEnable --- +FORCEINLINE void GLContextSet( GLStencilTestEnable_t *src ) +{ + glSetEnable( GL_STENCIL_TEST, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLStencilTestEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_STENCIL_TEST ); +} + +FORCEINLINE void GLContextGetDefault( GLStencilTestEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLStencilFunc --- +FORCEINLINE void GLContextSet( GLStencilFunc_t *src ) +{ + if (src->frontfunc == src->backfunc) + gGL->glStencilFuncSeparate( GL_FRONT_AND_BACK, src->frontfunc, src->ref, src->mask); + else + { + gGL->glStencilFuncSeparate( GL_FRONT, src->frontfunc, src->ref, src->mask); + gGL->glStencilFuncSeparate( GL_BACK, src->backfunc, src->ref, src->mask); + } +} + +FORCEINLINE void GLContextGet( GLStencilFunc_t *dst ) +{ + glGetEnumv ( GL_STENCIL_FUNC, &dst->frontfunc ); + glGetEnumv ( GL_STENCIL_BACK_FUNC, &dst->backfunc ); + gGL->glGetIntegerv ( GL_STENCIL_REF, &dst->ref ); + gGL->glGetIntegerv ( GL_STENCIL_VALUE_MASK, (GLint*)&dst->mask ); +} + +FORCEINLINE void GLContextGetDefault( GLStencilFunc_t *dst ) +{ + dst->frontfunc = GL_ALWAYS; + dst->backfunc = GL_ALWAYS; + dst->ref = 0; + dst->mask = 0xFFFFFFFF; +} + + +// --- GLStencilOp --- indexed 0=front, 1=back + +FORCEINLINE void GLContextSetIndexed( GLStencilOp_t *src, int index ) +{ + GLenum face = (index==0) ? GL_FRONT : GL_BACK; + gGL->glStencilOpSeparate( face, src->sfail, src->dpfail, src->dppass ); +} + +FORCEINLINE void GLContextGetIndexed( GLStencilOp_t *dst, int index ) +{ + glGetEnumv ( (index==0) ? GL_STENCIL_FAIL : GL_STENCIL_BACK_FAIL, &dst->sfail ); + glGetEnumv ( (index==0) ? GL_STENCIL_PASS_DEPTH_FAIL : GL_STENCIL_BACK_PASS_DEPTH_FAIL, &dst->dpfail ); + glGetEnumv ( (index==0) ? GL_STENCIL_PASS_DEPTH_PASS : GL_STENCIL_BACK_PASS_DEPTH_PASS, &dst->dppass ); +} + +FORCEINLINE void GLContextGetDefaultIndexed( GLStencilOp_t *dst, int index ) +{ + dst->sfail = dst->dpfail = dst->dppass = GL_KEEP; +} + + +// --- GLStencilWriteMask --- +FORCEINLINE void GLContextSet( GLStencilWriteMask_t *src ) +{ + gGL->glStencilMask( src->mask ); +} + +FORCEINLINE void GLContextGet( GLStencilWriteMask_t *dst ) +{ + gGL->glGetIntegerv ( GL_STENCIL_WRITEMASK, &dst->mask ); +} + +FORCEINLINE void GLContextGetDefault( GLStencilWriteMask_t *dst ) +{ + dst->mask = 0xFFFFFFFF; +} + + +// --- GLClearColor --- +FORCEINLINE void GLContextSet( GLClearColor_t *src ) +{ + gGL->glClearColor( src->r, src->g, src->b, src->a ); +} + +FORCEINLINE void GLContextGet( GLClearColor_t *dst ) +{ + gGL->glGetFloatv ( GL_COLOR_CLEAR_VALUE, &dst->r ); +} + +FORCEINLINE void GLContextGetDefault( GLClearColor_t *dst ) +{ + dst->r = dst->g = dst->b = 0.5; + dst->a = 1.0; +} + + +// --- GLClearDepth --- +FORCEINLINE void GLContextSet( GLClearDepth_t *src ) +{ + gGL->glClearDepth ( src->d ); +} + +FORCEINLINE void GLContextGet( GLClearDepth_t *dst ) +{ + gGL->glGetDoublev ( GL_DEPTH_CLEAR_VALUE, &dst->d ); +} + +FORCEINLINE void GLContextGetDefault( GLClearDepth_t *dst ) +{ + dst->d = 1.0; +} + + +// --- GLClearStencil --- +FORCEINLINE void GLContextSet( GLClearStencil_t *src ) +{ + gGL->glClearStencil( src->s ); +} + +FORCEINLINE void GLContextGet( GLClearStencil_t *dst ) +{ + gGL->glGetIntegerv ( GL_STENCIL_CLEAR_VALUE, &dst->s ); +} + +FORCEINLINE void GLContextGetDefault( GLClearStencil_t *dst ) +{ + dst->s = 0; +} + +//===========================================================================// + +// caching state object template. One of these is instantiated in the context per unique struct type above +template class GLState +{ + public: + inline GLState() + { + memset( &data, 0, sizeof(data) ); + Default(); + } + + FORCEINLINE void Flush() + { + // immediately blast out the state - it makes no sense to delta it or do anything fancy because shaderapi, dxabstract, and OpenGL itself does this for us (and OpenGL calls with multithreaded drivers are very cheap) + GLContextSet( &data ); + } + + // write: client src into cache + // common case is both false. dirty is calculated, context write is deferred. + FORCEINLINE void Write( const T *src ) + { + data = *src; + Flush(); + } + + // default: write default value to cache, optionally write through + inline void Default( bool noDefer=false ) + { + GLContextGetDefault( &data ); // read default values directly to our cache copy + Flush(); + } + + // read: sel = 0 for cache, 1 for context + inline void Read( T *dst, int sel ) + { + if (sel==0) + *dst = data; + else + GLContextGet( dst ); + } + + // check: verify that context equals cache, return true if mismatched or if illegal values seen + inline bool Check ( void ) + { + T temp; + bool result; + + GLContextGet( &temp ); + result = !(temp == data); + return result; + } + + FORCEINLINE const T &GetData() const { return data; } + + protected: + T data; +}; + +// caching state object template - with multiple values behind it that are indexed +template class GLStateArray +{ + public: + inline GLStateArray() + { + memset( &data, 0, sizeof(data) ); + Default(); + } + + // write cache->context if dirty or forced. + FORCEINLINE void FlushIndex( int index ) + { + // immediately blast out the state - it makes no sense to delta it or do anything fancy because shaderapi, dxabstract, and OpenGL itself does this for us (and OpenGL calls with multithreaded drivers are very cheap) + GLContextSetIndexed( &data[index], index ); + }; + + // write: client src into cache + // common case is both false. dirty is calculated, context write is deferred. + FORCEINLINE void WriteIndex( T *src, int index ) + { + data[index] = *src; + FlushIndex( index ); // dirty becomes false + }; + + // write all slots in the array + FORCEINLINE void Flush() + { + for( int i=0; i < COUNT; i++) + { + FlushIndex( i ); + } + } + + // default: write default value to cache, optionally write through + inline void DefaultIndex( int index ) + { + GLContextGetDefaultIndexed( &data[index], index ); // read default values directly to our cache copy + Flush(); + }; + + inline void Default( void ) + { + for( int i=0; i((reinterpret_cast(m_pRawBuf) + 65535) & (~65535)); + m_nSize = nSize; + m_nOfs = 0; + + gGL->glGenBuffersARB( 1, &m_nBufferObj ); + gGL->glBindBufferARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nBufferObj ); + + gGL->glBufferDataARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nSize, m_pBuf, GL_STREAM_COPY ); + + return true; + } + + void Deinit() + { + if ( !m_pRawBuf ) + return; + + BlockUntilNotBusy(); + + gGL->glBindBufferARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nBufferObj ); + + gGL->glBufferDataARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0, (void*)NULL, GL_STREAM_COPY ); + + gGL->glBindBufferARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0 ); + + gGL->glDeleteBuffersARB( 1, &m_nBufferObj ); + m_nBufferObj = 0; + + free( m_pRawBuf ); + m_pRawBuf = NULL; + m_pBuf = NULL; + + m_nSize = 0; + m_nOfs = 0; + } + + inline uint GetSize() const { return m_nSize; } + inline uint GetOfs() const { return m_nOfs; } + inline uint GetBytesRemaining() const { return m_nSize - m_nOfs; } + inline void *GetPtr() const { return m_pBuf; } + inline GLuint GetHandle() const { return m_nBufferObj; } + + void InsertFence() + { + if ( m_nSyncObj ) + { + gGL->glDeleteSync( m_nSyncObj ); + } + + m_nSyncObj = gGL->glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 ); + } + + void BlockUntilNotBusy() + { + if ( m_nSyncObj ) + { + gGL->glClientWaitSync( m_nSyncObj, GL_SYNC_FLUSH_COMMANDS_BIT, 3000000000000ULL ); + + gGL->glDeleteSync( m_nSyncObj ); + + m_nSyncObj = 0; + } + m_nOfs = 0; + } + + void Append( uint nSize ) + { + m_nOfs += nSize; + Assert( m_nOfs <= m_nSize ); + } + +private: + void *m_pRawBuf; + void *m_pBuf; + uint m_nSize; + uint m_nOfs; + + GLuint m_nBufferObj; + + GLsync m_nSyncObj; +}; + +//===========================================================================// + +class GLMContext +{ + public: + // set/check current context (perq for many other calls) + void MakeCurrent( bool bRenderThread = false ); + void ReleaseCurrent( bool bRenderThread = false ); + + // CheckCurrent has been removed (it no longer compiled on Linux). To minimize churn I'm leaving + // the inline NOP version. + // DO NOT change this to non-inlined. It's called all over the place from very hot codepaths. + FORCEINLINE void CheckCurrent( void ) { } + + void PopulateCaps( void ); // fill out later portions of renderer info record which need context queries + void DumpCaps( void ); // printf all the caps info (you can call this in release too) + const GLMRendererInfoFields& Caps( void ); // peek at the caps record + + // state cache/mirror + void SetDefaultStates( void ); + void ForceFlushStates(); + + void VerifyStates( void ); + + // textures + // Lock and Unlock reqs go directly to the tex object + CGLMTex *NewTex( GLMTexLayoutKey *key, const char *debugLabel=NULL ); + void DelTex( CGLMTex *tex ); + + // options for Blit (replacement for ResolveTex and BlitTex) + // pass NULL for dstTex if you want to target GL_BACK with the blit. You get y-flip with that, don't change the dstrect yourself. + void Blit2( CGLMTex *srcTex, GLMRect *srcRect, int srcFace, int srcMip, CGLMTex *dstTex, GLMRect *dstRect, int dstFace, int dstMip, uint filter ); + + // tex blit (via FBO blit) + void BlitTex( CGLMTex *srcTex, GLMRect *srcRect, int srcFace, int srcMip, CGLMTex *dstTex, GLMRect *dstRect, int dstFace, int dstMip, uint filter, bool useBlitFB = true ); + + // MSAA resolve - we do this in GLMContext because it has to do a bunch of FBO/blit gymnastics + void ResolveTex( CGLMTex *tex, bool forceDirty=false ); + + // texture pre-load (residency forcing) - normally done one-time but you can force it + void PreloadTex( CGLMTex *tex, bool force=false ); + + // samplers + FORCEINLINE void SetSamplerTex( int sampler, CGLMTex *tex ); + + FORCEINLINE void SetSamplerDirty( int sampler ); + FORCEINLINE void SetSamplerMinFilter( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerMagFilter( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerMipFilter( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerAddressU( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerAddressV( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerAddressW( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerStates( int sampler, GLenum AddressU, GLenum AddressV, GLenum AddressW, GLenum minFilter, GLenum magFilter, GLenum mipFilter ); + FORCEINLINE void SetSamplerBorderColor( int sampler, DWORD Value ); + FORCEINLINE void SetSamplerMipMapLODBias( int sampler, DWORD Value ); + FORCEINLINE void SetSamplerMaxMipLevel( int sampler, DWORD Value ); + FORCEINLINE void SetSamplerMaxAnisotropy( int sampler, DWORD Value ); + FORCEINLINE void SetSamplerSRGBTexture( int sampler, DWORD Value ); + FORCEINLINE void SetShadowFilter( int sampler, DWORD Value ); + + // render targets (FBO's) + CGLMFBO *NewFBO( void ); + void DelFBO( CGLMFBO *fbo ); + + // programs + CGLMProgram *NewProgram( EGLMProgramType type, char *progString, const char *pShaderName ); + void DelProgram( CGLMProgram *pProg ); + void NullProgram( void ); // de-ac all shader state + + FORCEINLINE void SetVertexProgram( CGLMProgram *pProg ); + FORCEINLINE void SetFragmentProgram( CGLMProgram *pProg ); + FORCEINLINE void SetProgram( EGLMProgramType nProgType, CGLMProgram *pProg ) { m_drawingProgram[nProgType] = pProg; m_bDirtyPrograms = true; } + + void SetDrawingLang( EGLMProgramLang lang, bool immediate=false ); // choose ARB or GLSL. immediate=false defers lang change to top of frame + + void LinkShaderPair( CGLMProgram *vp, CGLMProgram *fp ); // ensure this combo has been linked and is in the GLSL pair cache + void ClearShaderPairCache( void ); // call this to shoot down all the linked pairs + void QueryShaderPair( int index, GLMShaderPairInfo *infoOut ); // this lets you query the shader pair cache for saving its state + + // buffers + // Lock and Unlock reqs go directly to the buffer object + CGLMBuffer *NewBuffer( EGLMBufferType type, uint size, uint options ); + void DelBuffer( CGLMBuffer *buff ); + + FORCEINLINE void SetIndexBuffer( CGLMBuffer *buff ) { BindIndexBufferToCtx( buff ); } + + // FIXME: Remove this, it's no longer used + FORCEINLINE void SetVertexAttributes( GLMVertexSetup *setup ) + { + // we now just latch the vert setup and then execute on it at flushdrawstatestime if shaders are enabled. + if ( setup ) + { + m_drawVertexSetup = *setup; + } + else + { + memset( &m_drawVertexSetup, 0, sizeof( m_drawVertexSetup ) ); + } + } + + // note, no API is exposed for setting a single attribute source. + // come prepared with a complete block of attributes to use. + + // Queries + CGLMQuery *NewQuery( GLMQueryParams *params ); + void DelQuery( CGLMQuery *query ); + + // "slot" means a vec4-sized thing + // these write into .env parameter space + FORCEINLINE void SetProgramParametersF( EGLMProgramType type, uint baseSlot, float *slotData, uint slotCount ); + FORCEINLINE void SetProgramParametersB( EGLMProgramType type, uint baseSlot, int *slotData, uint boolCount ); // take "BOOL" aka int + FORCEINLINE void SetProgramParametersI( EGLMProgramType type, uint baseSlot, int *slotData, uint slotCount ); // take int4s + + // state sync + // If lazyUnbinding is true, unbound samplers will not actually be unbound to the GL device. + FORCEINLINE void FlushDrawStates( uint nStartIndex, uint nEndIndex, uint nBaseVertex ); // pushes all drawing state - samplers, tex, programs, etc. + void FlushDrawStatesNoShaders(); + + // drawing + FORCEINLINE void DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ); + void DrawRangeElementsNonInline( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ); + + void CheckNative( void ); + + // clearing + void Clear( bool color, unsigned long colorValue, bool depth, float depthValue, bool stencil, unsigned int stencilValue, GLScissorBox_t *rect = NULL ); + + // display + //void SetVSyncEnable( bool vsyncOn ); + //void SetFullScreen( bool fsOn, int screenIndex ); // will be latched for next BeginFrame + //void ActivateFullScreen( bool fsOn, int screenIndex ); // will be called by BeginFrame + bool SetDisplayParams( GLMDisplayParams *params ); // either the first time setup, or a change to new setup + + void Present( CGLMTex *tex ); // somewhat hardwired for the time being + + // Called when IDirect3DDevice9::Reset() is called. + void Reset(); + + // writers for the state block inputs + + FORCEINLINE void WriteAlphaTestEnable( GLAlphaTestEnable_t *src ) { m_AlphaTestEnable.Write( src ); } + FORCEINLINE void WriteAlphaTestFunc( GLAlphaTestFunc_t *src ) { m_AlphaTestFunc.Write( src ); } + FORCEINLINE void WriteAlphaToCoverageEnable( GLAlphaToCoverageEnable_t *src ) { m_AlphaToCoverageEnable.Write( src ); } + FORCEINLINE void WriteCullFaceEnable( GLCullFaceEnable_t *src ) { m_CullFaceEnable.Write( src ); } + FORCEINLINE void WriteCullFrontFace( GLCullFrontFace_t *src ) { m_CullFrontFace.Write( src ); } + FORCEINLINE void WritePolygonMode( GLPolygonMode_t *src ) { m_PolygonMode.Write( src ); } + FORCEINLINE void WriteDepthBias( GLDepthBias_t *src ) { m_DepthBias.Write( src ); } + FORCEINLINE void WriteClipPlaneEnable( GLClipPlaneEnable_t *src, int which ) { m_ClipPlaneEnable.WriteIndex( src, which ); } + FORCEINLINE void WriteClipPlaneEquation( GLClipPlaneEquation_t *src, int which ) { m_ClipPlaneEquation.WriteIndex( src, which ); } + FORCEINLINE void WriteScissorEnable( GLScissorEnable_t *src ) { m_ScissorEnable.Write( src ); } + FORCEINLINE void WriteScissorBox( GLScissorBox_t *src ) { m_ScissorBox.Write( src ); } + FORCEINLINE void WriteViewportBox( GLViewportBox_t *src ) { m_ViewportBox.Write( src ); } + FORCEINLINE void WriteViewportDepthRange( GLViewportDepthRange_t *src ) { m_ViewportDepthRange.Write( src ); } + FORCEINLINE void WriteColorMaskSingle( GLColorMaskSingle_t *src ) { m_ColorMaskSingle.Write( src ); } + FORCEINLINE void WriteColorMaskMultiple( GLColorMaskMultiple_t *src, int which ) { m_ColorMaskMultiple.WriteIndex( src, which ); } + FORCEINLINE void WriteBlendEnable( GLBlendEnable_t *src ) { m_BlendEnable.Write( src ); } + FORCEINLINE void WriteBlendFactor( GLBlendFactor_t *src ) { m_BlendFactor.Write( src ); } + FORCEINLINE void WriteBlendEquation( GLBlendEquation_t *src ) { m_BlendEquation.Write( src ); } + FORCEINLINE void WriteBlendColor( GLBlendColor_t *src ) { m_BlendColor.Write( src ); } + + FORCEINLINE void WriteBlendEnableSRGB( GLBlendEnableSRGB_t *src ) + { + if (m_caps.m_hasGammaWrites) // only if caps allow do we actually push it through to the extension + { + m_BlendEnableSRGB.Write( src ); + } + else + { + m_FakeBlendEnableSRGB = src->enable != 0; + } + // note however that we're still tracking what this mode should be, so FlushDrawStates can look at it and adjust the pixel shader + // if fake SRGB mode is in place (m_caps.m_hasGammaWrites is false) + } + + FORCEINLINE void WriteDepthTestEnable( GLDepthTestEnable_t *src ) { m_DepthTestEnable.Write( src ); } + FORCEINLINE void WriteDepthFunc( GLDepthFunc_t *src ) { m_DepthFunc.Write( src ); } + FORCEINLINE void WriteDepthMask( GLDepthMask_t *src ) { m_DepthMask.Write( src ); } + FORCEINLINE void WriteStencilTestEnable( GLStencilTestEnable_t *src ) { m_StencilTestEnable.Write( src ); } + FORCEINLINE void WriteStencilFunc( GLStencilFunc_t *src ) { m_StencilFunc.Write( src ); } + FORCEINLINE void WriteStencilOp( GLStencilOp_t *src, int which ) { m_StencilOp.WriteIndex( src, which ); } + FORCEINLINE void WriteStencilWriteMask( GLStencilWriteMask_t *src ) { m_StencilWriteMask.Write( src ); } + FORCEINLINE void WriteClearColor( GLClearColor_t *src ) { m_ClearColor.Write( src ); } + FORCEINLINE void WriteClearDepth( GLClearDepth_t *src ) { m_ClearDepth.Write( src ); } + FORCEINLINE void WriteClearStencil( GLClearStencil_t *src ) { m_ClearStencil.Write( src ); } + + // debug stuff + void BeginFrame( void ); + void EndFrame( void ); + + // new interactive debug stuff +#if GLMDEBUG + void DebugDump( GLMDebugHookInfo *info, uint options, uint vertDumpMode ); + void DebugHook( GLMDebugHookInfo *info ); + void DebugPresent( void ); + void DebugClear( void ); +#endif + + FORCEINLINE void SetMaxUsedVertexShaderConstantsHint( uint nMaxConstants ); + + FORCEINLINE DWORD GetCurrentOwnerThreadId() const { return m_nCurOwnerThreadId; } + + protected: + friend class GLMgr; // only GLMgr can make GLMContext objects + friend class GLMRendererInfo; // only GLMgr can make GLMContext objects + friend class CGLMTex; // tex needs to be able to do binds + friend class CGLMFBO; // fbo needs to be able to do binds + friend class CGLMProgram; + friend class CGLMShaderPair; + friend class CGLMShaderPairCache; + friend class CGLMBuffer; + friend class CGLMBufferSpanManager; + friend class GLMTester; // tester class needs access back into GLMContext + + friend struct IDirect3D9; + friend struct IDirect3DDevice9; + friend struct IDirect3DQuery9; + + // methods------------------------------------------ + + // old GLMContext( GLint displayMask, GLint rendererID, PseudoNSGLContextPtr nsglShareCtx ); + GLMContext( IDirect3DDevice9 *pDevice, GLMDisplayParams *params ); + ~GLMContext(); + + FORCEINLINE GLuint FindSamplerObject( const GLMTexSamplingParams &desiredParams ); + + FORCEINLINE void SetBufAndVertexAttribPointer( uint nIndex, GLuint nGLName, GLuint stride, GLuint datatype, GLboolean normalized, GLuint nCompCount, const void *pBuf, uint nRevision ) + { + VertexAttribs_t &curAttribs = m_boundVertexAttribs[nIndex]; + if ( nGLName != m_nBoundGLBuffer[kGLMVertexBuffer] ) + { + m_nBoundGLBuffer[kGLMVertexBuffer] = nGLName; + gGL->glBindBufferARB( GL_ARRAY_BUFFER_ARB, nGLName ); + } + else if ( ( curAttribs.m_pPtr == pBuf ) && + ( curAttribs.m_revision == nRevision ) && + ( curAttribs.m_stride == stride ) && + ( curAttribs.m_datatype == datatype ) && + ( curAttribs.m_normalized == normalized ) && + ( curAttribs.m_nCompCount == nCompCount ) ) + { + return; + } + + curAttribs.m_nCompCount = nCompCount; + curAttribs.m_datatype = datatype; + curAttribs.m_normalized = normalized; + curAttribs.m_stride = stride; + curAttribs.m_pPtr = pBuf; + curAttribs.m_revision = nRevision; + + gGL->glVertexAttribPointer( nIndex, nCompCount, datatype, normalized, stride, pBuf ); + } + + struct CurAttribs_t + { + uint m_nTotalBufferRevision; + IDirect3DVertexDeclaration9 *m_pVertDecl; + D3DStreamDesc m_streams[ D3D_MAX_STREAMS ]; + uint64 m_vtxAttribMap[2]; + }; + + CurAttribs_t m_CurAttribs; + + FORCEINLINE void ClearCurAttribs() + { + m_CurAttribs.m_nTotalBufferRevision = 0; + m_CurAttribs.m_pVertDecl = NULL; + memset( m_CurAttribs.m_streams, 0, sizeof( m_CurAttribs.m_streams ) ); + m_CurAttribs.m_vtxAttribMap[0] = 0xBBBBBBBBBBBBBBBBULL; + m_CurAttribs.m_vtxAttribMap[1] = 0xBBBBBBBBBBBBBBBBULL; + } + + FORCEINLINE void ReleasedShader() { NullProgram(); } + + // textures + FORCEINLINE void SelectTMU( int tmu ) + { + if ( tmu != m_activeTexture ) + { + gGL->glActiveTexture( GL_TEXTURE0 + tmu ); + m_activeTexture = tmu; + } + } + + void BindTexToTMU( CGLMTex *tex, int tmu ); + + // render targets / FBO's + void BindFBOToCtx( CGLMFBO *fbo, GLenum bindPoint = GL_FRAMEBUFFER_EXT ); // you can also choose GL_READ_FRAMEBUFFER_EXT / GL_DRAW_FRAMEBUFFER_EXT + + // buffers + FORCEINLINE void BindGLBufferToCtx( GLenum nGLBufType, GLuint nGLName, bool bForce = false ) + { + Assert( ( nGLBufType == GL_ARRAY_BUFFER_ARB ) || ( nGLBufType == GL_ELEMENT_ARRAY_BUFFER_ARB ) ); + + const uint nIndex = ( nGLBufType == GL_ARRAY_BUFFER_ARB ) ? kGLMVertexBuffer : kGLMIndexBuffer; + if ( ( bForce ) || ( m_nBoundGLBuffer[nIndex] != nGLName ) ) + { + m_nBoundGLBuffer[nIndex] = nGLName; + gGL->glBindBufferARB( nGLBufType, nGLName ); + } + } + + void BindBufferToCtx( EGLMBufferType type, CGLMBuffer *buff, bool force = false ); // does not twiddle any enables. + + FORCEINLINE void BindIndexBufferToCtx( CGLMBuffer *buff ); + FORCEINLINE void BindVertexBufferToCtx( CGLMBuffer *buff ); + + CPinnedMemoryBuffer *GetCurPinnedMemoryBuffer( ) { return &m_PinnedMemoryBuffers[m_nCurPinnedMemoryBuffer]; } + + // members------------------------------------------ + + // context + DWORD m_nCurOwnerThreadId; + uint m_nThreadOwnershipReleaseCounter; + + bool m_bUseSamplerObjects; + bool m_bPreferMapBufferRange; + + IDirect3DDevice9 *m_pDevice; + GLMRendererInfoFields m_caps; + + bool m_displayParamsValid; // is there a param block copied in yet + GLMDisplayParams m_displayParams; // last known display config, either via constructor, or by SetDisplayParams... + +#ifdef OSX + CGLPixelFormatAttribute m_pixelFormatAttribs[100]; // more than enough + PseudoNSGLContextPtr m_nsctx; + CGLContextObj m_ctx; +#elif defined( USE_SDL ) + int m_pixelFormatAttribs[100]; // more than enough + PseudoNSGLContextPtr m_nsctx; + void * m_ctx; +#endif + bool m_oneCtxEnable; // true if we use the window's context directly instead of making a second one shared against it + + bool m_bUseBoneUniformBuffers; // if true, we use two uniform buffers for vertex shader constants vs. one + + // texture form table + CGLMTexLayoutTable *m_texLayoutTable; + + // context state mirrors + + GLState m_AlphaTestEnable; + + GLState m_AlphaTestFunc; + + GLState m_CullFaceEnable; + GLState m_CullFrontFace; + GLState m_PolygonMode; + + GLState m_DepthBias; + + GLStateArray m_ClipPlaneEnable; + GLStateArray m_ClipPlaneEquation; // dxabstract puts them directly into param slot 253(0) and 254(1) + + GLState m_ScissorEnable; + GLState m_ScissorBox; + + GLState m_AlphaToCoverageEnable; + + GLState m_ViewportBox; + GLState m_ViewportDepthRange; + + GLState m_ColorMaskSingle; + GLStateArray m_ColorMaskMultiple; // need an official constant for the color buffers limit + + GLState m_BlendEnable; + GLState m_BlendFactor; + GLState m_BlendEquation; + GLState m_BlendColor; + GLState m_BlendEnableSRGB; // write to this one to transmit intent to write SRGB encoded pixels to drawing FB + bool m_FakeBlendEnableSRGB; // writes to above will be shunted here if fake SRGB is in effect. + + GLState m_DepthTestEnable; + GLState m_DepthFunc; + GLState m_DepthMask; + + GLState m_StencilTestEnable; // global stencil test enable + GLState m_StencilFunc; // holds front and back stencil funcs + GLStateArray m_StencilOp; // indexed: 0=front 1=back + GLState m_StencilWriteMask; + + GLState m_ClearColor; + GLState m_ClearDepth; + GLState m_ClearStencil; + + // texture bindings and sampler setup + int m_activeTexture; // mirror for glActiveTexture + GLMTexSampler m_samplers[GLM_SAMPLER_COUNT]; + + uint8 m_nDirtySamplerFlags[GLM_SAMPLER_COUNT]; // 0 if the sampler is dirty, 1 if not + uint32 m_nNumDirtySamplers; // # of unique dirty sampler indices in m_nDirtySamplers + uint8 m_nDirtySamplers[GLM_SAMPLER_COUNT + 1]; // dirty sampler indices + + void MarkAllSamplersDirty(); + + struct SamplerHashEntry + { + GLuint m_samplerObject; + GLMTexSamplingParams m_params; + }; + + enum + { + cSamplerObjectHashBits = 9, cSamplerObjectHashSize = 1 << cSamplerObjectHashBits + }; + SamplerHashEntry m_samplerObjectHash[cSamplerObjectHashSize]; + uint m_nSamplerObjectHashNumEntries; + + // texture lock tracking - CGLMTex objects share usage of this + CUtlVector< GLMTexLockDesc > m_texLocks; + + // render target binding - check before draw + // similar to tex sampler mechanism, we track "bound" from "chosen for drawing" separately, + // so binding for creation/setup need not disrupt any notion of what will be used at draw time + + CGLMFBO *m_boundDrawFBO; // FBO on GL_DRAW_FRAMEBUFFER bind point + CGLMFBO *m_boundReadFBO; // FBO on GL_READ_FRAMEBUFFER bind point + // ^ both are set if you bind to GL_FRAMEBUFFER_EXT + + CGLMFBO *m_drawingFBO; // what FBO should be bound at draw time (to both read/draw bp's). + + CGLMFBO *m_blitReadFBO; + CGLMFBO *m_blitDrawFBO; // scratch FBO's for framebuffer blit + + CGLMFBO *m_scratchFBO[ kGLMScratchFBOCount ]; // general purpose FBO's for internal use + + CUtlVector< CGLMFBO* > m_fboTable; // each live FBO goes in the table + + // program bindings + EGLMProgramLang m_drawingLangAtFrameStart; // selector for start of frame (spills into m_drawingLang) + EGLMProgramLang m_drawingLang; // selector for which language we desire to draw with on the next batch + CGLMProgram *m_drawingProgram[ kGLMNumProgramTypes ]; + bool m_bDirtyPrograms; + + GLMProgramParamsF m_programParamsF[ kGLMNumProgramTypes ]; + GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + GLMProgramParamsI m_programParamsI[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + EGLMParamWriteMode m_paramWriteMode; + + CGLMProgram *m_pNullFragmentProgram; // write opaque black. Activate when caller asks for null FP + + CGLMProgram *m_preloadTexVertexProgram; // programs to help preload textures (dummies) + CGLMProgram *m_preload2DTexFragmentProgram; + CGLMProgram *m_preload3DTexFragmentProgram; + CGLMProgram *m_preloadCubeTexFragmentProgram; + + CGLMShaderPairCache *m_pairCache; // GLSL only + CGLMShaderPair *m_pBoundPair; // GLSL only + + FORCEINLINE void NewLinkedProgram() { ClearCurAttribs(); } + + //uint m_boundPairRevision; // GLSL only + //GLhandleARB m_boundPairProgram; // GLSL only + + // buffer bindings + GLuint m_nBoundGLBuffer[kGLMNumBufferTypes]; + + struct VertexAttribs_t + { + GLuint m_nCompCount; + GLenum m_datatype; + GLboolean m_normalized; + GLuint m_stride; + const void *m_pPtr; + uint m_revision; + }; + + VertexAttribs_t m_boundVertexAttribs[ kGLMVertexAttributeIndexMax ]; // tracked per attrib for dupe-set-absorb + uint m_lastKnownVertexAttribMask; // tracked for dupe-enable-absorb + int m_nNumSetVertexAttributes; + + // FIXME: Remove this, it's no longer used + GLMVertexSetup m_drawVertexSetup; + + EGLMAttribWriteMode m_attribWriteMode; + + bool m_slowCheckEnable; // turn this on or no native checking is done ("-glmassertslow" or "-glmsspewslow") + bool m_slowAssertEnable; // turn this on to assert on a non-native batch "-glmassertslow" + bool m_slowSpewEnable; // turn this on to log non-native batches to stdout "-glmspewslow" + bool m_checkglErrorsAfterEveryBatch; // turn this on to check for GL errors after each batch (slow) ("-glcheckerrors") + + // debug font texture + CGLMTex *m_debugFontTex; // might be NULL unless you call GenDebugFontTex + CGLMBuffer *m_debugFontIndices; // up to 1024 indices (256 chars times 4) + CGLMBuffer *m_debugFontVertices; // up to 1024 verts + + // batch/frame debugging support + int m_debugFrameIndex; // init to -1. Increment at BeginFrame + + int m_nMaxUsedVertexProgramConstantsHint; + + uint32 m_dwRenderThreadId; + volatile bool m_bIsThreading; + + uint m_nCurFrame; + uint m_nBatchCounter; + + enum { cNumPinnedMemoryBuffers = 4 }; + CPinnedMemoryBuffer m_PinnedMemoryBuffers[cNumPinnedMemoryBuffers]; + uint m_nCurPinnedMemoryBuffer; + + void SaveColorMaskAndSetToDefault(); + void RestoreSavedColorMask(); + GLColorMaskSingle_t m_SavedColorMask; + +#if GLMDEBUG + // interactive (DebugHook) debug support + + // using these you can implement frame advance, batch single step, and batch rewind (let it run til next frame and hold on prev batch #) + int m_holdFrameBegin; // -1 if no hold req'd, otherwise # of frame to hold at (at beginframe time) + int m_holdFrameEnd; // -1 if no hold req'd, otherwise # of frame to hold at (at endframe time) + + int m_holdBatch,m_holdBatchFrame; // -1 if no hold, else # of batch&frame to hold at (both must be set) + // these can be expired/cleared to -1 if the frame passes without a hit + // may be desirable to re-pause in that event, as user was expecting a hold to occur + + bool m_debugDelayEnable; // allow sleep delay + uint m_debugDelay; // sleep time per hook call in microseconds (for usleep()) + + // pre-draw global toggles / options + bool m_autoClearColor,m_autoClearDepth,m_autoClearStencil; + float m_autoClearColorValues[4]; + + // debug knobs + int m_selKnobIndex; + float m_selKnobMinValue,m_selKnobMaxValue,m_selKnobIncrement; +#endif + +#if GL_BATCH_PERF_ANALYSIS + uint m_nTotalVSUniformCalls; + uint m_nTotalVSUniformBoneCalls; + uint m_nTotalVSUniformsSet; + uint m_nTotalVSUniformsBoneSet; + uint m_nTotalPSUniformCalls; + uint m_nTotalPSUniformsSet; + + CFlushDrawStatesStats m_FlushStats; +#endif +}; + +FORCEINLINE void GLMContext::DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ) +{ +#if GL_ENABLE_INDEX_VERIFICATION + DrawRangeElementsNonInline( mode, start, end, count, type, indices, baseVertex, pIndexBuf ); +#else + +#if GLMDEBUG + GLM_FUNC; +#else + //tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %d-%d count:%d mode:%d type:%d", __FUNCTION__, start, end, count, mode, type ); +#endif + + ++m_nBatchCounter; + + SetIndexBuffer( pIndexBuf ); + + void *indicesActual = (void*)indices; + + if ( pIndexBuf->m_bPseudo ) + { + // you have to pass actual address, not offset + indicesActual = (void*)( (int)indicesActual + (int)pIndexBuf->m_pPseudoBuf ); + } + +#if GLMDEBUG + bool hasVP = m_drawingProgram[ kGLMVertexProgram ] != NULL; + bool hasFP = m_drawingProgram[ kGLMFragmentProgram ] != NULL; + + // init debug hook information + GLMDebugHookInfo info; + memset( &info, 0, sizeof(info) ); + info.m_caller = eDrawElements; + + // relay parameters we're operating under + info.m_drawMode = mode; + info.m_drawStart = start; + info.m_drawEnd = end; + info.m_drawCount = count; + info.m_drawType = type; + info.m_drawIndices = indices; + + do + { + // obey global options re pre-draw clear + if ( m_autoClearColor || m_autoClearDepth || m_autoClearStencil ) + { + GLMPRINTF(("-- DrawRangeElements auto clear" )); + this->DebugClear(); + } + + // always sync with editable shader text prior to draw +#if GLMDEBUG + //FIXME disengage this path if context is in GLSL mode.. + // it will need fixes to get the shader pair re-linked etc if edits happen anyway. + + if (m_drawingProgram[ kGLMVertexProgram ]) + { + m_drawingProgram[ kGLMVertexProgram ]->SyncWithEditable(); + } + else + { + AssertOnce(!"drawing with no vertex program bound"); + } + + + if (m_drawingProgram[ kGLMFragmentProgram ]) + { + m_drawingProgram[ kGLMFragmentProgram ]->SyncWithEditable(); + } + else + { + AssertOnce(!"drawing with no fragment program bound"); + } +#endif + // do the drawing + if (hasVP && hasFP) + { + gGL->glDrawRangeElementsBaseVertex( mode, start, end, count, type, indicesActual, baseVertex ); + + if ( m_slowCheckEnable ) + { + CheckNative(); + } + } + this->DebugHook( &info ); + + } while ( info.m_loop ); +#else + Assert( m_drawingLang == kGLMGLSL ); + + if ( m_pBoundPair ) + { + gGL->glDrawRangeElementsBaseVertex( mode, start, end, count, type, indicesActual, baseVertex ); + +#if GLMDEBUG + if ( m_slowCheckEnable ) + { + CheckNative(); + } +#endif + } +#endif + +#endif // GL_ENABLE_INDEX_VERIFICATION +} + +FORCEINLINE void GLMContext::SetVertexProgram( CGLMProgram *pProg ) +{ + m_drawingProgram[kGLMVertexProgram] = pProg; + m_bDirtyPrograms = true; +} + +FORCEINLINE void GLMContext::SetFragmentProgram( CGLMProgram *pProg ) +{ + m_drawingProgram[kGLMFragmentProgram] = pProg ? pProg : m_pNullFragmentProgram; + m_bDirtyPrograms = true; +} + +// "slot" means a vec4-sized thing +// these write into .env parameter space +FORCEINLINE void GLMContext::SetProgramParametersF( EGLMProgramType type, uint baseSlot, float *slotData, uint slotCount ) +{ +#if GLMDEBUG + GLM_FUNC; +#endif + + Assert( baseSlot < kGLMProgramParamFloat4Limit ); + Assert( baseSlot+slotCount <= kGLMProgramParamFloat4Limit ); + +#if GLMDEBUG + GLMPRINTF(("-S-GLMContext::SetProgramParametersF %s slots %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + slotCount - 1 )); + for( uint i=0; i DXABSTRACT_VS_FIRST_BONE_SLOT ) + { + if ( baseSlot < DXABSTRACT_VS_FIRST_BONE_SLOT ) + { + // The register set crosses between the constant buffers - should only happen at startup during init. + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, (int)baseSlot ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, (int)MIN( baseSlot + slotCount, DXABSTRACT_VS_FIRST_BONE_SLOT ) ); + baseSlot = DXABSTRACT_VS_FIRST_BONE_SLOT; + } + + int nNumActualBones = ( baseSlot + slotCount ) - DXABSTRACT_VS_FIRST_BONE_SLOT; + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone, nNumActualBones ); + } + else + { + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, (int)baseSlot ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, (int)(baseSlot + slotCount) ); + } + } + else + { + m_programParamsF[type].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[type].m_dirtySlotHighWaterNonBone, (int)(baseSlot + slotCount) ); + m_programParamsF[type].m_firstDirtySlotNonBone = MIN( m_programParamsF[type].m_firstDirtySlotNonBone, (int)baseSlot ); + } +} + +FORCEINLINE void GLMContext::SetProgramParametersB( EGLMProgramType type, uint baseSlot, int *slotData, uint boolCount ) +{ +#if GLMDEBUG + GLM_FUNC; +#endif + + Assert( m_drawingLang == kGLMGLSL ); + Assert( type==kGLMVertexProgram ); + + Assert( baseSlot < kGLMProgramParamBoolLimit ); + Assert( baseSlot+boolCount <= kGLMProgramParamBoolLimit ); + +#if GLMDEBUG + GLMPRINTF(("-S-GLMContext::SetProgramParametersB %s bools %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + boolCount - 1 )); + for( uint i=0; i m_programParamsB[type].m_dirtySlotCount) + m_programParamsB[type].m_dirtySlotCount = baseSlot+boolCount; +} + +FORCEINLINE void GLMContext::SetProgramParametersI( EGLMProgramType type, uint baseSlot, int *slotData, uint slotCount ) // groups of 4 ints... +{ +#if GLMDEBUG + GLM_FUNC; +#endif + + Assert( m_drawingLang == kGLMGLSL ); + Assert( type==kGLMVertexProgram ); + + Assert( baseSlot < kGLMProgramParamInt4Limit ); + Assert( baseSlot+slotCount <= kGLMProgramParamInt4Limit ); + +#if GLMDEBUG + GLMPRINTF(("-S-GLMContext::SetProgramParametersI %s slots %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + slotCount - 1 )); + for( uint i=0; i m_programParamsI[type].m_dirtySlotCount) + { + m_programParamsI[type].m_dirtySlotCount = baseSlot + slotCount; + } +} + +FORCEINLINE void GLMContext::SetSamplerDirty( int sampler ) +{ + Assert( sampler < GLM_SAMPLER_COUNT ); + m_nDirtySamplers[m_nNumDirtySamplers] = sampler; + m_nNumDirtySamplers += m_nDirtySamplerFlags[sampler]; + m_nDirtySamplerFlags[sampler] = 0; +} + +FORCEINLINE void GLMContext::SetSamplerTex( int sampler, CGLMTex *tex ) +{ + Assert( sampler < GLM_SAMPLER_COUNT ); + m_samplers[sampler].m_pBoundTex = tex; + if ( tex ) + { + if ( !gGL->m_bHave_GL_EXT_direct_state_access ) + { + if ( sampler != m_activeTexture ) + { + gGL->glActiveTexture( GL_TEXTURE0 + sampler ); + m_activeTexture = sampler; + } + + gGL->glBindTexture( tex->m_texGLTarget, tex->m_texName ); + } + else + { + gGL->glBindMultiTextureEXT( GL_TEXTURE0 + sampler, tex->m_texGLTarget, tex->m_texName ); + } + } + + if ( !m_bUseSamplerObjects ) + { + SetSamplerDirty( sampler ); + } +} + +FORCEINLINE void GLMContext::SetSamplerMinFilter( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_minFilter = Value; +} + +FORCEINLINE void GLMContext::SetSamplerMagFilter( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_magFilter = Value; +} + +FORCEINLINE void GLMContext::SetSamplerMipFilter( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_mipFilter = Value; +} + +FORCEINLINE void GLMContext::SetSamplerAddressU( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + m_samplers[sampler].m_samp.m_packed.m_addressU = Value; +} + +FORCEINLINE void GLMContext::SetSamplerAddressV( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + m_samplers[sampler].m_samp.m_packed.m_addressV = Value; +} + +FORCEINLINE void GLMContext::SetSamplerAddressW( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + m_samplers[sampler].m_samp.m_packed.m_addressW = Value; +} + +FORCEINLINE void GLMContext::SetSamplerStates( int sampler, GLenum AddressU, GLenum AddressV, GLenum AddressW, GLenum minFilter, GLenum magFilter, GLenum mipFilter ) +{ + Assert( AddressU < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + Assert( AddressV < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + Assert( AddressW < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + Assert( minFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS ) ); + Assert( magFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS ) ); + Assert( mipFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS ) ); + + GLMTexSamplingParams ¶ms = m_samplers[sampler].m_samp; + params.m_packed.m_addressU = AddressU; + params.m_packed.m_addressV = AddressV; + params.m_packed.m_addressW = AddressW; + params.m_packed.m_minFilter = minFilter; + params.m_packed.m_magFilter = magFilter; + params.m_packed.m_mipFilter = mipFilter; +} + +FORCEINLINE void GLMContext::SetSamplerBorderColor( int sampler, DWORD Value ) +{ + m_samplers[sampler].m_samp.m_borderColor = Value; +} + +FORCEINLINE void GLMContext::SetSamplerMipMapLODBias( int sampler, DWORD Value ) +{ + // not currently supported +} + +FORCEINLINE void GLMContext::SetSamplerMaxMipLevel( int sampler, DWORD Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_minLOD = Value; +} + +FORCEINLINE void GLMContext::SetSamplerMaxAnisotropy( int sampler, DWORD Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_maxAniso = Value; +} + +FORCEINLINE void GLMContext::SetSamplerSRGBTexture( int sampler, DWORD Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_srgb = Value; +} + +FORCEINLINE void GLMContext::SetShadowFilter( int sampler, DWORD Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_compareMode = Value; +} + +FORCEINLINE void GLMContext::BindIndexBufferToCtx( CGLMBuffer *buff ) +{ + GLMPRINTF(( "--- GLMContext::BindIndexBufferToCtx buff %p, GL name %d", buff, (buff) ? buff->m_nHandle : -1 )); + + Assert( !buff || ( buff->m_buffGLTarget == GL_ELEMENT_ARRAY_BUFFER_ARB ) ); + + GLuint nGLName = buff ? buff->m_nHandle : 0; + + if ( m_nBoundGLBuffer[ kGLMIndexBuffer] == nGLName ) + return; + + m_nBoundGLBuffer[ kGLMIndexBuffer] = nGLName; + gGL->glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, nGLName ); +} + +FORCEINLINE void GLMContext::BindVertexBufferToCtx( CGLMBuffer *buff ) +{ + GLMPRINTF(( "--- GLMContext::BindVertexBufferToCtx buff %p, GL name %d", buff, (buff) ? buff->m_nHandle : -1 )); + + Assert( !buff || ( buff->m_buffGLTarget == GL_ARRAY_BUFFER_ARB ) ); + + GLuint nGLName = buff ? buff->m_nHandle : 0; + + if ( m_nBoundGLBuffer[ kGLMVertexBuffer] == nGLName ) + return; + + m_nBoundGLBuffer[ kGLMVertexBuffer] = nGLName; + gGL->glBindBufferARB( GL_ARRAY_BUFFER_ARB, nGLName ); +} + +FORCEINLINE void GLMContext::SetMaxUsedVertexShaderConstantsHint( uint nMaxConstants ) +{ + static bool bUseMaxVertexShadeConstantHints = !CommandLine()->CheckParm("-disablemaxvertexshaderconstanthints"); + if ( bUseMaxVertexShadeConstantHints ) + { + m_nMaxUsedVertexProgramConstantsHint = nMaxConstants; + } +} + +struct GLMTestParams +{ + GLMContext *m_ctx; + int *m_testList; // -1 termed + + bool m_glErrToDebugger; + bool m_glErrToConsole; + + bool m_intlErrToDebugger; + bool m_intlErrToConsole; + + int m_frameCount; // how many frames to test. +}; + +class CShowPixelsParams +{ +public: + GLuint m_srcTexName; + int m_width,m_height; + bool m_vsyncEnable; + bool m_fsEnable; // want receiving view to be full screen. for now, just target the main screen. extend later. + bool m_useBlit; // use FBO blit - sending context says it is available. + bool m_noBlit; // the back buffer has already been populated by the caller (perhaps via direct MSAA resolve from multisampled RT tex) + bool m_onlySyncView; // react to full/windowed state change only, do not present bits +}; + +#define kMaxCrawlFrames 100 +#define kMaxCrawlText (kMaxCrawlFrames * 256) +class CStackCrawlParams +{ + public: + uint m_frameLimit; // input: max frames to retrieve + uint m_frameCount; // output: frames found + void *m_crawl[kMaxCrawlFrames]; // call site addresses + char *m_crawlNames[kMaxCrawlFrames]; // pointers into text following, one per decoded name + char m_crawlText[kMaxCrawlText]; +}; + +#endif // GLMGR_H diff --git a/mp/src/public/togl/linuxwin/glmgrbasics.h b/mp/src/public/togl/linuxwin/glmgrbasics.h new file mode 100644 index 00000000..1897ebca --- /dev/null +++ b/mp/src/public/togl/linuxwin/glmgrbasics.h @@ -0,0 +1,308 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgrbasics.h +// types, common headers, forward declarations, utilities +// +//=============================================================================== + +#ifndef GLMBASICS_H +#define GLMBASICS_H + +#pragma once + +#ifdef OSX + #include + #include + #include + #include + #include + #include + #include + #include +#elif defined(DX_TO_GL_ABSTRACTION) + #include + #include +#else + #error +#endif + +#include "tier0/platform.h" + +#include "bitmap/imageformat.h" +#include "bitvec.h" +#include "tier1/checksum_md5.h" +#include "tier1/utlvector.h" +#include "tier1/convar.h" + +#include + +#include "dxabstract_types.h" + +struct GLMRect; +typedef void *PseudoGLContextPtr; + +// types + + // 3-d integer box (used for texture lock/unlock etc) +struct GLMRegion +{ + int xmin,xmax; + int ymin,ymax; + int zmin,zmax; +}; + +struct GLMRect // follows GL convention - if coming from the D3D rect you will need to fiddle the Y's +{ + int xmin; // left + int ymin; // bottom + int xmax; // right + int ymax; // top +}; + +// macros + +//#define GLMassert(x) assert(x) + +// forward decls +class GLMgr; // singleton +class GLMContext; // GL context +class CGLMContextTester; // testing class +class CGLMTex; +class CGLMFBO; +class CGLMProgram; +class CGLMBuffer; + + +// utilities + +typedef enum +{ + // D3D codes + eD3D_DEVTYPE, + eD3D_FORMAT, + eD3D_RTYPE, + eD3D_USAGE, + eD3D_RSTATE, // render state + eD3D_SIO, // D3D shader bytecode + eD3D_VTXDECLUSAGE, + + // CGL codes + eCGL_RENDID, + + // OpenGL error codes + eGL_ERROR, + + // OpenGL enums + eGL_ENUM, + eGL_RENDERER + +} GLMThing_t; + +// these will look at the string to guess its flavor: <, >, ---, -M-, -S- +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const +#else + DLL_IMPORT const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const +#endif + +const char* GLMDecodeMask( GLMThing_t type, unsigned long value ); // decode a bitmask + +FORCEINLINE void GLMStop( void ) { DXABSTRACT_BREAK_ON_ERROR(); } + +void GLMEnableTrace( bool on ); + +//=============================================================================== +// output functions + +// expose these in release now +// Mimic PIX events so we can decorate debug spew +DLL_EXPORT void GLMBeginPIXEvent( const char *str ); +DLL_EXPORT void GLMEndPIXEvent( void ); + +class CScopedGLMPIXEvent +{ + CScopedGLMPIXEvent( const CScopedGLMPIXEvent & ); + CScopedGLMPIXEvent& operator= ( const CScopedGLMPIXEvent & ); +public: + inline CScopedGLMPIXEvent( const char *pName ) { GLMBeginPIXEvent( pName ); } + inline ~CScopedGLMPIXEvent() { GLMEndPIXEvent( ); } +}; + +#if GLMDEBUG + + +//=============================================================================== +// classes + +// helper class making function tracking easier to wire up + +class GLMFuncLogger +{ + public: + + // simple function log + GLMFuncLogger( const char *funcName ) + { + m_funcName = funcName; + m_earlyOut = false; + + GLMPrintf( ">%s", m_funcName ); + }; + + // more advanced version lets you pass args (i.e. called parameters or anything else of interest) + // no macro for this one, since no easy way to pass through the args as well as the funcname + GLMFuncLogger( const char *funcName, char *fmt, ... ) + { + m_funcName = funcName; + m_earlyOut = false; + + // this acts like GLMPrintf here + // all the indent policy is down in GLMPrintfVA + // which means we need to inject a ">" at the front of the format string to make this work... sigh. + + char modifiedFmt[2000]; + modifiedFmt[0] = '>'; + strcpy( modifiedFmt+1, fmt ); + + va_list vargs; + va_start(vargs, fmt); + GLMPrintfVA( modifiedFmt, vargs ); + va_end( vargs ); + } + + ~GLMFuncLogger( ) + { + if (m_earlyOut) + { + GLMPrintf( "<%s (early out)", m_funcName ); + } + else + { + GLMPrintf( "<%s", m_funcName ); + } + }; + + void EarlyOut( void ) + { + m_earlyOut = true; + }; + + const char *m_funcName; // set at construction time + bool m_earlyOut; +}; + +// handy macro to go with the function tracking class +#define GLM_FUNC GLMFuncLogger _logger_ ( __FUNCTION__ ) +#else +#define GLM_FUNC tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s", __FUNCTION__ ) +#endif + + +// class to keep an in-memory mirror of a file which may be getting edited during run +class CGLMFileMirror +{ +public: + CGLMFileMirror( char *fullpath ); // just associates mirror with file. if file exists it will be read. + //if non existent it will be created with size zero + ~CGLMFileMirror( ); + + bool HasData( void ); // see if data avail + void GetData( char **dataPtr, uint *dataSizePtr ); // read it out + void SetData( char *data, uint dataSize ); // put data in (and write it to disk) + bool PollForChanges( void ); // check disk copy. If different, read it back in and return true. + + void UpdateStatInfo( void ); // make sure stat info is current for our file + void ReadFile( void ); + void WriteFile( void ); + + void OpenInEditor( bool foreground=false ); // pass TRUE if you would like the editor to pop to foreground + + /// how about a "wait for change" method.. + + char *m_path; // fullpath to file + bool m_exists; + struct stat m_stat; // stat results for the file (last time checked) + + char *m_data; // content of file + uint m_size; // length of content + +}; + +// class based on the file mirror, that makes it easy to edit them outside the app. + +// it receives an initial block of text from the engine, and hashes it. ("orig") +// it munges it by duplicating all the text after the "!!" line, and appending it in commented form. ("munged") +// a mirror file is activated, using a filename based on the hash from the orig text. +// if there is already content on disk matching that filename, use that content *unless* the 'blitz' parameter is set. +// (i.e. engine is instructing this subsystem to wipe out any old/modified variants of the text) + + +class CGLMEditableTextItem +{ +public: + CGLMEditableTextItem( char *text, uint size, bool forceOverwrite, char *prefix, char *suffix = NULL ); // create a text blob from text source, optional filename suffix + ~CGLMEditableTextItem( ); + + bool HasData( void ); + bool PollForChanges( void ); // return true if stale i.e. you need to get a new edition + void GetCurrentText( char **textOut, uint *sizeOut ); // query for read access to the active blob (could be the original, could be external edited copy) + void OpenInEditor( bool foreground=false ); // call user attention to this text + + // internal methods + void GenHashOfOrigText( void ); + void GenBaseNameAndFullPath( char *prefix, char *suffix ); + void GenMungedText( bool fromMirror ); + + // members + // orig + uint m_origSize; + char *m_origText; // what was submitted + unsigned char m_origDigest[MD5_DIGEST_LENGTH]; // digest of what was submitted + + // munged + uint m_mungedSize; + char *m_mungedText; // re-processed edition, initial content submission to the file mirror + + // mirror + char *m_mirrorBaseName; // generated from the hash of the orig text, plus the label / prefix + char *m_mirrorFullPath; // base name + CGLMFileMirror *m_mirror; // file mirror itself. holds "official" copy for GetCurrentText to return. +}; + + +// debug font +extern unsigned char g_glmDebugFontMap[16384]; + +// class for cracking multi-part text blobs +// sections are demarcated by beginning-of-line markers submitted in a table by the caller + +struct GLMTextSection +{ + int m_markerIndex; // based on table of markers passed in to constructor + uint m_textOffset; // where is the text - offset + int m_textLength; // how big is the section +}; + +class CGLMTextSectioner +{ +public: + CGLMTextSectioner( char *text, int textSize, const char **markers ); // constructor finds all the sections + ~CGLMTextSectioner( ); + + int Count( void ); // how many sections found + void GetSection( int index, uint *offsetOut, uint *lengthOut, int *markerIndexOut ); + // find section, size, what marker + // note that more than one section can be marked similarly. + // so policy isn't made here, you walk the sections and decide what to do if there are dupes. + + //members + + //section table + CUtlVector< GLMTextSection > m_sectionTable; +}; + +void GLMGPUTimestampManagerInit(); +void GLMGPUTimestampManagerDeinit(); +void GLMGPUTimestampManagerTick(); + +#endif // GLMBASICS_H diff --git a/mp/src/public/togl/linuxwin/glmgrext.h b/mp/src/public/togl/linuxwin/glmgrext.h new file mode 100644 index 00000000..810d4055 --- /dev/null +++ b/mp/src/public/togl/linuxwin/glmgrext.h @@ -0,0 +1,93 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgrext.h +// helper file for extension testing and runtime importing of entry points +// +//=============================================================================== + +#pragma once + +#ifdef OSX +#include +#include +#elif defined(DX_TO_GL_ABSTRACTION) +#include +#include +#else +#error +#endif + +#ifndef GL_EXT_framebuffer_sRGB + #define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 + #define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif + +#ifndef ARB_texture_rg + #define GL_COMPRESSED_RED 0x8225 + #define GL_COMPRESSED_RG 0x8226 + #define GL_RG 0x8227 + #define GL_RG_INTEGER 0x8228 + #define GL_R8 0x8229 + #define GL_R16 0x822A + #define GL_RG8 0x822B + #define GL_RG16 0x822C + #define GL_R16F 0x822D + #define GL_R32F 0x822E + #define GL_RG16F 0x822F + #define GL_RG32F 0x8230 + #define GL_R8I 0x8231 + #define GL_R8UI 0x8232 + #define GL_R16I 0x8233 + #define GL_R16UI 0x8234 + #define GL_R32I 0x8235 + #define GL_R32UI 0x8236 + #define GL_RG8I 0x8237 + #define GL_RG8UI 0x8238 + #define GL_RG16I 0x8239 + #define GL_RG16UI 0x823A + #define GL_RG32I 0x823B + #define GL_RG32UI 0x823C +#endif + +#ifndef GL_EXT_bindable_uniform + #define GL_UNIFORM_BUFFER_EXT 0x8DEE +#endif + +// unpublished extension enums (thus the "X") + +// from EXT_framebuffer_multisample_blit_scaled.. +#define XGL_SCALED_RESOLVE_FASTEST_EXT 0x90BA +#define XGL_SCALED_RESOLVE_NICEST_EXT 0x90BB + +#ifndef GL_TEXTURE_MINIMIZE_STORAGE_APPLE +#define GL_TEXTURE_MINIMIZE_STORAGE_APPLE 0x85B6 +#endif + +#ifndef GL_ALL_COMPLETED_NV +#define GL_ALL_COMPLETED_NV 0x84F2 +#endif + +#ifndef GL_MAP_READ_BIT +#define GL_MAP_READ_BIT 0x0001 +#endif + +#ifndef GL_MAP_WRITE_BIT +#define GL_MAP_WRITE_BIT 0x0002 +#endif + +#ifndef GL_MAP_INVALIDATE_RANGE_BIT +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#endif + +#ifndef GL_MAP_INVALIDATE_BUFFER_BIT +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#endif + +#ifndef GL_MAP_FLUSH_EXPLICIT_BIT +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#endif + +#ifndef GL_MAP_UNSYNCHRONIZED_BIT +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#endif + diff --git a/mp/src/public/togl/osx/cglmbuffer.h b/mp/src/public/togl/osx/cglmbuffer.h new file mode 100644 index 00000000..0e40f474 --- /dev/null +++ b/mp/src/public/togl/osx/cglmbuffer.h @@ -0,0 +1,99 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmprogram.h +// GLMgr buffers (index / vertex) +// ... maybe add PBO later as well +//=============================================================================== + +#ifndef CGLMBUFFER_H +#define CGLMBUFFER_H + +#pragma once + +// ext links + +// http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt + +//=============================================================================== + +// tokens not in the SDK headers + +//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT +// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +//#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; + +enum EGLMBufferType +{ + kGLMVertexBuffer, + kGLMIndexBuffer, + kGLMUniformBuffer, // for bindable uniform + kGLMPixelBuffer, // for PBO + + kGLMNumBufferTypes +}; + + // pass this in "options" to constructor to make a dynamic buffer +#define GLMBufferOptionDynamic 0x00000001 + +struct GLMBuffLockParams +{ + uint m_offset; + uint m_size; + bool m_nonblocking; + bool m_discard; +}; + +class CGLMBuffer +{ + +public: + void Lock( GLMBuffLockParams *params, char **addressOut ); + void Unlock( void ); + +//protected: + friend class GLMContext; // only GLMContext can make CGLMBuffer objects + friend class GLMTester; + friend class IDirect3D9; + friend class IDirect3DDevice9; + + CGLMBuffer ( GLMContext *ctx, EGLMBufferType type, uint size, uint options ); + ~CGLMBuffer ( ); + + void SetModes ( bool asyncMap, bool explicitFlush, bool force = false ); + void FlushRange ( uint offset, uint size ); + + GLMContext *m_ctx; // link back to parent context + EGLMBufferType m_type; + uint m_size; + GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB + GLuint m_name; // name of this program in the context + uint m_revision; // bump anytime the size changes or buffer is orphaned + bool m_enableAsyncMap; // mirror of the buffer state + bool m_enableExplicitFlush; // mirror of the buffer state + + bool m_bound; // true if bound to context + bool m_mapped; // is it currently mapped + uint m_dirtyMinOffset; // when equal, range is empty + uint m_dirtyMaxOffset; + + float *m_lastMappedAddress; + + // --------------------- pseudo-VBO support below here (explicitly for dynamic index buffers) + bool m_pseudo; // true if the m_name is 0, and the backing is plain RAM + + // in pseudo mode, there is just one RAM buffer that acts as the backing. + // expectation is that this mode would only be used for dynamic indices. + // since indices have to be consumed (copied to command stream) prior to return from a drawing call, + // there's no need to do any fencing or multibuffering. orphaning in particular becomes a no-op. + + char *m_pseudoBuf; // storage for pseudo buffer +}; + + +#endif \ No newline at end of file diff --git a/mp/src/public/togl/osx/cglmfbo.h b/mp/src/public/togl/osx/cglmfbo.h new file mode 100644 index 00000000..ab889af2 --- /dev/null +++ b/mp/src/public/togl/osx/cglmfbo.h @@ -0,0 +1,91 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmfbo.h +// GLMgr FBO's (render targets) +// +//=============================================================================== + +#ifndef CGLMFBO_H +#define CGLMFBO_H + +#pragma once + +#include "togl/rendermechanism.h" + +// good FBO references / recaps +// http://www.songho.ca/opengl/gl_fbo.html +// http://www.gamedev.net/reference/articles/article2331.asp + +// ext links + +// http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt +// http://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt + +//=============================================================================== + +// tokens not in the SDK headers + +#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT + #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; + +// implicitly 16 maximum color attachments possible +enum EGLMFBOAttachment { + kAttColor0, kAttColor1, kAttColor2, kAttColor3, + kAttColor4, kAttColor5, kAttColor6, kAttColor7, + kAttColor8, kAttColor9, kAttColor10, kAttColor11, + kAttColor12, kAttColor13, kAttColor14, kAttColor15, + kAttDepth, kAttStencil, kAttDepthStencil, + kAttCount +}; + +struct GLMFBOTexAttachParams +{ + CGLMTex *m_tex; + int m_face; // keep zero if not cube map + int m_mip; // keep zero if notmip mapped + int m_zslice; // keep zero if not a 3D tex +}; + +class CGLMFBO +{ + +public: + +protected: + friend class GLMContext; // only GLMContext can make CGLMFBO objects + friend class GLMTester; + friend class CGLMTex; + + friend class IDirect3D9; + friend class IDirect3DDevice9; + + CGLMFBO( GLMContext *ctx ); + ~CGLMFBO( ); + + void TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); + void TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); + // you can also pass GL_READ_FRAMEBUFFER_EXT or GL_DRAW_FRAMEBUFFER_EXT to selectively bind the receiving FBO to one or the other. + + void TexScrub( CGLMTex *tex ); + // search and destroy any attachment for the named texture + + bool IsReady( void ); // aka FBO completeness check - ready to draw + + GLMContext *m_ctx; // link back to parent context + + GLuint m_name; // name of this FBO in the context + + GLMFBOTexAttachParams m_attach[ kAttCount ]; // indexed by EGLMFBOAttachment + + int m_sizeX,m_sizeY; +}; + + +#endif diff --git a/mp/src/public/togl/osx/cglmprogram.h b/mp/src/public/togl/osx/cglmprogram.h new file mode 100644 index 00000000..8d702c42 --- /dev/null +++ b/mp/src/public/togl/osx/cglmprogram.h @@ -0,0 +1,291 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmprogram.h +// GLMgr programs (ARBVP/ARBfp) +// +//=============================================================================== + +#ifndef CGLMPROGRAM_H +#define CGLMPROGRAM_H + +#include + +#pragma once + +// good ARB program references +// http://petewarden.com/notes/archives/2005/05/fragment_progra_2.html +// http://petewarden.com/notes/archives/2005/06/fragment_progra_3.html + +// ext links + +// http://www.opengl.org/registry/specs/ARB/vertex_program.txt +// http://www.opengl.org/registry/specs/ARB/fragment_program.txt +// http://www.opengl.org/registry/specs/EXT/gpu_program_parameters.txt + + +//=============================================================================== + +// tokens not in the SDK headers + +//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT +// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +//#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; +class CGLMShaderPair; +class CGLMShaderPairCache; + +// CGLMProgram can contain two flavors of the same program, one in assembler, one in GLSL. +// these flavors are pretty different in terms of the API's that are used to activate them - +// for example, assembler programs can just get bound to the context, whereas GLSL programs +// have to be linked. To some extent we try to hide that detail inside GLM. + +// for now, make CGLMProgram a container, it does not set policy or hold a preference as to which +// flavor you want to use. GLMContext has to handle that. + +enum EGLMProgramType +{ + kGLMVertexProgram, + kGLMFragmentProgram, + + kGLMNumProgramTypes +}; + +enum EGLMProgramLang +{ + kGLMARB, + kGLMGLSL, + + kGLMNumProgramLangs +}; + +struct GLMShaderDesc +{ + union + { + GLuint arb; // ARB program object name + GLhandleARB glsl; // GLSL shader object handle (void*) + } m_object; + + // these can change if shader text is edited + bool m_textPresent; // is this flavor(lang) of text present in the buffer? + int m_textOffset; // where is it + int m_textLength; // how big + + bool m_compiled; // has this text been through a compile attempt + bool m_valid; // and if so, was the compile successful + + int m_slowMark; // has it been flagged during a non native draw batch before. increment every time it's slow. + + int m_highWater; // vount of vec4's in the major uniform array ("vc" on vs, "pc" on ps) + // written by dxabstract.... gross! +}; + +GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target +GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target + +class CGLMProgram +{ +public: + friend class CGLMShaderPairCache; + friend class CGLMShaderPair; + friend class GLMContext; // only GLMContext can make CGLMProgram objects + friend class GLMTester; + friend class IDirect3D9; + friend class IDirect3DDevice9; + + //=============================== + + // constructor is very light, it just makes one empty program object per flavor. + CGLMProgram( GLMContext *ctx, EGLMProgramType type ); + ~CGLMProgram( ); + + void SetProgramText ( char *text ); // import text to GLM object - invalidate any prev compiled program + + bool CompileActiveSources ( void ); // compile only the flavors that were provided. + bool Compile ( EGLMProgramLang lang ); + bool CheckValidity ( EGLMProgramLang lang ); + + void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that + + void GetLabelIndexCombo ( char *labelOut, int labelOutMaxChars, int *indexOut, int *comboOut ); + void GetComboIndexNameString ( char *stringOut, int stringOutMaxChars ); // mmmmmmmm-nnnnnnnn-filename + +#if GLMDEBUG + bool PollForChanges( void ); // check mirror for changes. + void ReloadStringFromEditable( void ); // populate m_string from editable item (react to change) + bool SyncWithEditable( void ); +#endif + + //=============================== + + // common stuff + + GLMContext *m_ctx; // link back to parent context + + EGLMProgramType m_type; // vertex or pixel + + uint m_serial; // serial number for hashing + + char *m_text; // copy of text passed into constructor. Can change if editable shaders is enabled. + // note - it can contain multiple flavors, so use CGLMTextSectioner to scan it and locate them +#if GLMDEBUG + CGLMEditableTextItem *m_editable; // editable text item for debugging +#endif + + GLMShaderDesc m_descs[ kGLMNumProgramLangs ]; + + uint m_samplerMask; // (1< m_layoutMap; +}; + +//=============================================================================== + +// a sampler specifies desired state for drawing on a given sampler index +// this is the combination of a texture choice and a set of sampler parameters +// see http://msdn.microsoft.com/en-us/library/bb172602(VS.85).aspx + + +struct GLMTexSamplingParams +{ + GLenum m_addressModes[3]; // S, T, R + GLfloat m_borderColor[4]; // R,G,B,A + + GLenum m_magFilter; + GLenum m_minFilter; + + GLfloat m_mipmapBias; + GLint m_minMipLevel; + GLint m_maxMipLevel; + GLint m_maxAniso; + GLenum m_compareMode; // only used for depth and stencil type textures + bool m_srgb; // srgb texture read... +}; + +struct GLMTexLockParams +{ + // input params which identify the slice of interest + CGLMTex *m_tex; + int m_face; + int m_mip; + + // identifies the region of the slice + GLMRegion m_region; + + // tells GLM to force re-read of the texels back from GL + // i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale" + bool m_readback; +}; + +struct GLMTexLockDesc +{ + GLMTexLockParams m_req; // form of the lock request + + bool m_active; // set true at lock time. cleared at unlock time. + + int m_sliceIndex; // which slice in the layout + int m_sliceBaseOffset; // where is that in the texture data + int m_sliceRegionOffset; // offset to the start (lowest address corner) of the region requested +}; + +//=============================================================================== + +#define GLM_SAMPLER_COUNT 16 + +typedef CBitVec CTexBindMask; + +enum EGLMTexSliceFlag +{ + kSliceValid = 0x01, // slice has been teximage'd in whole at least once - set to 0 initially + kSliceStorageValid = 0x02, // if backing store is available, this slice's data is a valid copy - set to 0 initially + kSliceLocked = 0x04, // are one or more locks outstanding on this slice + kSliceFullyDirty = 0x08, // does the slice need to be fully downloaded at unlock time (disregard dirty rects) +}; + +class CGLMTex +{ + +public: + + void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut ); + void Unlock( GLMTexLockParams *params ); + +protected: + friend class GLMContext; // only GLMContext can make CGLMTex objects + friend class GLMTester; + friend class CGLMFBO; + + friend class IDirect3DDevice9; + friend class IDirect3DBaseTexture9; + friend class IDirect3DTexture9; + friend class IDirect3DSurface9; + friend class IDirect3DCubeTexture9; + friend class IDirect3DVolumeTexture9; + + CGLMTex( GLMContext *ctx, GLMTexLayout *layout, GLMTexSamplingParams *sampling, char *debugLabel = NULL ); + ~CGLMTex( ); + + int CalcSliceIndex( int face, int mip ); + void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut ); + + void ApplySamplingParams( GLMTexSamplingParams *params, bool noCheck=FALSE ); + + void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true ); + void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false ); + // last param lets us send NULL data ptr (only legal with uncompressed formats, beware) + // this helps out ResetSRGB. + + void ResetSRGB( bool srgb, bool noDataWrite ); + // re-specify texture format to match desired sRGB form + // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's + + GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout) + int m_minActiveMip;//index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. + int m_maxActiveMip;//index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. + + GLMTexSamplingParams m_sampling; // mirror of sampling params currently embodied in the texture + // (consult this at draw time, in order to know if changes need to be made) + + GLMContext *m_ctx; // link back to parent context + + GLuint m_texName; // name of this texture in the context + bool m_texClientStorage; // was CS selecetd for texture + bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet + + GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero) + bool m_rboDirty; // has RBO been drawn on - i.e. needs to be blitted back to texture if texture is going to be sampled from + + CTexBindMask m_bindPoints; // true for each place in the parent ctx where currently + // bound (indexed via EGLMTexCtxBindingIndex) + + int m_rtAttachCount; // how many RT's have this texture attached somewhere + + char *m_backing; // backing storage if available + + int m_lockCount; // lock reqs are stored in the GLMContext for tracking + + CUtlVector m_sliceFlags; + + char *m_debugLabel; // strdup() of debugLabel passed in, or NULL +}; + + +#endif diff --git a/mp/src/public/togl/osx/dxabstract.h b/mp/src/public/togl/osx/dxabstract.h new file mode 100644 index 00000000..682676c7 --- /dev/null +++ b/mp/src/public/togl/osx/dxabstract.h @@ -0,0 +1,804 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// +// +//================================================================================================== + +#ifndef DXABSTRACT_H +#define DXABSTRACT_H +#ifdef _WIN32 +#pragma once +#endif + +#include "togl/rendermechanism.h" + +#include "materialsystem/ishader.h" + +// Uncomment this on Windows if you want to compile the Windows GL version. +// #undef USE_ACTUAL_DX + +#ifdef USE_ACTUAL_DX + +#ifndef WIN32 +#error sorry man +#endif +#ifdef _X360 +#include "d3d9.h" +#include "d3dx9.h" +#else +#include +#include "../../dx9sdk/include/d3d9.h" +#include "../../dx9sdk/include/d3dx9.h" +#endif +typedef HWND VD3DHWND; + +#else + +#ifdef WIN32 +#error Gl on win32? +#endif + +#include "tier0/platform.h" + +#ifndef DX_TO_GL_ABSTRACTION +#define DX_TO_GL_ABSTRACTION +#endif + +#include "bitmap/imageformat.h" +#include "togl/rendermechanism.h" + +#ifdef OSX +extern "C" void Debugger(void); +#endif + +// turn this on to get refcount logging from IUnknown +#define IUNKNOWN_ALLOC_SPEW 0 +#define IUNKNOWN_ALLOC_SPEW_MARK_ALL 0 + + +// ------------------------------------------------------------------------------------------------------------------------------ // +// DEFINES +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef void* VD3DHWND; +typedef void* VD3DHANDLE; + + +TOGL_INTERFACE void toglGetClientRect( VD3DHWND hWnd, RECT *destRect ); + +struct TOGL_CLASS IUnknown +{ + int m_refcount[2]; + bool m_mark; + + IUnknown( void ) + { + m_refcount[0] = 1; + m_refcount[1] = 0; + m_mark = (IUNKNOWN_ALLOC_SPEW_MARK_ALL != 0); // either all are marked, or only the ones that have SetMark(true) called on them + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUnew (%08x) refc -> (%d,%d) ",this,m_refcount[0],m_refcount[1])); + } + #endif + }; + + virtual ~IUnknown( void ) + { + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUdel (%08x) ",this )); + } + #endif + }; + + void AddRef( int which=0, char *comment = NULL ) + { + Assert( which >= 0 ); + Assert( which < 2 ); + m_refcount[which]++; + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUAddRef (%08x,%d) refc -> (%d,%d) [%s]",this,which,m_refcount[0],m_refcount[1],comment?comment:"...")) ; + if (!comment) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + } + #endif + }; + + ULONG __stdcall Release( int which=0, char *comment = NULL ) + { + Assert( which >= 0 ); + Assert( which < 2 ); + + //int oldrefcs[2] = { m_refcount[0], m_refcount[1] }; + bool deleting = false; + + m_refcount[which]--; + if ( (!m_refcount[0]) && (!m_refcount[1]) ) + { + deleting = true; + } + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IURelease (%08x,%d) refc -> (%d,%d) [%s] %s",this,which,m_refcount[0],m_refcount[1],comment?comment:"...",deleting?"->DELETING":"")); + if (!comment) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + } + #endif + + if (deleting) + { + if (m_mark) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + delete this; + return 0; + } + else + { + return m_refcount[0]; + } + }; + + void SetMark( bool markValue, char *comment=NULL ) + { + #if IUNKNOWN_ALLOC_SPEW + if (!m_mark && markValue) // leading edge detect + { + // print the same thing that the constructor would have printed if it had been marked from the beginning + // i.e. it's anticipated that callers asking for marking will do so right at create time + GLMPRINTF(("-A- IUSetMark (%08x) refc -> (%d,%d) (%s) ",this,m_refcount[0],m_refcount[1],comment?comment:"...")); + } + #endif + + m_mark = markValue; + } +}; + + +// ------------------------------------------------------------------------------------------------------------------------------ // +// INTERFACES +// ------------------------------------------------------------------------------------------------------------------------------ // + +struct TOGL_CLASS IDirect3DResource9 : public IUnknown +{ + IDirect3DDevice9 *m_device; // parent device + D3DRESOURCETYPE m_restype; + + DWORD SetPriority(DWORD PriorityNew); +}; + +struct TOGL_CLASS IDirect3DBaseTexture9 : public IDirect3DResource9 // "A Texture.." +{ + D3DSURFACE_DESC m_descZero; // desc of top level. + CGLMTex *m_tex; // a CGLMTex can represent all forms of tex + int m_srgbFlipCount; + + virtual ~IDirect3DBaseTexture9(); + D3DRESOURCETYPE GetType(); + DWORD GetLevelCount(); + HRESULT GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DTexture9 : public IDirect3DBaseTexture9 // "Texture 2D" +{ + IDirect3DSurface9 *m_surfZero; // surf of top level. + + virtual ~IDirect3DTexture9(); + + HRESULT LockRect(UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); + HRESULT UnlockRect(UINT Level); + HRESULT GetSurfaceLevel(UINT Level,IDirect3DSurface9** ppSurfaceLevel); +}; + +struct TOGL_CLASS IDirect3DCubeTexture9 : public IDirect3DBaseTexture9 // "Texture Cube Map" +{ + IDirect3DSurface9 *m_surfZero[6]; // surfs of top level. + + virtual ~IDirect3DCubeTexture9(); + + HRESULT GetCubeMapSurface(D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface); + HRESULT GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DVolumeTexture9 : public IDirect3DBaseTexture9 // "Texture 3D" +{ + IDirect3DSurface9 *m_surfZero; // surf of top level. + D3DVOLUME_DESC m_volDescZero; // volume desc top level + + virtual ~IDirect3DVolumeTexture9(); + + HRESULT LockBox(UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags); + HRESULT UnlockBox(UINT Level); + HRESULT GetLevelDesc( UINT level, D3DVOLUME_DESC *pDesc ); +}; + + +// for the moment, a "D3D surface" is modeled as a GLM tex, a face, and a mip. +// no Create method, these are filled in by the various create surface methods. + +struct TOGL_CLASS IDirect3DSurface9 : public IDirect3DResource9 +{ + virtual ~IDirect3DSurface9(); + + HRESULT LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); + HRESULT UnlockRect(); + HRESULT GetDesc(D3DSURFACE_DESC *pDesc); + + D3DSURFACE_DESC m_desc; + CGLMTex *m_tex; + int m_face; + int m_mip; +}; + + + +struct TOGL_CLASS IDirect3D9 : public IUnknown +{ +public: + virtual ~IDirect3D9(); + + UINT GetAdapterCount(); //cheese: returns 1 + + HRESULT GetDeviceCaps (UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps); + HRESULT GetAdapterIdentifier (UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier); + HRESULT CheckDeviceFormat (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat); + UINT GetAdapterModeCount (UINT Adapter,D3DFORMAT Format); + HRESULT EnumAdapterModes (UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode); + HRESULT CheckDeviceType (UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed); + HRESULT GetAdapterDisplayMode (UINT Adapter,D3DDISPLAYMODE* pMode); + HRESULT CheckDepthStencilMatch (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat); + HRESULT CheckDeviceMultiSampleType (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels); + + HRESULT CreateDevice (UINT Adapter,D3DDEVTYPE DeviceType,VD3DHWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface); +}; + +struct TOGL_CLASS IDirect3DSwapChain9 : public IUnknown +{ +}; + + + + // typedef enum D3DDECLUSAGE + // { + // D3DDECLUSAGE_POSITION = 0, + // D3DDECLUSAGE_BLENDWEIGHT = 1, + // D3DDECLUSAGE_BLENDINDICES = 2, + // D3DDECLUSAGE_NORMAL = 3, + // D3DDECLUSAGE_PSIZE = 4, + // D3DDECLUSAGE_TEXCOORD = 5, + // D3DDECLUSAGE_TANGENT = 6, + // D3DDECLUSAGE_BINORMAL = 7, + // D3DDECLUSAGE_TESSFACTOR = 8, + // D3DDECLUSAGE_POSITIONT = 9, + // D3DDECLUSAGE_COLOR = 10, + // D3DDECLUSAGE_FOG = 11, + // D3DDECLUSAGE_DEPTH = 12, + // D3DDECLUSAGE_SAMPLE = 13, + // } D3DDECLUSAGE, *LPD3DDECLUSAGE; + // Constants + // + // D3DDECLUSAGE_POSITION + // Position data ranging from (-1,-1) to (1,1). Use D3DDECLUSAGE_POSITION with + // a usage index of 0 to specify untransformed position for fixed function + // vertex processing and the n-patch tessellator. Use D3DDECLUSAGE_POSITION + // with a usage index of 1 to specify untransformed position in the fixed + // function vertex shader for vertex tweening. + // + // D3DDECLUSAGE_BLENDWEIGHT + // Blending weight data. Use D3DDECLUSAGE_BLENDWEIGHT with a usage index of 0 + // to specify the blend weights used in indexed and nonindexed vertex + // blending. + // + // D3DDECLUSAGE_BLENDINDICES + // Blending indices data. Use D3DDECLUSAGE_BLENDINDICES with a usage index of + // 0 to specify matrix indices for indexed paletted skinning. + // + // D3DDECLUSAGE_NORMAL + // Vertex normal data. Use D3DDECLUSAGE_NORMAL with a usage index of 0 to + // specify vertex normals for fixed function vertex processing and the n-patch + // tessellator. Use D3DDECLUSAGE_NORMAL with a usage index of 1 to specify + // vertex normals for fixed function vertex processing for vertex tweening. + // + // D3DDECLUSAGE_PSIZE + // Point size data. Use D3DDECLUSAGE_PSIZE with a usage index of 0 to specify + // the point-size attribute used by the setup engine of the rasterizer to + // expand a point into a quad for the point-sprite functionality. + // + // D3DDECLUSAGE_TEXCOORD + // Texture coordinate data. Use D3DDECLUSAGE_TEXCOORD, n to specify texture + // coordinates in fixed function vertex processing and in pixel shaders prior + // to ps_3_0. These can be used to pass user defined data. + // + // D3DDECLUSAGE_TANGENT + // Vertex tangent data. + // + // D3DDECLUSAGE_BINORMAL + // Vertex binormal data. + // + // D3DDECLUSAGE_TESSFACTOR + // Single positive floating point value. Use D3DDECLUSAGE_TESSFACTOR with a + // usage index of 0 to specify a tessellation factor used in the tessellation + // unit to control the rate of tessellation. For more information about the + // data type, see D3DDECLTYPE_FLOAT1. + // + // D3DDECLUSAGE_POSITIONT + // Vertex data contains transformed position data ranging from (0,0) to + // (viewport width, viewport height). Use D3DDECLUSAGE_POSITIONT with a usage + // index of 0 to specify transformed position. When a declaration containing + // this is set, the pipeline does not perform vertex processing. + // + // D3DDECLUSAGE_COLOR + // Vertex data contains diffuse or specular color. Use D3DDECLUSAGE_COLOR with + // a usage index of 0 to specify the diffuse color in the fixed function + // vertex shader and pixel shaders prior to ps_3_0. Use D3DDECLUSAGE_COLOR + // with a usage index of 1 to specify the specular color in the fixed function + // vertex shader and pixel shaders prior to ps_3_0. + // + // D3DDECLUSAGE_FOG + // Vertex data contains fog data. Use D3DDECLUSAGE_FOG with a usage index of 0 + // to specify a fog blend value used after pixel shading finishes. This + // applies to pixel shaders prior to version ps_3_0. + // + // D3DDECLUSAGE_DEPTH + // Vertex data contains depth data. + // + // D3DDECLUSAGE_SAMPLE + // Vertex data contains sampler data. Use D3DDECLUSAGE_SAMPLE with a usage + // index of 0 to specify the displacement value to look up. It can be used + // only with D3DDECLUSAGE_LOOKUPPRESAMPLED or D3DDECLUSAGE_LOOKUP. + + //note the form of the list terminator.. + + // #define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0} + // typedef struct _D3DVERTEXELEMENT9 + // { + // WORD Stream; // Stream index + // WORD Offset; // Offset in the stream in bytes + // BYTE Type; // Data type + // BYTE Method; // Processing method + // BYTE Usage; // Semantics + // BYTE UsageIndex; // Semantic index + // } D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; + +#define MAX_D3DVERTEXELEMENTS 16 + +struct TOGL_CLASS IDirect3DVertexDeclaration9 : public IUnknown +{ +//public: + uint m_elemCount; + D3DVERTEXELEMENT9_GL m_elements[ MAX_D3DVERTEXELEMENTS ]; + + virtual ~IDirect3DVertexDeclaration9(); +}; + +struct TOGL_CLASS IDirect3DQuery9 : public IDirect3DResource9 //was IUnknown +{ +//public: + D3DQUERYTYPE m_type; // D3DQUERYTYPE_OCCLUSION or D3DQUERYTYPE_EVENT + GLMContext *m_ctx; + CGLMQuery *m_query; + + virtual ~IDirect3DQuery9(); + + HRESULT Issue(DWORD dwIssueFlags); + HRESULT GetData(void* pData,DWORD dwSize,DWORD dwGetDataFlags); +}; + +struct TOGL_CLASS IDirect3DVertexBuffer9 : public IDirect3DResource9 //was IUnknown +{ +//public: + GLMContext *m_ctx; + CGLMBuffer *m_vtxBuffer; + D3DVERTEXBUFFER_DESC m_vtxDesc; // to satisfy GetDesc + + virtual ~IDirect3DVertexBuffer9(); + HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); + HRESULT Unlock(); + HRESULT UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); + +}; + +struct TOGL_CLASS IDirect3DIndexBuffer9 : public IDirect3DResource9 //was IUnknown +{ +//public: + GLMContext *m_ctx; + CGLMBuffer *m_idxBuffer; + D3DINDEXBUFFER_DESC m_idxDesc; // to satisfy GetDesc + + virtual ~IDirect3DIndexBuffer9(); + + HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); + HRESULT Unlock(); + HRESULT UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); + HRESULT GetDesc(D3DINDEXBUFFER_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DPixelShader9 : public IDirect3DResource9 //was IUnknown +{ +//public: + CGLMProgram *m_pixProgram; + uint m_pixHighWater; // count of active constant slots referenced by shader. + uint m_pixSamplerMask; // (1< m_stack; + int m_stackTop; // top of stack is at the highest index, this is that index. push increases, pop decreases. + + HRESULT Create( void ); + + D3DXMATRIX* GetTop(); + void Push(); + void Pop(); + void LoadIdentity(); + void LoadMatrix( const D3DXMATRIX *pMat ); + void MultMatrix( const D3DXMATRIX *pMat ); + void MultMatrixLocal( const D3DXMATRIX *pMat ); + HRESULT ScaleLocal(FLOAT x, FLOAT y, FLOAT z); + + // Left multiply the current matrix with the computed rotation + // matrix, counterclockwise about the given axis with the given angle. + // (rotation is about the local origin of the object) + HRESULT RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle); + + // Left multiply the current matrix with the computed translation + // matrix. (transformation is about the local origin of the object) + HRESULT TranslateLocal(FLOAT x, FLOAT y, FLOAT z); +}; +typedef ID3DXMatrixStack* LPD3DXMATRIXSTACK; + +struct TOGL_CLASS IDirect3DDevice9 : public IUnknown +{ +public: + // members + + IDirect3DDevice9Params m_params; // mirror of the creation inputs + + // D3D flavor stuff + IDirect3DSurface9 *m_rtSurfaces[16]; // current color RT surfaces. [0] is initially == m_defaultColorSurface + IDirect3DSurface9 *m_dsSurface; // current DS RT surface. can be changed! + + IDirect3DSurface9 *m_defaultColorSurface; // default color surface. + IDirect3DSurface9 *m_defaultDepthStencilSurface; // queried by GetDepthStencilSurface. + + IDirect3DVertexDeclaration9 *m_vertDecl; // Set by SetVertexDeclaration... + D3DStreamDesc m_streams[ D3D_MAX_STREAMS ]; // Set by SetStreamSource.. + D3DIndexDesc m_indices; // Set by SetIndices.. + + IDirect3DVertexShader9 *m_vertexShader; // Set by SetVertexShader... + IDirect3DPixelShader9 *m_pixelShader; // Set by SetPixelShader... + + IDirect3DBaseTexture9 *m_textures[16]; // set by SetTexture... NULL if stage inactive + D3DSamplerDesc m_samplers[16]; // set by SetSamplerState.. + // GLM flavor stuff + GLMContext *m_ctx; + CGLMFBO *m_drawableFBO; // this FBO should have all the attachments set to match m_rtSurfaces and m_dsSurface. + + // GL state + struct + { + // render state buckets + GLAlphaTestEnable_t m_AlphaTestEnable; + GLAlphaTestFunc_t m_AlphaTestFunc; + + GLAlphaToCoverageEnable_t m_AlphaToCoverageEnable; + + GLDepthTestEnable_t m_DepthTestEnable; + GLDepthMask_t m_DepthMask; + GLDepthFunc_t m_DepthFunc; + + GLClipPlaneEnable_t m_ClipPlaneEnable[kGLMUserClipPlanes]; + GLClipPlaneEquation_t m_ClipPlaneEquation[kGLMUserClipPlanes]; + + GLColorMaskSingle_t m_ColorMaskSingle; + GLColorMaskMultiple_t m_ColorMaskMultiple; + + GLCullFaceEnable_t m_CullFaceEnable; + GLCullFrontFace_t m_CullFrontFace; + GLPolygonMode_t m_PolygonMode; + GLDepthBias_t m_DepthBias; + GLScissorEnable_t m_ScissorEnable; + GLScissorBox_t m_ScissorBox; + GLViewportBox_t m_ViewportBox; + GLViewportDepthRange_t m_ViewportDepthRange; + + GLBlendEnable_t m_BlendEnable; + GLBlendFactor_t m_BlendFactor; + GLBlendEquation_t m_BlendEquation; + GLBlendColor_t m_BlendColor; + GLBlendEnableSRGB_t m_BlendEnableSRGB; + + GLStencilTestEnable_t m_StencilTestEnable; + GLStencilFunc_t m_StencilFunc; + GLStencilOp_t m_StencilOp; + GLStencilWriteMask_t m_StencilWriteMask; + + GLClearColor_t m_ClearColor; + GLClearDepth_t m_ClearDepth; + GLClearStencil_t m_ClearStencil; + + bool m_FogEnable; // not really pushed to GL, just latched here + + // samplers + GLMTexSamplingParams m_samplers[ 16 ]; + + // bindings...hmmm... + + // dirty-bits + uint m_stateDirtyMask; // covers the state blocks, indexed by 1<m_nCurOwnerThreadId; } + +}; + +struct ID3DXInclude +{ + virtual HRESULT Open(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) = 0; + virtual HRESULT Close(LPCVOID pData) = 0; +}; +typedef ID3DXInclude* LPD3DXINCLUDE; + + +struct TOGL_CLASS ID3DXBuffer : public IUnknown +{ + void* GetBufferPointer(); + DWORD GetBufferSize(); +}; + +typedef ID3DXBuffer* LPD3DXBUFFER; + +class TOGL_CLASS ID3DXConstantTable : public IUnknown +{ +}; +typedef ID3DXConstantTable* LPD3DXCONSTANTTABLE; + + + +// ------------------------------------------------------------------------------------------------------------------------------ // +// D3DX stuff. +// ------------------------------------------------------------------------------------------------------------------------------ // + +TOGL_INTERFACE const char* D3DXGetPixelShaderProfile( IDirect3DDevice9 *pDevice ); + + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); +TOGL_INTERFACE D3DXVECTOR3* D3DXVec3TransformCoord( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack); +TOGL_INTERFACE void D3DXMatrixIdentity( D3DXMATRIX * ); + +TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Subtract( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + return pOut; +} + +TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Cross( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + D3DXVECTOR3 v; + + v.x = pV1->y * pV2->z - pV1->z * pV2->y; + v.y = pV1->z * pV2->x - pV1->x * pV2->z; + v.z = pV1->x * pV2->y - pV1->y * pV2->x; + + *pOut = v; + return pOut; +} + +TOGL_INTERFACE D3DXINLINE FLOAT D3DXVec3Dot( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; +} + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP); + +TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM ); + + +TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z ); + +// Build an ortho projection matrix. (right-handed) +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf ); + +// Transform a plane by a matrix. The vector (a,b,c) must be normal. +// M should be the inverse transpose of the transformation desired. +TOGL_INTERFACE D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE IDirect3D9 *Direct3DCreate9(UINT SDKVersion); + +TOGL_INTERFACE void D3DPERF_SetOptions( DWORD dwOptions ); + +TOGL_INTERFACE HRESULT D3DXCompileShader( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + + +#endif // USE_ACTUAL_DX + +// fake D3D usage constant for SRGB tex creation +#define D3DUSAGE_TEXTURE_SRGB (0x80000000L) + +#endif // DXABSTRACT_H diff --git a/mp/src/public/togl/osx/dxabstract_types.h b/mp/src/public/togl/osx/dxabstract_types.h new file mode 100644 index 00000000..7df586cd --- /dev/null +++ b/mp/src/public/togl/osx/dxabstract_types.h @@ -0,0 +1,1710 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// dxabstract_types.h +// +//================================================================================================== +#ifndef DXABSTRACT_TYPES_H +#define DXABSTRACT_TYPES_H + +#pragma once + +#if GL_BATCH_PERF_ANALYSIS + class simple_bitmap; +#endif + +struct IUnknown; +struct IDirect3D9; +struct IDirect3DDevice9; +struct IDirect3DResource9; +struct IDirect3DBaseTexture9; +struct IDirect3DTexture9; +struct IDirect3DCubeTexture9; +struct IDirect3DVolumeTexture9; +struct IDirect3DSurface9; +struct IDirect3DVertexDeclaration9; +struct IDirect3DQuery9; +struct IDirect3DVertexBuffer9; +struct IDirect3DIndexBuffer9; +struct IDirect3DPixelShader9; +struct IDirect3DVertexShader9; +struct IDirect3DDevice9Params; + +class GLMContext; +struct GLMRect; +struct GLMShaderPairInfo; +class CGLMBuffer; +class CGLMQuery; +class CGLMTex; +class CGLMProgram; +class CGLMFBO; + +#ifdef TOGL_DLL_EXPORT + #define TOGL_INTERFACE DLL_EXPORT + #define TOGL_OVERLOAD DLL_GLOBAL_EXPORT + #define TOGL_CLASS DLL_CLASS_EXPORT + #define TOGL_GLOBAL DLL_GLOBAL_EXPORT +#else + #define TOGL_INTERFACE DLL_IMPORT + #define TOGL_OVERLOAD DLL_GLOBAL_IMPORT + #define TOGL_CLASS DLL_CLASS_IMPORT + #define TOGL_GLOBAL DLL_GLOBAL_IMPORT +#endif + +#define TOGLMETHODCALLTYPE __stdcall +//#define TOGLMETHODCALLTYPE + +#define DXABSTRACT_BREAK_ON_ERROR() DebuggerBreak() + +typedef void* VD3DHWND; +typedef void* VD3DHANDLE; + +#define MAKEFOURCC(ch0, ch1, ch2, ch3) ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) + +// +// +// Stuff that would be in windows.h +// +// +#if !defined(_WINNT_) + + typedef int INT; + typedef unsigned long ULONG; + typedef long LONG; + typedef float FLOAT; + typedef unsigned short WORD; + typedef long long LONGLONG; + typedef unsigned int UINT; + typedef long HRESULT; + typedef unsigned char BYTE; + #define CONST const + + #if defined(POSIX) + typedef size_t ULONG_PTR; + #else + typedef unsigned long ULONG_PTR; + #endif + + typedef ULONG_PTR SIZE_T; + + typedef const char* LPCSTR; + typedef char* LPSTR; +#ifndef OSX + typedef unsigned int DWORD; + typedef DWORD* LPDWORD; +#endif + + + #define ZeroMemory RtlZeroMemory + #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length)) + + typedef union _LARGE_INTEGER + { + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + LONGLONG QuadPart; + } LARGE_INTEGER; + + typedef struct _GUID + { + bool operator==( const struct _GUID &other ) const; + + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; + } GUID; + + typedef struct _RECT + { + int left; + int top; + int right; + int bottom; + } RECT; + + typedef struct tagPOINT + { + LONG x; + LONG y; + } POINT, *PPOINT, *LPPOINT; + + typedef struct _MEMORYSTATUS + { + DWORD dwLength; + SIZE_T dwTotalPhys; + } MEMORYSTATUS, *LPMEMORYSTATUS; + + typedef DWORD COLORREF; + #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) + + #define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + + +// Mac header files like to define these +#ifdef S_FALSE +#undef S_FALSE +#endif +#ifdef S_OK +#undef S_OK +#endif +#ifdef E_FAIL +#undef E_FAIL +#endif +#ifdef E_OUTOFMEMORY +#undef E_OUTOFMEMORY +#endif +#ifdef FAILED +#undef FAILED +#endif +#ifdef SUCCEEDED +#undef SUCCEEDED +#endif + + #define S_FALSE ((HRESULT)0x00000001L) + #define S_OK 0 + #define E_FAIL ((HRESULT)0x80004005L) + #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) + + #define FAILED(hr) ((HRESULT)(hr) < 0) + #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) + + struct RGNDATA + { + }; + + typedef const void* LPCVOID; +#endif + +//----------------------------------------------------------------------------- + +typedef enum _D3DFORMAT D3DFORMAT; + +#define D3DSI_OPCODE_MASK 0x0000FFFF +#define D3DSP_TEXTURETYPE_MASK 0x78000000 + +#define D3DUSAGE_AUTOGENMIPMAP 0x00000400L +#define D3DSP_DCL_USAGE_MASK 0x0000000f + +#define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000 +#define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16 + + +/* Flags to construct D3DRS_COLORWRITEENABLE */ +#define D3DCOLORWRITEENABLE_RED (1L<<0) +#define D3DCOLORWRITEENABLE_GREEN (1L<<1) +#define D3DCOLORWRITEENABLE_BLUE (1L<<2) +#define D3DCOLORWRITEENABLE_ALPHA (1L<<3) + +#define D3DSGR_NO_CALIBRATION 0x00000000L + +#define D3DXINLINE inline + +#define D3D_SDK_VERSION 32 + +#define _FACD3D 0x876 +#define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) + +#define D3DERR_NOTFOUND MAKE_D3DHRESULT(2150) +#define D3DERR_DEVICELOST MAKE_D3DHRESULT(2152) +#define D3DERR_NOTAVAILABLE MAKE_D3DHRESULT(2154) +#define D3DERR_DEVICENOTRESET MAKE_D3DHRESULT(2153) +#define D3DERR_INVALIDCALL MAKE_D3DHRESULT(2156) +#define D3DERR_DRIVERINTERNALERROR MAKE_D3DHRESULT(2087) +#define D3DERR_OUTOFVIDEOMEMORY MAKE_D3DHRESULT(380) +#define D3D_OK S_OK + +#define D3DPRESENT_RATE_DEFAULT 0x00000000 + +// +// DevCaps +// +// we need to see who in Source land is interested in these values, as dxabstract is currently reporting zero for the whole Caps word +#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ +#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ +#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ +#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */ +#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */ +#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */ +#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */ +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */ +#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */ +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ +#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */ +#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */ +#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */ + +// +// PrimitiveMiscCaps +// +#define D3DPMISCCAPS_MASKZ 0x00000002L +#define D3DPMISCCAPS_CULLNONE 0x00000010L +#define D3DPMISCCAPS_CULLCW 0x00000020L +#define D3DPMISCCAPS_CULLCCW 0x00000040L +#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L +#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */ +#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */ +#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */ +#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */ +#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */ +#define D3DPMISCCAPS_PERSTAGECONSTANT 0x00008000L /* Device supports per-stage constants */ +#define D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS 0x00040000L /* Device supports different bit depths for MRT */ +#define D3DPMISCCAPS_FOGVERTEXCLAMPED 0x00100000L /* Device clamps fog blend factor per vertex */ + +// Flags field for Issue +#define D3DISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled". +#define D3DISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginng of a query. + + +#define D3DPRESENT_INTERVAL_ONE 0x00000001L +#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L + +/* + * Options for clearing + */ +#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ +#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ +#define D3DCLEAR_STENCIL 0x00000004l /* Clear stencil planes */ + + +#define D3DENUM_WHQL_LEVEL 0x00000002L + + + + +#define D3DPTEXTURECAPS_NOPROJECTEDBUMPENV 0x00200000L /* Device does not support projected bump env lookup operation + in programmable and fixed function pixel shaders */ +#define D3DDEVCAPS2_STREAMOFFSET 0x00000001L /* Device supports offsets in streams. Must be set by DX9 drivers */ + +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ + +#define D3DCREATE_PUREDEVICE 0x00000010L +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0x00000020L +#define D3DCREATE_HARDWARE_VERTEXPROCESSING 0x00000040L +#define D3DCREATE_FPU_PRESERVE 0x00000002L +#define D3DPRASTERCAPS_FOGRANGE 0x00010000L +#define D3DPRASTERCAPS_FOGTABLE 0x00000100L +#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L +#define D3DPRASTERCAPS_WFOG 0x00100000L +#define D3DPRASTERCAPS_ZFOG 0x00200000L +#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L +#define D3DPRASTERCAPS_WBUFFER 0x00040000L +#define D3DPRASTERCAPS_ZTEST 0x00000010L + +// +// Caps2 +// +#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L +#define D3DPRASTERCAPS_SCISSORTEST 0x01000000L +#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */ +#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */ +#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */ +#define D3DCREATE_MULTITHREADED 0x00000004L +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L +#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L +#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */ +#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */ +#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L +#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */ +#define D3DTEXOPCAPS_ADD 0x00000040L +#define D3DTEXOPCAPS_MODULATE2X 0x00000010L +#define D3DPRASTERCAPS_DEPTHBIAS 0x04000000L +#define D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS 0x02000000L +#define D3DVTXPCAPS_TEXGEN_SPHEREMAP 0x00000100L /* device supports D3DTSS_TCI_SPHEREMAP */ +#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L + +// The following usages are valid only for querying CheckDeviceFormat +#define D3DUSAGE_QUERY_SRGBREAD (0x00010000L) +#define D3DUSAGE_QUERY_FILTER (0x00020000L) +#define D3DUSAGE_QUERY_SRGBWRITE (0x00040000L) +#define D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING (0x00080000L) +#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) + +/* Usages for Vertex/Index buffers */ +#define D3DUSAGE_WRITEONLY (0x00000008L) +#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) +#define D3DUSAGE_DONOTCLIP (0x00000020L) +#define D3DUSAGE_POINTS (0x00000040L) +#define D3DUSAGE_RTPATCHES (0x00000080L) +#define D3DUSAGE_NPATCHES (0x00000100L) + + +// Flags field for GetData +#define D3DGETDATA_FLUSH (1 << 0) // Tells the runtime to flush if the query is outstanding. + +#define D3DFVF_XYZ 0x002 + + +#define D3DTA_SELECTMASK 0x0000000f // mask for arg selector +#define D3DTA_DIFFUSE 0x00000000 // select diffuse color (read only) +#define D3DTA_CURRENT 0x00000001 // select stage destination register (read/write) +#define D3DTA_TEXTURE 0x00000002 // select texture color (read only) +#define D3DTA_TFACTOR 0x00000003 // select D3DRS_TEXTUREFACTOR (read only) +#define D3DTA_SPECULAR 0x00000004 // select specular color (read only) +#define D3DTA_TEMP 0x00000005 // select temporary register color (read/write) +#define D3DTA_CONSTANT 0x00000006 // select texture stage constant +#define D3DTA_COMPLEMENT 0x00000010 // take 1.0 - x (read modifier) +#define D3DTA_ALPHAREPLICATE 0x00000020 // replicate alpha to color components (read modifier) + + +#define D3DUSAGE_RENDERTARGET (0x00000001L) +#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) +#define D3DUSAGE_QUERY_FILTER (0x00020000L) +#define D3DUSAGE_DEPTHSTENCIL (0x00000002L) +#define D3DUSAGE_WRITEONLY (0x00000008L) +#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) +#define D3DUSAGE_DYNAMIC (0x00000200L) + +#define D3DSI_INSTLENGTH_MASK 0x0F000000 +#define D3DSI_INSTLENGTH_SHIFT 24 +#define D3DSP_TEXTURETYPE_SHIFT 27 +#define D3DSP_REGTYPE_SHIFT 28 +#define D3DSP_REGTYPE_SHIFT2 8 +#define D3DSP_REGTYPE_MASK 0x70000000 +#define D3DSP_REGTYPE_MASK2 0x00001800 + +#define D3DSP_REGNUM_MASK 0x000007FF + +#define D3DSP_DSTMOD_SHIFT 20 +#define D3DSP_DSTMOD_MASK 0x00F00000 +#define D3DSPDM_MSAMPCENTROID (4<>8)&0xFF) +#define D3DSHADER_VERSION_MINOR(_Version) (((_Version)>>0)&0xFF) + +#define D3DSHADER_ADDRESSMODE_SHIFT 13 +#define D3DSHADER_ADDRESSMODE_MASK (1 << D3DSHADER_ADDRESSMODE_SHIFT) + +#define D3DPS_END() 0x0000FFFF + +// ps_2_0 texld controls +#define D3DSI_TEXLD_PROJECT (0x01 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) +#define D3DSI_TEXLD_BIAS (0x02 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) + + +// destination parameter write mask +#define D3DSP_WRITEMASK_0 0x00010000 // Component 0 (X;Red) +#define D3DSP_WRITEMASK_1 0x00020000 // Component 1 (Y;Green) +#define D3DSP_WRITEMASK_2 0x00040000 // Component 2 (Z;Blue) +#define D3DSP_WRITEMASK_3 0x00080000 // Component 3 (W;Alpha) +#define D3DSP_WRITEMASK_ALL 0x000F0000 // All Components + +#define D3DVS_SWIZZLE_SHIFT 16 +#define D3DVS_SWIZZLE_MASK 0x00FF0000 + +// The following bits define where to take component X from: + +#define D3DVS_X_X (0 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_Y (1 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_Z (2 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_W (3 << D3DVS_SWIZZLE_SHIFT) + +// The following bits define where to take component Y from: + +#define D3DVS_Y_X (0 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_Y (1 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_Z (2 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_W (3 << (D3DVS_SWIZZLE_SHIFT + 2)) + +// The following bits define where to take component Z from: + +#define D3DVS_Z_X (0 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_Y (1 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_Z (2 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_W (3 << (D3DVS_SWIZZLE_SHIFT + 4)) + +// The following bits define where to take component W from: + +#define D3DVS_W_X (0 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_Y (1 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_Z (2 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_W (3 << (D3DVS_SWIZZLE_SHIFT + 6)) + +// source parameter modifiers +#define D3DSP_SRCMOD_SHIFT 24 +#define D3DSP_SRCMOD_MASK 0x0F000000 + +// ------------------------------------------------------------------------------------------------------------------------------ // +// ENUMS +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef enum _D3DSHADER_PARAM_SRCMOD_TYPE +{ + D3DSPSM_NONE = 0<= 2.0 + + + D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 + D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) + D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) + D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) + D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) + D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) + D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) + D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) + D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values + D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. +} D3DDECLTYPE; + +typedef enum _D3DDECLMETHOD +{ + D3DDECLMETHOD_DEFAULT = 0, + D3DDECLMETHOD_PARTIALU, + D3DDECLMETHOD_PARTIALV, + D3DDECLMETHOD_CROSSUV, // Normal + D3DDECLMETHOD_UV, + D3DDECLMETHOD_LOOKUP, // Lookup a displacement map + D3DDECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map +} D3DDECLMETHOD; + +typedef enum _D3DDECLUSAGE +{ + D3DDECLUSAGE_POSITION = 0, + D3DDECLUSAGE_BLENDWEIGHT = 1, + D3DDECLUSAGE_BLENDINDICES = 2, + D3DDECLUSAGE_NORMAL = 3, + D3DDECLUSAGE_PSIZE = 4, + D3DDECLUSAGE_TEXCOORD = 5, + D3DDECLUSAGE_TANGENT = 6, + D3DDECLUSAGE_BINORMAL = 7, + D3DDECLUSAGE_TESSFACTOR = 8, + D3DDECLUSAGE_PLUGH = 9, // mystery value + D3DDECLUSAGE_COLOR = 10, + D3DDECLUSAGE_FOG = 11, + D3DDECLUSAGE_DEPTH = 12, + D3DDECLUSAGE_SAMPLE = 13, +} D3DDECLUSAGE; + +typedef enum _D3DPRIMITIVETYPE +{ + D3DPT_POINTLIST = 1, + D3DPT_LINELIST = 2, + D3DPT_TRIANGLELIST = 4, + D3DPT_TRIANGLESTRIP = 5, + D3DPT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DPRIMITIVETYPE; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// STRUCTURES +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef struct TOGL_CLASS D3DXPLANE +{ + float& operator[]( int i ); + bool operator==( const D3DXPLANE &o ); + bool operator!=( const D3DXPLANE &o ); + operator float*(); + operator const float*() const; + + float a, b, c, d; +} D3DXPLANE; + +typedef enum _D3DVERTEXBLENDFLAGS +{ + D3DVBF_DISABLE = 0, // Disable vertex blending + D3DVBF_1WEIGHTS = 1, // 2 matrix blending + D3DVBF_2WEIGHTS = 2, // 3 matrix blending + D3DVBF_3WEIGHTS = 3, // 4 matrix blending + D3DVBF_TWEENING = 255, // blending using D3DRS_TWEENFACTOR + D3DVBF_0WEIGHTS = 256, // one matrix is used with weight 1.0 + D3DVBF_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} D3DVERTEXBLENDFLAGS; + +typedef struct _D3DINDEXBUFFER_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + UINT Size; +} D3DINDEXBUFFER_DESC; + +typedef struct _D3DVERTEXELEMENT9 +{ + WORD Stream; // Stream index + WORD Offset; // Offset in the stream in bytes + BYTE Type; // Data type + BYTE Method; // Processing method + BYTE Usage; // Semantics + BYTE UsageIndex; // Semantic index +} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; + + +#define MAX_DEVICE_IDENTIFIER_STRING 512 +typedef struct _D3DADAPTER_IDENTIFIER9 +{ + char Driver[MAX_DEVICE_IDENTIFIER_STRING]; + char Description[MAX_DEVICE_IDENTIFIER_STRING]; + char DeviceName[32]; /* Device name for GDI (ex. \\.\DISPLAY1) */ + + LARGE_INTEGER DriverVersion; /* Defined for 32 bit components */ + + DWORD VendorId; + DWORD DeviceId; + DWORD SubSysId; + DWORD Revision; + DWORD VideoMemory; + +} D3DADAPTER_IDENTIFIER9; + +typedef struct _D3DCOLORVALUE +{ + float r; + float g; + float b; + float a; +} D3DCOLORVALUE; + +typedef struct _D3DMATERIAL9 +{ + D3DCOLORVALUE Diffuse; /* Diffuse color RGBA */ + D3DCOLORVALUE Ambient; /* Ambient color RGB */ + D3DCOLORVALUE Specular; /* Specular 'shininess' */ + D3DCOLORVALUE Emissive; /* Emissive color RGB */ + float Power; /* Sharpness if specular highlight */ +} D3DMATERIAL9; + +typedef struct _D3DVOLUME_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + + UINT Width; + UINT Height; + UINT Depth; +} D3DVOLUME_DESC; + +typedef struct _D3DVIEWPORT9 +{ + DWORD X; + DWORD Y; /* Viewport Top left */ + DWORD Width; + DWORD Height; /* Viewport Dimensions */ + float MinZ; /* Min/max of clip Volume */ + float MaxZ; +} D3DVIEWPORT9; + +typedef struct _D3DPSHADERCAPS2_0 +{ + DWORD Caps; + INT DynamicFlowControlDepth; + INT NumTemps; + INT StaticFlowControlDepth; + INT NumInstructionSlots; +} D3DPSHADERCAPS2_0; + +typedef struct _D3DCAPS9 +{ + /* Device Info */ + D3DDEVTYPE DeviceType; + + /* Caps from DX7 Draw */ + DWORD Caps; + DWORD Caps2; + + /* Cursor Caps */ + DWORD CursorCaps; + + /* 3D Device Caps */ + DWORD DevCaps; + + DWORD PrimitiveMiscCaps; + DWORD RasterCaps; + DWORD TextureCaps; + DWORD TextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DTexture9's + + DWORD MaxTextureWidth, MaxTextureHeight; + DWORD MaxVolumeExtent; + + DWORD MaxTextureAspectRatio; + DWORD MaxAnisotropy; + + DWORD TextureOpCaps; + DWORD MaxTextureBlendStages; + DWORD MaxSimultaneousTextures; + + DWORD VertexProcessingCaps; + DWORD MaxActiveLights; + DWORD MaxUserClipPlanes; + DWORD MaxVertexBlendMatrices; + DWORD MaxVertexBlendMatrixIndex; + + DWORD MaxPrimitiveCount; // max number of primitives per DrawPrimitive call + DWORD MaxStreams; + + DWORD VertexShaderVersion; + DWORD MaxVertexShaderConst; // number of vertex shader constant registers + + DWORD PixelShaderVersion; + + // Here are the DX9 specific ones + DWORD DevCaps2; + D3DPSHADERCAPS2_0 PS20Caps; + + DWORD NumSimultaneousRTs; // Will be at least 1 + DWORD MaxVertexShader30InstructionSlots; + DWORD MaxPixelShader30InstructionSlots; + + // only on Posix/GL + DWORD FakeSRGBWrite; // 1 for parts which can't support SRGB writes due to driver issues - 0 for others + DWORD MixedSizeTargets; // 1 for parts which can mix attachment sizes (RT's color vs depth) + DWORD CanDoSRGBReadFromRTs; // 0 when we're on Leopard, 1 when on Snow Leopard +} D3DCAPS9; + +typedef struct _D3DDISPLAYMODE +{ + UINT Width; + UINT Height; + UINT RefreshRate; + D3DFORMAT Format; +} D3DDISPLAYMODE; + +typedef struct _D3DGAMMARAMP +{ + WORD red [256]; + WORD green[256]; + WORD blue [256]; +} D3DGAMMARAMP; + + +/* Resize Optional Parameters */ +typedef struct _D3DPRESENT_PARAMETERS_ +{ + UINT BackBufferWidth; + UINT BackBufferHeight; + D3DFORMAT BackBufferFormat; + UINT BackBufferCount; + + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + + D3DSWAPEFFECT SwapEffect; + VD3DHWND hDeviceWindow; + BOOL Windowed; + BOOL EnableAutoDepthStencil; + D3DFORMAT AutoDepthStencilFormat; + DWORD Flags; + + /* FullScreen_RefreshRateInHz must be zero for Windowed mode */ + UINT FullScreen_RefreshRateInHz; + UINT PresentationInterval; +} D3DPRESENT_PARAMETERS; + +typedef struct _D3DDEVICE_CREATION_PARAMETERS +{ + UINT AdapterOrdinal; + D3DDEVTYPE DeviceType; + VD3DHWND hFocusWindow; + DWORD BehaviorFlags; +} D3DDEVICE_CREATION_PARAMETERS; + +/* Structures for LockBox */ +typedef struct _D3DBOX +{ + UINT Left; + UINT Top; + UINT Right; + UINT Bottom; + UINT Front; + UINT Back; +} D3DBOX; + +typedef struct _D3DLOCKED_BOX +{ + INT RowPitch; + INT SlicePitch; + void* pBits; +} D3DLOCKED_BOX; + +typedef struct _D3DSURFACE_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + UINT Width; + UINT Height; +} D3DSURFACE_DESC; + + +typedef struct _D3DLOCKED_RECT +{ + INT Pitch; + void* pBits; +} D3DLOCKED_RECT; + + +typedef struct _D3DRASTER_STATUS +{ + BOOL InVBlank; + UINT ScanLine; +} D3DRASTER_STATUS; + +typedef enum _D3DLIGHTTYPE +{ + D3DLIGHT_POINT = 1, + D3DLIGHT_SPOT = 2, + D3DLIGHT_DIRECTIONAL = 3, + D3DLIGHT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DLIGHTTYPE; + +typedef struct TOGL_CLASS _D3DVECTOR +{ + float x; + float y; + float z; +} D3DVECTOR; + +class TOGL_CLASS D3DXVECTOR2 +{ +public: + operator FLOAT* (); + operator CONST FLOAT* () const; + + float x,y; +}; + +class TOGL_CLASS D3DXVECTOR3 : public D3DVECTOR +{ +public: + D3DXVECTOR3() {} + D3DXVECTOR3( float a, float b, float c ); + operator FLOAT* (); + operator CONST FLOAT* () const; +}; + +typedef enum _D3DXINCLUDE_TYPE +{ + D3DXINC_LOCAL, + + // force 32-bit size enum + D3DXINC_FORCE_DWORD = 0x7fffffff + +} D3DXINCLUDE_TYPE; + +typedef struct _D3DLIGHT9 +{ + D3DLIGHTTYPE Type; /* Type of light source */ + D3DCOLORVALUE Diffuse; /* Diffuse color of light */ + D3DCOLORVALUE Specular; /* Specular color of light */ + D3DCOLORVALUE Ambient; /* Ambient color of light */ + D3DVECTOR Position; /* Position in world space */ + D3DVECTOR Direction; /* Direction in world space */ + float Range; /* Cutoff range */ + float Falloff; /* Falloff */ + float Attenuation0; /* Constant attenuation */ + float Attenuation1; /* Linear attenuation */ + float Attenuation2; /* Quadratic attenuation */ + float Theta; /* Inner angle of spotlight cone */ + float Phi; /* Outer angle of spotlight cone */ +} D3DLIGHT9; + +class TOGL_CLASS D3DXVECTOR4 +{ +public: + D3DXVECTOR4() {} + D3DXVECTOR4( float a, float b, float c, float d ); + + float x,y,z,w; +}; + +//---------------------------------------------------------------------------- +// D3DXMACRO: +// ---------- +// Preprocessor macro definition. The application pass in a NULL-terminated +// array of this structure to various D3DX APIs. This enables the application +// to #define tokens at runtime, before the file is parsed. +//---------------------------------------------------------------------------- + +typedef struct _D3DXMACRO +{ + LPCSTR Name; + LPCSTR Definition; + +} D3DXMACRO, *LPD3DXMACRO; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// ------------------------------------------------------------------------------------------------------------------------------ // +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +// +// Also look for any functions marked with "**** FIXED FUNCTION STUFF" +// +// It's only laying around here so we don't have to chop up the shader system a lot to strip out the fixed function code paths. +// ------------------------------------------------------------------------------------------------------------------------------ // +// ------------------------------------------------------------------------------------------------------------------------------ // + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTRANSFORMSTATETYPE +{ + D3DTS_VIEW = 2, + D3DTS_PROJECTION = 3, + D3DTS_TEXTURE0 = 16, + D3DTS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTRANSFORMSTATETYPE; + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTEXTUREOP +{ + // Control + D3DTOP_DISABLE = 1, // disables stage + D3DTOP_SELECTARG1 = 2, // the default + D3DTOP_SELECTARG2 = 3, + + // Modulate + D3DTOP_MODULATE = 4, // multiply args together + D3DTOP_MODULATE2X = 5, // multiply and 1 bit + D3DTOP_MODULATE4X = 6, // multiply and 2 bits + + // Add + D3DTOP_ADD = 7, // add arguments together + D3DTOP_ADDSIGNED = 8, // add with -0.5 bias + D3DTOP_ADDSIGNED2X = 9, // as above but left 1 bit + D3DTOP_SUBTRACT = 10, // Arg1 - Arg2, with no saturation + D3DTOP_ADDSMOOTH = 11, // add 2 args, subtract product + // Arg1 + Arg2 - Arg1*Arg2 + // = Arg1 + (1-Arg1)*Arg2 + + // Linear alpha blend: Arg1*(Alpha) + Arg2*(1-Alpha) + D3DTOP_BLENDDIFFUSEALPHA = 12, // iterated alpha + D3DTOP_BLENDTEXTUREALPHA = 13, // texture alpha + D3DTOP_BLENDFACTORALPHA = 14, // alpha from D3DRS_TEXTUREFACTOR + + // Linear alpha blend with pre-multiplied arg1 input: Arg1 + Arg2*(1-Alpha) + D3DTOP_BLENDTEXTUREALPHAPM = 15, // texture alpha + D3DTOP_BLENDCURRENTALPHA = 16, // by alpha of current color + + // Specular mapping + D3DTOP_PREMODULATE = 17, // modulate with next texture before use + D3DTOP_MODULATEALPHA_ADDCOLOR = 18, // Arg1.RGB + Arg1.A*Arg2.RGB + // COLOROP only + D3DTOP_MODULATECOLOR_ADDALPHA = 19, // Arg1.RGB*Arg2.RGB + Arg1.A + // COLOROP only + D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20, // (1-Arg1.A)*Arg2.RGB + Arg1.RGB + // COLOROP only + D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21, // (1-Arg1.RGB)*Arg2.RGB + Arg1.A + // COLOROP only + + // Bump mapping + D3DTOP_BUMPENVMAP = 22, // per pixel env map perturbation + D3DTOP_BUMPENVMAPLUMINANCE = 23, // with luminance channel + + // This can do either diffuse or specular bump mapping with correct input. + // Performs the function (Arg1.R*Arg2.R + Arg1.G*Arg2.G + Arg1.B*Arg2.B) + // where each component has been scaled and offset to make it signed. + // The result is replicated into all four (including alpha) channels. + // This is a valid COLOROP only. + D3DTOP_DOTPRODUCT3 = 24, + + // Triadic ops + D3DTOP_MULTIPLYADD = 25, // Arg0 + Arg1*Arg2 + D3DTOP_LERP = 26, // (Arg0)*Arg1 + (1-Arg0)*Arg2 + + D3DTOP_FORCE_DWORD = 0x7fffffff, +} D3DTEXTUREOP; + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTEXTURESTAGESTATETYPE +{ + D3DTSS_COLOROP = 1, /* D3DTEXTUREOP - per-stage blending controls for color channels */ + D3DTSS_COLORARG1 = 2, /* D3DTA_* (texture arg) */ + D3DTSS_COLORARG2 = 3, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAOP = 4, /* D3DTEXTUREOP - per-stage blending controls for alpha channel */ + D3DTSS_ALPHAARG1 = 5, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAARG2 = 6, /* D3DTA_* (texture arg) */ + D3DTSS_BUMPENVMAT00 = 7, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT01 = 8, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT10 = 9, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT11 = 10, /* float (bump mapping matrix) */ + D3DTSS_TEXCOORDINDEX = 11, /* identifies which set of texture coordinates index this texture */ + D3DTSS_BUMPENVLOFFSET = 23, /* float offset for bump map luminance */ + D3DTSS_TEXTURETRANSFORMFLAGS = 24, /* D3DTEXTURETRANSFORMFLAGS controls texture transform */ + D3DTSS_COLORARG0 = 26, /* D3DTA_* third arg for triadic ops */ + D3DTSS_RESULTARG = 28, /* D3DTA_* arg for result (CURRENT or TEMP) */ + + + D3DTSS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTEXTURESTAGESTATETYPE; + +//===========================================================================// + +enum GLMVertexAttributeIndex +{ + kGLMGenericAttr00 = 0, + kGLMGenericAttr01, + kGLMGenericAttr02, + kGLMGenericAttr03, + kGLMGenericAttr04, + kGLMGenericAttr05, + kGLMGenericAttr06, + kGLMGenericAttr07, + kGLMGenericAttr08, + kGLMGenericAttr09, + kGLMGenericAttr10, + kGLMGenericAttr11, + kGLMGenericAttr12, + kGLMGenericAttr13, + kGLMGenericAttr14, + kGLMGenericAttr15, + + kGLMVertexAttributeIndexMax // ideally < 32 +}; + +struct GLMVertexAttributeDesc // all the info you need to do vertex setup for one attribute +{ + CGLMBuffer *m_buffer; // NULL allowed in which case m_offset is the full 32-bit pointer.. so you can draw from plain RAM if desired + GLuint m_datasize; // comp count of the attribute (1-4) + GLenum m_datatype; // data type of the attribute (GL_FLOAT, GL_UNSIGNED_BYTE, etc) + GLuint m_stride; + GLuint m_offset; // net offset to attribute 'zero' within the buffer. + GLboolean m_normalized; // apply to any fixed point data that needs normalizing, esp color bytes + + // may need a seed value at some point to be able to disambiguate re-lifed buffers holding same pointer + // simpler alternative is to do shoot-down inside the vertex/index buffer free calls. + // I'd rather not have to have each attribute fiddling a ref count on the buffer to which it refers.. + +#define EQ(fff) ( (src.fff) == (fff) ) + // test in decreasing order of likelihood of difference, but do not include the buffer revision as caller is not supplying it.. + bool operator==(const GLMVertexAttributeDesc& src) const { return EQ(m_buffer) && EQ(m_offset) && EQ(m_stride) && EQ(m_datatype) && EQ(m_normalized) && EQ(m_datasize); } +#undef EQ + + uint m_bufferRevision; // only set in GLM context's copy, to disambiguate references that are same offset / same buffer but cross an orphan event +}; + + +#define MAX_D3DVERTEXELEMENTS 16 + +struct D3DVERTEXELEMENT9_GL +{ + // fields right out of the original decl element (copied) + D3DVERTEXELEMENT9 m_dxdecl; // d3d info + // WORD Stream; // Stream index + // WORD Offset; // Offset in the stream in bytes + // BYTE Type; // Data type + // BYTE Method; // Processing method + // BYTE Usage; // Semantics + // BYTE UsageIndex; // Semantic index + + GLMVertexAttributeDesc m_gldecl; + // CGLMBuffer *m_buffer; // late-dropped from selected stream desc (left NULL, will replace with stream source buffer at sync time) + // GLuint m_datasize; // component count (1,2,3,4) of the attrib + // GLenum m_datatype; // data type of the attribute (GL_FLOAT et al) + // GLuint m_stride; // late-dropped from stream desc + // GLuint m_offset; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. + // GLuint m_normalized; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. +}; + +struct IDirect3DDevice9Params +{ + UINT m_adapter; + D3DDEVTYPE m_deviceType; + VD3DHWND m_focusWindow; + DWORD m_behaviorFlags; + D3DPRESENT_PARAMETERS m_presentationParameters; +}; + +#define D3D_MAX_STREAMS 4 +struct D3DStreamDesc +{ + IDirect3DVertexBuffer9 *m_vtxBuffer; + uint m_offset; + uint m_stride; +}; + +struct D3DIndexDesc +{ + IDirect3DIndexBuffer9 *m_idxBuffer; +}; + +// we latch sampler values until draw time and then convert them all to GL form +// note these are similar in name to the fields of a GLMTexSamplingParams but contents are not +// particularly in the texture filtering area + +struct D3DSamplerDesc +{ + D3DTEXTUREADDRESS m_addressModes[3]; // D3DTEXTUREADDRESS modes for S,T,R + DWORD m_borderColor; // DWORD bordercolor + D3DTEXTUREFILTERTYPE m_magFilter; // mag filter + D3DTEXTUREFILTERTYPE m_minFilter; // min filter + D3DTEXTUREFILTERTYPE m_mipFilter; // mip filter + float m_mipmapBias; // float: mipmap bias + DWORD m_maxMipLevel; // DWORD 0..(n-1) LOD index of largest map to use (0 == largest) + DWORD m_maxAniso; // D3DSAMP_MAXANISOTROPY max aniso + DWORD m_srgb; // D3DSAMP_SRGBTEXTURE 0 = no SRGB sampling + DWORD m_shadowFilter; // D3DSAMP_SHADOWFILTER +}; + +// Tracking and naming sampler dimensions +#define SAMPLER_TYPE_2D 0 +#define SAMPLER_TYPE_CUBE 1 +#define SAMPLER_TYPE_3D 2 +#define SAMPLER_TYPE_UNUSED 3 + +#endif // DXABSTRACT_TYPES_H diff --git a/mp/src/public/togl/osx/glentrypoints.h b/mp/src/public/togl/osx/glentrypoints.h new file mode 100644 index 00000000..1ae4423c --- /dev/null +++ b/mp/src/public/togl/osx/glentrypoints.h @@ -0,0 +1,329 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glentrypoints.h +// +//=============================================================================== + +#ifndef GLENTRYPOINTS_H +#define GLENTRYPOINTS_H + +#pragma once + +#ifdef DX_TO_GL_ABSTRACTION + +#include "tier0/platform.h" +#include "tier0/dynfunction.h" +#include "tier0/vprof_telemetry.h" +#include "interface.h" + +#include "togl/rendermechanism.h" + +#ifndef APIENTRY +#define APIENTRY +#endif + +#ifndef CALLBACK +#define CALLBACK +#endif + + +void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback=NULL); + +#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME +class CGLExecuteHelperBase +{ +public: + inline void StartCall(const char *pName); + inline void StopCall(const char *pName); +#if GL_TRACK_API_TIME + TmU64 m_nStartTime; +#endif +}; + +template < class FunctionType, typename Result > +class CGLExecuteHelper : public CGLExecuteHelperBase +{ +public: + inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } + + inline operator Result() const { return m_Result; } + inline operator char*() const { return (char*)m_Result; } + + FunctionType m_pFn; + + Result m_Result; +}; + +template < class FunctionType> +class CGLExecuteHelper : public CGLExecuteHelperBase +{ +public: + inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } + + FunctionType m_pFn; +}; +#endif + +template < class FunctionType, typename Result > +class CDynamicFunctionOpenGLBase +{ +public: + // Construct with a NULL function pointer. You must manually call + // Lookup() before you can call a dynamic function through this interface. + CDynamicFunctionOpenGLBase() : m_pFn(NULL) {} + + // Construct and do a lookup right away. You will need to make sure that + // the lookup actually succeeded, as the gl library might have failed to load + // or (fn) might not exist in it. + CDynamicFunctionOpenGLBase(const char *fn, FunctionType fallback=NULL) : m_pFn(NULL) + { + Lookup(fn, fallback); + } + + // Construct and do a lookup right away. See comments in Lookup() about what (okay) does. + CDynamicFunctionOpenGLBase(const char *fn, bool &okay, FunctionType fallback=NULL) : m_pFn(NULL) + { + Lookup(fn, okay, fallback); + } + + // Load library if necessary, look up symbol. Returns true and sets + // m_pFn on successful lookup, returns false otherwise. If the + // function pointer is already looked up, this return true immediately. + // Use Reset() first if you want to look up the symbol again. + // This function will return false immediately unless (okay) is true. + // This allows you to chain lookups like this: + // bool okay = true; + // x.Lookup(lib, "x", okay); + // y.Lookup(lib, "y", okay); + // z.Lookup(lib, "z", okay); + // if (okay) { printf("All functions were loaded successfully!\n"); } + // If you supply a fallback, it'll be used if the lookup fails (and if + // non-NULL, means this will always return (okay)). + bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) + { + if (!okay) + return false; + else if (this->m_pFn == NULL) + { + this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, false, (void *) fallback); + this->SetFuncName( fn ); + } + return okay; + } + + // Load library if necessary, look up symbol. Returns true and sets + // m_pFn on successful lookup, returns false otherwise. If the + // function pointer is already looked up, this return true immediately. + // Use Reset() first if you want to look up the symbol again. + // This function will return false immediately unless (okay) is true. + // If you supply a fallback, it'll be used if the lookup fails (and if + // non-NULL, means this will always return true). + bool Lookup(const char *fn, FunctionType fallback=NULL) + { + bool okay = true; + return Lookup(fn, okay, fallback); + } + + // Invalidates the current lookup. Makes the function pointer NULL. You + // will need to call Lookup() before you can call a dynamic function + // through this interface again. + void Reset() { m_pFn = NULL; } + + // Force this to be a specific function pointer. + void Force(FunctionType ptr) { m_pFn = ptr; } + + // Retrieve the actual function pointer. + FunctionType Pointer() const { return m_pFn; } + +#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME + #if GL_TELEMETRY_ZONES + #define GL_FUNC_NAME m_szName + #else + #define GL_FUNC_NAME "" + #endif + + inline CGLExecuteHelper operator() () const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME ); } + + template + inline CGLExecuteHelper operator() (T a) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a); } + + template + inline CGLExecuteHelper operator() (T a, U b) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c ) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i, C j) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i, j); } +#else + operator FunctionType() const { return m_pFn; } +#endif + + // Can be used to verify that we have an actual function looked up and + // ready to call: if (!MyDynFunc) { printf("Function not found!\n"); } + operator bool () const { return m_pFn != NULL; } + bool operator !() const { return m_pFn == NULL; } + +protected: + FunctionType m_pFn; + +#if GL_TELEMETRY_ZONES + char m_szName[32]; + inline void SetFuncName(const char *pFn) { V_strncpy( m_szName, pFn, sizeof( m_szName ) ); } +#else + inline void SetFuncName(const char *pFn) { (void)pFn; } +#endif +}; + +// This works a lot like CDynamicFunctionMustInit, but we use SDL_GL_GetProcAddress(). +template < const bool bRequired, class FunctionType, typename Result > +class CDynamicFunctionOpenGL : public CDynamicFunctionOpenGLBase< FunctionType, Result > +{ +private: // forbid default constructor. + CDynamicFunctionOpenGL() {} + +public: + CDynamicFunctionOpenGL(const char *fn, FunctionType fallback=NULL) + { + bool okay = true; + Lookup(fn, okay, fallback); + this->SetFuncName( fn ); + } + + CDynamicFunctionOpenGL(const char *fn, bool &okay, FunctionType fallback=NULL) + { + Lookup(fn, okay, fallback); + this->SetFuncName( fn ); + } + + // Please note this is not virtual. + // !!! FIXME: we might want to fall back and try "EXT" or "ARB" versions in some case. + bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) + { + if (this->m_pFn == NULL) + { + this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, bRequired, (void *) fallback); + this->SetFuncName( fn ); + } + return okay; + } +}; + + +// This provides all the entry points for a given OpenGL context. +// ENTRY POINTS ARE ONLY VALID FOR THE CONTEXT THAT WAS CURRENT WHEN +// YOU LOOKED THEM UP. 99% of the time, this is not a problem, but +// that 1% is really hard to track down. Always access the GL +// through this class! +class COpenGLEntryPoints +{ +public: + // The GL context you are looking up entry points for must be current when you construct this object! + COpenGLEntryPoints(); + + uint64 m_nTotalGLCycles, m_nTotalGLCalls; + + int m_nOpenGLVersionMajor; // if GL_VERSION is 2.1.0, this will be set to 2. + int m_nOpenGLVersionMinor; // if GL_VERSION is 2.1.0, this will be set to 1. + int m_nOpenGLVersionPatch; // if GL_VERSION is 2.1.0, this will be set to 0. + bool m_bHave_OpenGL; + + #define GL_EXT(x,glmajor,glminor) bool m_bHave_##x; + #define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn; + #define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn; + #include "togl/glfuncs.inl" + #undef GL_FUNC_VOID + #undef GL_FUNC + #undef GL_EXT +}; + +// This will be set to the current OpenGL context's entry points. +extern COpenGLEntryPoints *gGL; +typedef void * (*GL_GetProcAddressCallbackFunc_t)(const char *, bool &, const bool, void *); + +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); + DLL_EXPORT void ToGLDisconnectLibraries(); + DLL_EXPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); +#else + DLL_IMPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); + DLL_IMPORT void ToGLDisconnectLibraries(); + DLL_IMPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); +#endif + +#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME +inline void CGLExecuteHelperBase::StartCall(const char *pName) +{ + (void)pName; + +#if GL_TELEMETRY_ZONES + tmEnter( TELEMETRY_LEVEL3, TMZF_NONE, pName ); +#endif + +#if GL_TRACK_API_TIME + m_nStartTime = tmFastTime(); +#endif +} + +inline void CGLExecuteHelperBase::StopCall(const char *pName) +{ +#if GL_TRACK_API_TIME + uint64 nTotalCycles = tmFastTime() - m_nStartTime; +#endif + +#if GL_TELEMETRY_ZONES + tmLeave( TELEMETRY_LEVEL3 ); +#endif + +#if GL_TRACK_API_TIME + //double flMilliseconds = g_Telemetry.flRDTSCToMilliSeconds * nTotalCycles; + if (gGL) + { + gGL->m_nTotalGLCycles += nTotalCycles; + gGL->m_nTotalGLCalls++; + } +#endif +} +#endif + +#endif // DX_TO_GL_ABSTRACTION + +#endif // GLENTRYPOINTS_H diff --git a/mp/src/public/togl/osx/glfuncs.h b/mp/src/public/togl/osx/glfuncs.h new file mode 100644 index 00000000..484786c6 --- /dev/null +++ b/mp/src/public/togl/osx/glfuncs.h @@ -0,0 +1,184 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// !!! FIXME: Some of these aren't base OpenGL...pick out the extensions. +// !!! FIXME: Also, look up these -1, -1 versions numbers. +GL_FUNC(OpenGL,true,GLenum,glGetError,(void),()) +GL_FUNC_VOID(OpenGL,true,glActiveTexture,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glAlphaFunc,(GLenum a,GLclampf b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glAttachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBegin,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glBindAttribLocationARB,(GLhandleARB a,GLuint b,const GLcharARB *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glBindBufferARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindProgramARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindTexture,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBlendColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glBlendEquation,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glBlendFunc,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBufferDataARB,(GLenum a,GLsizeiptrARB b,const GLvoid *c,GLenum d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glClear,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glClearColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glClearDepth,(GLclampd a),(a)) +GL_FUNC_VOID(OpenGL,true,glClearStencil,(GLint a),(a)) +GL_FUNC_VOID(OpenGL,true,glClipPlane,(GLenum a,const GLdouble *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glColorMask,(GLboolean a,GLboolean b,GLboolean c,GLboolean d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glCompileShaderARB,(GLhandleARB a),(a)) +GL_FUNC_VOID(OpenGL,true,glCompressedTexImage2D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLint f,GLsizei g,const GLvoid *h),(a,b,c,d,e,f,g,h)) +GL_FUNC_VOID(OpenGL,true,glCompressedTexImage3D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLsizei h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC(OpenGL,true,GLhandleARB,glCreateProgramObjectARB,(void),()) +GL_FUNC(OpenGL,true,GLhandleARB,glCreateShaderObjectARB,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteBuffersARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteObjectARB,(GLhandleARB a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteProgramsARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteQueriesARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteShader,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteTextures,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDepthFunc,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDepthMask,(GLboolean a),(a)) +GL_FUNC_VOID(OpenGL,true,glDepthRange,(GLclampd a,GLclampd b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDetachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDisable,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDisableVertexAttribArray,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawArrays,(GLenum a,GLint b,GLsizei c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glDrawBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawRangeElements,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glEnable,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glEnableVertexAttribArray,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glEnd,(void),()) +GL_FUNC_VOID(OpenGL,true,glFinish,(void),()) +GL_FUNC_VOID(OpenGL,true,glFlush,(void),()) +GL_FUNC_VOID(OpenGL,true,glFrontFace,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glGenBuffersARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenProgramsARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenQueriesARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenTextures,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetBooleanv,(GLenum a,GLboolean *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetCompressedTexImage,(GLenum a,GLint b,GLvoid *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGetDoublev,(GLenum a,GLdouble *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetFloatv,(GLenum a,GLfloat *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetInfoLogARB,(GLhandleARB a,GLsizei b,GLsizei *c,GLcharARB *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glGetIntegerv,(GLenum a,GLint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetObjectParameterivARB,(GLhandleARB a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGetProgramivARB,(GLenum a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC(OpenGL,true,const GLubyte *,glGetString,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glGetTexImage,(GLenum a,GLint b,GLenum c,GLenum d,GLvoid *e),(a,b,c,d,e)) +GL_FUNC(OpenGL,true,GLint,glGetUniformLocationARB,(GLhandleARB a,const GLcharARB *b),(a,b)) +GL_FUNC(OpenGL,true,GLboolean,glIsEnabled,(GLenum a),(a)) +GL_FUNC(OpenGL,true,GLboolean,glIsTexture,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glLinkProgramARB,(GLhandleARB a),(a)) +GL_FUNC(OpenGL,true,GLvoid*,glMapBufferARB,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glOrtho,(GLdouble a,GLdouble b,GLdouble c,GLdouble d,GLdouble e,GLdouble f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glPixelStorei,(GLenum a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPolygonMode,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPolygonOffset,(GLfloat a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPopAttrib,(void),()) +GL_FUNC_VOID(OpenGL,true,glProgramStringARB,(GLenum a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glPushAttrib,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glReadBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glScissor,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glShaderSourceARB,(GLhandleARB a,GLsizei b,const GLcharARB **c,const GLint *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glStencilFunc,(GLenum a,GLint b,GLuint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glStencilMask,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glStencilOp,(GLenum a,GLenum b,GLenum c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexCoord2f,(GLfloat a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glTexImage2D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLint f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC_VOID(OpenGL,true,glTexImage3D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLenum h,GLenum i,const GLvoid *j),(a,b,c,d,e,f,g,h,i,j)) +GL_FUNC_VOID(OpenGL,true,glTexParameterfv,(GLenum a,GLenum b,const GLfloat *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexParameteri,(GLenum a,GLenum b,GLint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexSubImage2D,(GLenum a,GLint b,GLint c,GLint d,GLsizei e,GLsizei f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC_VOID(OpenGL,true,glUniform1f,(GLint a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform1i,(GLint a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform1iARB,(GLint a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform4fv,(GLint a,GLsizei b,const GLfloat *c),(a,b,c)) +GL_FUNC(OpenGL,true,GLboolean,glUnmapBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glUseProgram,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glVertex3f,(GLfloat a,GLfloat b,GLfloat c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glVertexAttribPointer,(GLuint a,GLint b,GLenum c,GLboolean d,GLsizei e,const GLvoid *f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glViewport,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glEnableClientState,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDisableClientState,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glClientActiveTexture,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glVertexPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glTexCoordPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glProgramEnvParameters4fvEXT,(GLenum a,GLuint b,GLsizei c,const GLfloat *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glColor4sv,(const GLshort *a),(a)) +GL_FUNC_VOID(OpenGL,true,glStencilOpSeparate,(GLenum a,GLenum b,GLenum c,GLenum d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glStencilFuncSeparate,(GLenum a,GLenum b,GLint c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glGetTexLevelParameteriv,(GLenum a,GLint b,GLenum c,GLint *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glColor4f,(GLfloat a,GLfloat b,GLfloat c,GLfloat d),(a,b,c,d)) +GL_EXT(GL_EXT_framebuffer_object,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindFramebufferEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindRenderbufferEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC(GL_EXT_framebuffer_object,false,GLenum,glCheckFramebufferStatusEXT,(GLenum a),(a)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteRenderbuffersEXT,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferRenderbufferEXT,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture2DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture3DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenFramebuffersEXT,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenRenderbuffersEXT,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteFramebuffersEXT,(GLsizei a,const GLuint *b),(a,b)) +GL_EXT(GL_EXT_framebuffer_blit,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_blit,false,glBlitFramebufferEXT,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) +GL_EXT(GL_EXT_framebuffer_multisample,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_multisample,false,glRenderbufferStorageMultisampleEXT,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) +GL_EXT(GL_APPLE_fence,-1,-1) +GL_FUNC(GL_APPLE_fence,false,GLboolean,glTestFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glSetFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glFinishFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glDeleteFencesAPPLE,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_APPLE_fence,false,glGenFencesAPPLE,(GLsizei a,GLuint *b),(a,b)) +GL_EXT(GL_NV_fence,-1,-1) +GL_FUNC(GL_NV_fence,false,GLboolean,glTestFenceNV,(GLuint a),(a)) +GL_FUNC_VOID(GL_NV_fence,false,glSetFenceNV,(GLuint a,GLenum b),(a,b)) +GL_FUNC_VOID(GL_NV_fence,false,glFinishFenceNV,(GLuint a),(a)) +GL_FUNC_VOID(GL_NV_fence,false,glDeleteFencesNV,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_NV_fence,false,glGenFencesNV,(GLsizei a,GLuint *b),(a,b)) +GL_EXT(GL_ARB_sync,3,2) +#ifdef HAVE_GL_ARB_SYNC +GL_FUNC_VOID(GL_ARB_sync,false,glGetSynciv,(GLsync a, GLenum b, GLsizei c, GLsizei *d, GLint *e),(a,b,c,d,e)) +GL_FUNC(GL_ARB_sync,false,GLenum,glClientWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_sync,false,glWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_sync,false,glDeleteSync,(GLsync a),(a)) +GL_FUNC(GL_ARB_sync,false,GLsync,glFenceSync,(GLenum a, GLbitfield b),(a,b)) +#endif +GL_EXT(GL_EXT_draw_buffers2,-1,-1) +GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glColorMaskIndexedEXT,(GLuint a,GLboolean b,GLboolean c,GLboolean d,GLboolean e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glEnableIndexedEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glDisableIndexedEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glGetBooleanIndexedvEXT,(GLenum a,GLuint b,GLboolean *c),(a,b,c)) +GL_EXT(GL_EXT_bindable_uniform,-1,-1) +GL_FUNC_VOID(GL_EXT_bindable_uniform,false,glUniformBufferEXT,(GLuint a,GLint b,GLuint c),(a,b,c)) +GL_EXT(GL_APPLE_flush_buffer_range,-1,-1) +GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glBufferParameteriAPPLE,(GLenum a,GLenum b,GLint c),(a,b,c)) +GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glFlushMappedBufferRangeAPPLE,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) +GL_EXT(GL_ARB_map_buffer_range,-1,-1) +GL_FUNC(GL_ARB_map_buffer_range,false,void*,glMapBufferRange,(GLenum a,GLintptr b,GLsizeiptr c,GLbitfield d),(a,b,c,d)) +GL_FUNC_VOID(GL_ARB_map_buffer_range,false,glFlushMappedBufferRange,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) +GL_EXT(GL_ARB_occlusion_query,-1,-1) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glBeginQueryARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glEndQueryARB,(GLenum a),(a)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectivARB,(GLuint a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectuivARB,(GLuint a,GLenum b,GLuint *c),(a,b,c)) +GL_EXT(GL_APPLE_texture_range,-1,-1) +GL_FUNC_VOID(GL_APPLE_texture_range,false,glTextureRangeAPPLE,(GLenum a,GLsizei b,void *c),(a,b,c)) +GL_FUNC_VOID(GL_APPLE_texture_range,false,glGetTexParameterPointervAPPLE,(GLenum a,GLenum b,void* *c),(a,b,c)) +GL_EXT(GL_APPLE_client_storage,-1,-1) +GL_EXT(GL_ARB_uniform_buffer,-1,-1) +GL_EXT(GL_ARB_vertex_array_bgra,-1,-1) +GL_EXT(GL_EXT_vertex_array_bgra,-1,-1) +GL_EXT(GL_ARB_framebuffer_object,3,0) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindFramebuffer,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindRenderbuffer,(GLenum a,GLuint b),(a,b)) +GL_FUNC(GL_ARB_framebuffer_object,false,GLenum,glCheckFramebufferStatus,(GLenum a),(a)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteRenderbuffers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferRenderbuffer,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture2D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture3D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenFramebuffers,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenRenderbuffers,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteFramebuffers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBlitFramebuffer,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glRenderbufferStorageMultisample,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) +GL_EXT(GL_GREMEDY_string_marker,-1,-1) +GL_FUNC_VOID(GL_GREMEDY_string_marker,false,glStringMarkerGREMEDY,(GLsizei a,const void *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPushClientAttrib,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glPopClientAttrib,(void),()) + diff --git a/mp/src/public/togl/osx/glmdebug.h b/mp/src/public/togl/osx/glmdebug.h new file mode 100644 index 00000000..5981677d --- /dev/null +++ b/mp/src/public/togl/osx/glmdebug.h @@ -0,0 +1,157 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef GLMDEBUG_H +#define GLMDEBUG_H + +#include "tier0/platform.h" +#include + +// include this anywhere you need to be able to compile-out code related specifically to GLM debugging. + +// we expect DEBUG to be driven by the build system so you can include this header anywhere. +// when we come out, GLMDEBUG will be defined to a value - 0, 1, or 2 +// 0 means no GLM debugging is possible +// 1 means it's possible and resulted from being a debug build +// 2 means it's possible and resulted from being manually forced on for a release build + +#ifdef POSIX + #ifndef GLMDEBUG + #ifdef DEBUG + #define GLMDEBUG 1 // normally 1 here, testing + #else + // #define GLMDEBUG 2 // don't check this in enabled.. + #endif + + #ifndef GLMDEBUG + #define GLMDEBUG 0 + #endif + #endif +#else + #ifndef GLMDEBUG + #define GLMDEBUG 0 + #endif +#endif + + +//=============================================================================== +// debug channels + +enum EGLMDebugChannel +{ + ePrintf, + eDebugger, + eGLProfiler +}; + +#if GLMDEBUG + // make all these prototypes disappear in non GLMDEBUG + void GLMDebugInitialize( bool forceReinit=false ); + + bool GLMDetectOGLP( void ); + bool GLMDetectGDB( void ); + uint GLMDetectAvailableChannels( void ); + + uint GLMDebugChannelMask( uint *newValue = NULL ); + // note that GDB and OGLP can both come and go during run - forceCheck will allow that to be detected. + // mask returned is in form of 1< < + eComment, // 3 one off messages --- + eMatrixData, // 4 matrix data -M- + eShaderData, // 5 shader data (params) -S- + eFrameBufData, // 6 FBO data (attachments) -F- + eDXStuff, // 7 dxabstract spew -X- + eAllocations, // 8 tracking allocs and frees -A- + eSlowness, // 9 slow things happening (srgb flips..) -Z- + eDefaultFlavor, // not specified (no marker) + eFlavorCount +}; +uint GLMDebugFlavorMask( uint *newValue = NULL ); + +// make all these prototypes disappear in non GLMDEBUG +#if GLMDEBUG + // these are unconditional outputs, they don't interrogate the string + void GLMStringOut( const char *string ); + void GLMStringOutIndented( const char *string, int indentColumns ); + + #ifdef TOGL_DLL_EXPORT + // these will look at the string to guess its flavor: <, >, ---, -M-, -S- + DLL_EXPORT void GLMPrintfVA( const char *fmt, va_list vargs ); + DLL_EXPORT void GLMPrintf( const char *fmt, ... ); + #else + DLL_IMPORT void GLMPrintfVA( const char *fmt, va_list vargs ); + DLL_IMPORT void GLMPrintf( const char *fmt, ... ); + #endif + + // these take an explicit flavor with a default value + void GLMPrintStr( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor ); + + #define GLMPRINTTEXT_NUMBEREDLINES 0x80000000 + void GLMPrintText( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor, uint options=0 ); // indent each newline + + int GLMIncIndent( int indentDelta ); + int GLMGetIndent( void ); + void GLMSetIndent( int indent ); + +#endif + +// helpful macro if you are in a position to call GLM functions directly (i.e. you live in materialsystem / shaderapidx9) +#if GLMDEBUG + #define GLMPRINTF(args) GLMPrintf args + #define GLMPRINTSTR(args) GLMPrintStr args + #define GLMPRINTTEXT(args) GLMPrintText args +#else + #define GLMPRINTF(args) + #define GLMPRINTSTR(args) + #define GLMPRINTTEXT(args) +#endif + + +//=============================================================================== +// knob twiddling +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value + DLL_EXPORT float GLMKnobToggle( char *knobname ); +#else + DLL_IMPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value + DLL_IMPORT float GLMKnobToggle( char *knobname ); +#endif + +//=============================================================================== +// other stuff + +#if GLMDEBUG +void GLMTriggerDebuggerBreak(); +inline void GLMDebugger( void ) +{ + if (GLMDebugChannelMask() & (1< +#include +#include +#include +#include +#include + +typedef uint32_t CGDirectDisplayID; +typedef uint32_t CGOpenGLDisplayMask; +typedef double CGRefreshRate; + +//#include +#elif defined(LINUX) +#include "tier0/platform.h" +#include +#include +#else +#error +#endif + +typedef void _PseudoNSGLContext; // aka NSOpenGLContext +typedef _PseudoNSGLContext *PseudoNSGLContextPtr; + +struct GLMDisplayModeInfoFields +{ + uint m_modePixelWidth; + uint m_modePixelHeight; + uint m_modeRefreshHz; + // are we even going to talk about bit depth... not yet +}; + +struct GLMDisplayInfoFields +{ +#ifdef OSX + CGDirectDisplayID m_cgDisplayID; + CGOpenGLDisplayMask m_glDisplayMask; // result of CGDisplayIDToOpenGLDisplayMask on the cg_displayID. +#endif + uint m_displayPixelWidth; + uint m_displayPixelHeight; +}; + +struct GLMRendererInfoFields +{ + /*properties of interest and their desired values. + + kCGLRPFullScreen = 54, true + kCGLRPAccelerated = 73, true + kCGLRPWindow = 80, true + + kCGLRPRendererID = 70, informational + kCGLRPDisplayMask = 84, informational + kCGLRPBufferModes = 100, informational + kCGLRPColorModes = 103, informational + kCGLRPAccumModes = 104, informational + kCGLRPDepthModes = 105, informational + kCGLRPStencilModes = 106, informational + kCGLRPMaxAuxBuffers = 107, informational + kCGLRPMaxSampleBuffers = 108, informational + kCGLRPMaxSamples = 109, informational + kCGLRPSampleModes = 110, informational + kCGLRPSampleAlpha = 111, informational + kCGLRPVideoMemory = 120, informational + kCGLRPTextureMemory = 121, informational + kCGLRPRendererCount = 128 number of renderers in the CGLRendererInfoObj under examination + + kCGLRPOffScreen = 53, D/C + kCGLRPRobust = 75, FALSE or D/C - aka we're asking for no-fallback + kCGLRPBackingStore = 76, D/C + kCGLRPMPSafe = 78, D/C + kCGLRPMultiScreen = 81, D/C + kCGLRPCompliant = 83, D/C + */ + + + //--------------------------- info we have from CGL renderer queries, IOKit, Gestalt + //--------------------------- these are set up in the displayDB by CocoaMgr + GLint m_fullscreen; + GLint m_accelerated; + GLint m_windowed; + + GLint m_rendererID; + GLint m_displayMask; + GLint m_bufferModes; + GLint m_colorModes; + GLint m_accumModes; + GLint m_depthModes; + GLint m_stencilModes; + + GLint m_maxAuxBuffers; + GLint m_maxSampleBuffers; + GLint m_maxSamples; + GLint m_sampleModes; + GLint m_sampleAlpha; + + GLint m_vidMemory; + GLint m_texMemory; + + uint m_pciVendorID; + uint m_pciDeviceID; + char m_pciModelString[64]; + char m_driverInfoString[64]; + + //--------------------------- OS version related - set up by CocoaMgr + + // OS version found + uint m_osComboVersion; // 0x00XXYYZZ : XX major, YY minor, ZZ minor minor : 10.6.3 --> 0x000A0603. 10.5.8 --> 0x000A0508. + + //--------------------------- shorthands - also set up by CocoaMgr - driven by vendorid / deviceid + + bool m_ati; + bool m_atiR5xx; + bool m_atiR6xx; + bool m_atiR7xx; + bool m_atiR8xx; + bool m_atiNewer; + + bool m_intel; + bool m_intel95x; + bool m_intel3100; + bool m_intelNewer; + + bool m_nv; + bool m_nvG7x; + bool m_nvG8x; + bool m_nvNewer; + + //--------------------------- context query results - left blank in the display DB - but valid in a GLMContext (call ctx->Caps() to get a const ref) + + // booleans + bool m_hasGammaWrites; // aka glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT) / glEnable(GL_FRAMEBUFFER_SRGB_EXT) + bool m_hasMixedAttachmentSizes; // aka ARB_fbo in 10.6.3 - test for min OS vers, then exported ext string + bool m_hasBGRA; // aka GL_BGRA vertex attribs in 10.6.3 - - test for min OS vers, then exported ext string + bool m_hasNewFullscreenMode; // aka 10.6.x "big window" fullscreen mode + bool m_hasNativeClipVertexMode; // aka GLSL gl_ClipVertex does not fall back to SW- OS version and folklore-based + bool m_hasOcclusionQuery; // occlusion query: do you speak it ?! + bool m_hasFramebufferBlit; // framebuffer blit: know what I'm sayin?! + bool m_hasPerfPackage1; // means new MTGL, fast OQ, fast uniform upload, NV can resolve flipped (late summer 2010 post 10.6.4 update) + + // counts + int m_maxAniso; // aniso limit - context query + + // other exts + bool m_hasBindableUniforms; + bool m_hasUniformBuffers; + + // runtime options that aren't negotiable once set + bool m_hasDualShaders; // must supply CLI arg "-glmdualshaders" or we go GLSL only + + //--------------------------- " can'ts " - specific problems that need to be worked around + + bool m_cantBlitReliably; // Intel chipsets have problems blitting sRGB sometimes + bool m_cantAttachSRGB; // NV G8x on 10.5.8 can't have srgb tex on FBO color - separate issue from hasGammaWrites + bool m_cantResolveFlipped; // happens on NV in 10.6.4 and prior - console variable "gl_can_resolve_flipped" can overrule + bool m_cantResolveScaled; // happens everywhere per GL spec but may be relaxed some day - console variable "gl_can_resolve_scaled" can overrule + bool m_costlyGammaFlips; // this means that sRGB sampling state affects shader code gen, resulting in state-dependent code regen + + + //--------------------------- " bads " - known bad drivers + bool m_badDriver1064NV; // this is the bad NVIDIA driver on 10.6.4 - stutter, tex corruption, black screen issues +}; + + + +#endif diff --git a/mp/src/public/togl/osx/glmdisplaydb.h b/mp/src/public/togl/osx/glmdisplaydb.h new file mode 100644 index 00000000..4588aff3 --- /dev/null +++ b/mp/src/public/togl/osx/glmdisplaydb.h @@ -0,0 +1,115 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef GLMDISPLAYDB_H +#define GLMDISPLAYDB_H + +#include "tier1/utlvector.h" + +//=============================================================================== + +// modes, displays, and renderers +// think of renderers as being at the top of a tree. +// each renderer has displays hanging off of it. +// each display has modes hanging off of it. +// the tree is populated on demand and then queried as needed. + +//=============================================================================== + +// GLMDisplayModeInfoFields is in glmdisplay.h + +class GLMDisplayMode +{ +public: + GLMDisplayModeInfoFields m_info; + + GLMDisplayMode( uint width, uint height, uint refreshHz ); + GLMDisplayMode() { }; + ~GLMDisplayMode( void ); + + + void Init( uint width, uint height, uint refreshHz ); + void Dump( int which ); +}; + +//=============================================================================== + +// GLMDisplayInfoFields is in glmdisplay.h + +class GLMDisplayInfo +{ +public: + GLMDisplayInfoFields m_info; + CUtlVector< GLMDisplayMode* > *m_modes; // starts out NULL, set by PopulateModes + + GLMDisplayInfo( void ); + ~GLMDisplayInfo( void ); + + void PopulateModes( void ); + + void Dump( int which ); +}; + +//=============================================================================== + +// GLMRendererInfoFields is in glmdisplay.h + +class GLMRendererInfo +{ +public: + GLMRendererInfoFields m_info; + GLMDisplayInfo *m_display; // starts out NULL, set by PopulateDisplays + + GLMRendererInfo ( GLMRendererInfoFields *info ); + ~GLMRendererInfo ( void ); + + void PopulateDisplays(); + void Dump( int which ); +}; + +//=============================================================================== + +// this is just a tuple describing fake adapters which are really renderer/display pairings. +// dxabstract bridges the gap between the d3d adapter-centric world and the GL renderer+display world. +// this makes it straightforward to handle cases like two video cards with two displays on one, and one on the other - +// you get three fake adapters which represent each useful screen. + +// the constraint that dxa will have to follow though, is that if the user wants to change their +// display selection for full screen, they would only be able to pick on that has the same underlying renderer. +// can't change fakeAdapter from one to another with different GL renderer under it. Screen hop but no card hop. + +struct GLMFakeAdapter +{ + int m_rendererIndex; + int m_displayIndex; +}; + +class GLMDisplayDB +{ +public: + CUtlVector< GLMRendererInfo* > *m_renderers; // starts out NULL, set by PopulateRenderers + + CUtlVector< GLMFakeAdapter > m_fakeAdapters; + + GLMDisplayDB ( void ); + ~GLMDisplayDB ( void ); + + virtual void PopulateRenderers( void ); + virtual void PopulateFakeAdapters( uint realRendererIndex ); // fake adapters = one real adapter times however many displays are on it + virtual void Populate( void ); + + // The info-get functions return false on success. + virtual int GetFakeAdapterCount( void ); + virtual bool GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut ); + + virtual int GetRendererCount( void ); + virtual bool GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut ); + + virtual int GetDisplayCount( int rendererIndex ); + virtual bool GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut ); + + virtual int GetModeCount( int rendererIndex, int displayIndex ); + virtual bool GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut ); + + virtual void Dump( void ); +}; + +#endif // GLMDISPLAYDB_H diff --git a/mp/src/public/togl/osx/glmgr.h b/mp/src/public/togl/osx/glmgr.h new file mode 100644 index 00000000..1e951ca9 --- /dev/null +++ b/mp/src/public/togl/osx/glmgr.h @@ -0,0 +1,1088 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgr.h +// singleton class, common basis for managing GL contexts +// responsible for tracking adapters and contexts +// +//=============================================================================== + +#ifndef GLMGR_H +#define GLMGR_H + +#pragma once + +#undef HAVE_GL_ARB_SYNC +#ifdef LINUX +#define HAVE_GL_ARB_SYNC 1 +#endif + +#include "glentrypoints.h" +#include "glmdebug.h" +#include "glmdisplay.h" +#include "glmgrext.h" +#include "glmgrbasics.h" +#include "cglmtex.h" +#include "cglmfbo.h" +#include "cglmprogram.h" +#include "cglmbuffer.h" +#include "cglmquery.h" + +#include "tier0/vprof_telemetry.h" +#include "materialsystem/ishader.h" +#include "dxabstract_types.h" + + +#ifdef LINUX +#define Debugger DebuggerBreak +#undef CurrentTime + +// prevent some conflicts in SDL headers... +#undef M_PI +#include +#ifndef _STDINT_H_ +#define _STDINT_H_ 1 +#endif + +#include "SDL/SDL.h" +#endif + +//=============================================================================== +// glue to call out to Obj-C land (these are in glmgrcocoa.mm) +#ifdef OSX +PseudoNSGLContextPtr GetCurrentNSGLContext( ); +CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx ); +#endif + +#include "tier0/dynfunction.h" + +//=============================================================================== + +// parrot the D3D present parameters, more or less... "adapter" translates into "active display index" per the m_activeDisplayCount below. +class GLMDisplayParams +{ + public: + + // presumption, these indices are in sync with the current display DB that GLMgr has handy + //int m_rendererIndex; // index of renderer (-1 if root context) + //int m_displayIndex; // index of display in renderer - for FS + //int m_modeIndex; // index of mode in display - for FS + + void *m_focusWindow; // (VD3DHWND aka WindowRef) - what window does this context display into + + bool m_fsEnable; // fullscreen on or not + bool m_vsyncEnable; // vsync on or not + + // height and width have to match the display mode info if full screen. + + uint m_backBufferWidth; // pixel width (aka screen h-resolution if full screen) + uint m_backBufferHeight; // pixel height (aka screen v-resolution if full screen) + D3DFORMAT m_backBufferFormat; // pixel format + uint m_multiSampleCount; // 0 means no MSAA, 2 means 2x MSAA, etc + // uint m_multiSampleQuality; // no MSAA quality control yet + + bool m_enableAutoDepthStencil; // generally set to 'TRUE' per CShaderDeviceDx8::SetPresentParameters + D3DFORMAT m_autoDepthStencilFormat; + + uint m_fsRefreshHz; // if full screen, this refresh rate (likely 0 for LCD's) + + //uint m_rootRendererID; // only used if m_rendererIndex is -1. + //uint m_rootDisplayMask; // only used if m_rendererIndex is -1. + + bool m_mtgl; // enable multi threaded GL driver +}; + +//=============================================================================== + +class GLMgr +{ +public: + + //=========================================================================== + // class methods - singleton + static void NewGLMgr( void ); // instantiate singleton.. + static GLMgr *aGLMgr( void ); // return singleton.. + static void DelGLMgr( void ); // tear down singleton.. + + //=========================================================================== + // plain methods + + #if 0 // turned all these off while new approach is coded + void RefreshDisplayDB( void ); // blow away old display DB, make a new one + GLMDisplayDB *GetDisplayDB( void ); // get a ptr to the one GLMgr keeps. only valid til next refresh. + + // eligible renderers will be ranked by desirability starting at index 0 within the db + // within each renderer, eligible displays will be ranked some kind of desirability (area? dist from menu bar?) + // within each display, eligible modes will be ranked by descending areas + + // calls supplying indices are implicitly making reference to the current DB + bool CaptureDisplay( int rendIndex, int displayIndex, bool captureAll ); // capture one display or all displays + void ReleaseDisplays( void ); // release all captures + + int GetDisplayMode( int rendIndex, int displayIndex ); // retrieve current display res (returns modeIndex) + void SetDisplayMode( GLMDisplayParams *params ); // set the display res (only useful for FS) + #endif + + GLMContext *NewContext( GLMDisplayParams *params ); // this will have to change + void DelContext( GLMContext *context ); + + // with usage of CGLMacro.h we could dispense with the "current context" thing + // and just declare a member variable of GLMContext, allowing each glXXX call to be routed directly + // to the correct context + void SetCurrentContext( GLMContext *context ); // make current in calling thread only + GLMContext *GetCurrentContext( void ); + +protected: + friend class GLMContext; + + GLMgr(); + ~GLMgr(); +}; + + +//===========================================================================// + +// helper function to do enable or disable in one step +inline void glSetEnable( GLenum which, bool enable ) +{ + if (enable) + gGL->glEnable(which); + else + gGL->glDisable(which); +} + +// helper function for int vs enum clarity +inline void glGetEnumv( GLenum which, GLenum *dst ) +{ + gGL->glGetIntegerv( which, (int*)dst ); +} + +//===========================================================================// +// +// types to support the GLMContext +// +//===========================================================================// + +// Each state set/get path we are providing caching for, needs its own struct and a comparison operator. +// we also provide an enum of how many such types there are, handy for building dirty masks etc. + +// shorthand macros +#define EQ(fff) ( (src.fff) == (fff) ) + +//rasterizer +struct GLAlphaTestEnable_t { GLint enable; bool operator==(const GLAlphaTestEnable_t& src) const { return EQ(enable); } }; +struct GLAlphaTestFunc_t { GLenum func; GLclampf ref; bool operator==(const GLAlphaTestFunc_t& src) const { return EQ(func) && EQ(ref); } }; +struct GLCullFaceEnable_t { GLint enable; bool operator==(const GLCullFaceEnable_t& src) const { return EQ(enable); } }; +struct GLCullFrontFace_t { GLenum value; bool operator==(const GLCullFrontFace_t& src) const { return EQ(value); } }; +struct GLPolygonMode_t { GLenum values[2]; bool operator==(const GLPolygonMode_t& src) const { return EQ(values[0]) && EQ(values[1]); } }; +struct GLDepthBias_t { GLfloat factor; GLfloat units; bool operator==(const GLDepthBias_t& src) const { return EQ(factor) && EQ(units); } }; +struct GLScissorEnable_t { GLint enable; bool operator==(const GLScissorEnable_t& src) const { return EQ(enable); } }; +struct GLScissorBox_t { GLint x,y; GLsizei width, height; bool operator==(const GLScissorBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; +struct GLAlphaToCoverageEnable_t{ GLint enable; bool operator==(const GLAlphaToCoverageEnable_t& src) const { return EQ(enable); } }; +struct GLViewportBox_t { GLint x,y; GLsizei width, height; bool operator==(const GLViewportBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; +struct GLViewportDepthRange_t { GLdouble near,far; bool operator==(const GLViewportDepthRange_t& src) const { return EQ(near) && EQ(far); } }; +struct GLClipPlaneEnable_t { GLint enable; bool operator==(const GLClipPlaneEnable_t& src) const { return EQ(enable); } }; +struct GLClipPlaneEquation_t { GLfloat x,y,z,w; bool operator==(const GLClipPlaneEquation_t& src) const { return EQ(x) && EQ(y) && EQ(z) && EQ(w); } }; + +//blend +struct GLColorMaskSingle_t { char r,g,b,a; bool operator==(const GLColorMaskSingle_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLColorMaskMultiple_t { char r,g,b,a; bool operator==(const GLColorMaskMultiple_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLBlendEnable_t { GLint enable; bool operator==(const GLBlendEnable_t& src) const { return EQ(enable); } }; +struct GLBlendFactor_t { GLenum srcfactor,dstfactor; bool operator==(const GLBlendFactor_t& src) const { return EQ(srcfactor) && EQ(dstfactor); } }; +struct GLBlendEquation_t { GLenum equation; bool operator==(const GLBlendEquation_t& src) const { return EQ(equation); } }; +struct GLBlendColor_t { GLfloat r,g,b,a; bool operator==(const GLBlendColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLBlendEnableSRGB_t { GLint enable; bool operator==(const GLBlendEnableSRGB_t& src) const { return EQ(enable); } }; + +//depth +struct GLDepthTestEnable_t { GLint enable; bool operator==(const GLDepthTestEnable_t& src) const { return EQ(enable); } }; +struct GLDepthFunc_t { GLenum func; bool operator==(const GLDepthFunc_t& src) const { return EQ(func); } }; +struct GLDepthMask_t { char mask; bool operator==(const GLDepthMask_t& src) const { return EQ(mask); } }; + +//stencil +struct GLStencilTestEnable_t { GLint enable; bool operator==(const GLStencilTestEnable_t& src) const { return EQ(enable); } }; +struct GLStencilFunc_t { GLenum frontfunc, backfunc; GLint ref; GLuint mask; bool operator==(const GLStencilFunc_t& src) const { return EQ(frontfunc) && EQ(backfunc) && EQ(ref) && EQ(mask); } }; +struct GLStencilOp_t { GLenum sfail; GLenum dpfail; GLenum dppass; bool operator==(const GLStencilOp_t& src) const { return EQ(sfail) && EQ(dpfail) && EQ(dppass); } }; +struct GLStencilWriteMask_t { GLint mask; bool operator==(const GLStencilWriteMask_t& src) const { return EQ(mask); } }; + +//clearing +struct GLClearColor_t { GLfloat r,g,b,a; bool operator==(const GLClearColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLClearDepth_t { GLdouble d; bool operator==(const GLClearDepth_t& src) const { return EQ(d); } }; +struct GLClearStencil_t { GLint s; bool operator==(const GLClearStencil_t& src) const { return EQ(s); } }; + +#undef EQ + +enum EGLMStateBlockType +{ + kGLAlphaTestEnable, + kGLAlphaTestFunc, + + kGLCullFaceEnable, + kGLCullFrontFace, + + kGLPolygonMode, + + kGLDepthBias, + + kGLScissorEnable, + kGLScissorBox, + + kGLViewportBox, + kGLViewportDepthRange, + + kGLClipPlaneEnable, + kGLClipPlaneEquation, + + kGLColorMaskSingle, + kGLColorMaskMultiple, + + kGLBlendEnable, + kGLBlendFactor, + kGLBlendEquation, + kGLBlendColor, + kGLBlendEnableSRGB, + + kGLDepthTestEnable, + kGLDepthFunc, + kGLDepthMask, + + kGLStencilTestEnable, + kGLStencilFunc, + kGLStencilOp, + kGLStencilWriteMask, + + kGLClearColor, + kGLClearDepth, + kGLClearStencil, + + kGLAlphaToCoverageEnable, + + kGLMStateBlockLimit +}; + +//===========================================================================// + +// templated functions representing GL R/W bottlenecks +// one set of set/get/getdefault is instantiated for each of the GL*** types above. + +// use these from the non array state objects +template void GLContextSet( T *src ); +template void GLContextGet( T *dst ); +template void GLContextGetDefault( T *dst ); + +// use these from the array state objects +template void GLContextSetIndexed( T *src, int index ); +template void GLContextGetIndexed( T *dst, int index ); +template void GLContextGetDefaultIndexed( T *dst, int index ); + +//===========================================================================// + +// caching state object template. One of these is instantiated in the context per unique struct type above +template class GLState +{ + public: + + GLState() + { + dirty = false; + memset( &data, 0, sizeof(data) ); + }; + + // write: client src into cache + // common case is both false. dirty is calculated, context write is deferred. + void Write( T *src, bool noCompare=false, bool noDefer=false ) + { + if (noCompare) + { + dirty = true; + } + else + { + // only == is implemented, so test for equal and negate + // note, you only set dirty if mismatch, you never clear it until flush + if ( !(data == *src) ) + { + dirty = true; + } + } + + data = *src; + + if (noDefer) + { + Flush( true ); // dirty becomes false + } + }; + + // write cache->context if dirty or forced. + void Flush( bool noDefer=false ) + { + if (dirty || noDefer) + { + GLContextSet( &data ); + GLMCheckError(); + // good place for some error checking here + dirty = false; + } + }; + + // default: write default value to cache, optionally write through + void Default( bool noDefer=false ) + { + GLContextGetDefault( &data ); // read default values directly to our cache copy + dirty = true; + Flush(noDefer); + }; + + // read: sel = 0 for cache, 1 for context + void Read( T *dst, int sel ) + { + if (sel==0) + { + *dst = data; + } + else + { + GLContextGet( dst ); + GLMCheckError(); + } + }; + + // check: verify that context equals cache, return true if mismatched or if illegal values seen + bool Check ( void ) + { + T temp; + bool result; + + GLContextGet( &temp ); + GLMCheckError(); + result = !(temp == data); + return result; + }; + + protected: + T data; + bool dirty; +}; + +// caching state object template - with multiple values behind it that are indexed +template class GLStateArray +{ + public: + + GLStateArray() + { + memset( &dirty, 0, sizeof(dirty) ); + memset( &data, 0, sizeof(data) ); + }; + + // write: client src into cache + // common case is both false. dirty is calculated, context write is deferred. + void WriteIndex( T *src, int index, bool noCompare=false, bool noDefer=false ) + { + if (noCompare) + { + dirty[index] = true; + } + else + { + // only == is implemented, so test for equal and negate + // note, you only set dirty if mismatch, you never clear it until flush + if (! (data[index] == *src) ) + { + dirty[index] = true; + } + } + + data[index] = *src; + + if (noDefer) + { + FlushIndex( index, true ); // dirty becomes false + } + }; + + // write cache->context if dirty or forced. + void FlushIndex( int index, bool noDefer=false ) + { + if (dirty[index] || noDefer) + { + GLContextSetIndexed( &data[index], index ); + GLMCheckError(); + dirty[index] = false; + } + }; + + // write all slots in the array + void Flush( bool noDefer=false ) + { + for( int i=0; i m_AlphaTestEnable; + + GLState m_AlphaTestFunc; + + GLState m_CullFaceEnable; + GLState m_CullFrontFace; + GLState m_PolygonMode; + + GLState m_DepthBias; + + GLStateArray m_ClipPlaneEnable; + GLStateArray m_ClipPlaneEquation; // dxabstract puts them directly into param slot 253(0) and 254(1) + + GLState m_ScissorEnable; + GLState m_ScissorBox; + + GLState m_AlphaToCoverageEnable; + + GLState m_ViewportBox; + GLState m_ViewportDepthRange; + + GLState m_ColorMaskSingle; + GLStateArray m_ColorMaskMultiple; // need an official constant for the color buffers limit + + GLState m_BlendEnable; + GLState m_BlendFactor; + GLState m_BlendEquation; + GLState m_BlendColor; + GLState m_BlendEnableSRGB; // write to this one to transmit intent to write SRGB encoded pixels to drawing FB + bool m_FakeBlendEnableSRGB; // writes to above will be shunted here if fake SRGB is in effect. + + GLState m_DepthTestEnable; + GLState m_DepthFunc; + GLState m_DepthMask; + + GLState m_StencilTestEnable; // global stencil test enable + GLState m_StencilFunc; // holds front and back stencil funcs + GLStateArray m_StencilOp; // indexed: 0=front 1=back + GLState m_StencilWriteMask; + + GLState m_ClearColor; + GLState m_ClearDepth; + GLState m_ClearStencil; + + // texture bindings and sampler setup + int m_activeTexture; // mirror for glActiveTexture + GLMTexSampler m_samplers[GLM_SAMPLER_COUNT]; + + // texture lock tracking - CGLMTex objects share usage of this + CUtlVector< GLMTexLockDesc > m_texLocks; + + // render target binding - check before draw + // similar to tex sampler mechanism, we track "bound" from "chosen for drawing" separately, + // so binding for creation/setup need not disrupt any notion of what will be used at draw time + + CGLMFBO *m_boundDrawFBO; // FBO on GL_DRAW_FRAMEBUFFER bind point + CGLMFBO *m_boundReadFBO; // FBO on GL_READ_FRAMEBUFFER bind point + // ^ both are set if you bind to GL_FRAMEBUFFER_EXT + + CGLMFBO *m_drawingFBO; // what FBO should be bound at draw time (to both read/draw bp's). + + CGLMFBO *m_blitReadFBO; + CGLMFBO *m_blitDrawFBO; // scratch FBO's for framebuffer blit + + CGLMFBO *m_scratchFBO[ kGLMScratchFBOCount ]; // general purpose FBO's for internal use + + CUtlVector< CGLMFBO* > m_fboTable; // each live FBO goes in the table + + // program bindings + EGLMProgramLang m_drawingLangAtFrameStart; // selector for start of frame (spills into m_drawingLang) + EGLMProgramLang m_drawingLang; // selector for which language we desire to draw with on the next batch + CGLMProgram *m_drawingProgram[ kGLMNumProgramTypes ]; + + GLMProgramParamsF m_programParamsF[ kGLMNumProgramTypes ]; + GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + GLMProgramParamsI m_programParamsI[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + EGLMParamWriteMode m_paramWriteMode; + + CGLMProgram *m_nullFragmentProgram; // write opaque black. Activate when caller asks for null FP + + CGLMProgram *m_preloadTexVertexProgram; // programs to help preload textures (dummies) + CGLMProgram *m_preload2DTexFragmentProgram; + CGLMProgram *m_preload3DTexFragmentProgram; + CGLMProgram *m_preloadCubeTexFragmentProgram; + + CGLMProgram *m_boundProgram[ kGLMNumProgramTypes ]; + + CGLMShaderPairCache *m_pairCache; // GLSL only + CGLMShaderPair *m_boundPair; // GLSL only + uint m_boundPairRevision; // GLSL only + GLhandleARB m_boundPairProgram; // GLSL only + + // buffer bindings + CGLMBuffer *m_lastKnownBufferBinds[ kGLMNumBufferTypes ]; // tracked per bind point for dupe-bind-absorb + GLMVertexAttributeDesc m_lastKnownVertexAttribs[ kGLMVertexAttributeIndexMax ]; // tracked per attrib for dupe-set-absorb + uint m_lastKnownVertexAttribMask; // tracked for dupe-enable-absorb + + CGLMBuffer *m_drawIndexBuffer; // ... ? do we need dupe tracking for index buffer setup? ? + + GLMVertexSetup m_drawVertexSetup; + + EGLMAttribWriteMode m_attribWriteMode; + + bool m_slowCheckEnable; // turn this on or no native checking is done ("-glmassertslow" or "-glmsspewslow") + bool m_slowAssertEnable; // turn this on to assert on a non-native batch "-glmassertslow" + bool m_slowSpewEnable; // turn this on to log non-native batches to stdout "-glmspewslow" + + // debug font texture + CGLMTex *m_debugFontTex; // might be NULL unless you call GenDebugFontTex + CGLMBuffer *m_debugFontIndices; // up to 1024 indices (256 chars times 4) + CGLMBuffer *m_debugFontVertices; // up to 1024 verts + + // batch/frame debugging support + int m_debugFrameIndex; // init to -1. Increment at BeginFrame + int m_debugBatchIndex; // init to -1. Increment at any draw call + +#if GLMDEBUG + // interactive (DebugHook) debug support + + // using these you can implement frame advance, batch single step, and batch rewind (let it run til next frame and hold on prev batch #) + int m_holdFrameBegin; // -1 if no hold req'd, otherwise # of frame to hold at (at beginframe time) + int m_holdFrameEnd; // -1 if no hold req'd, otherwise # of frame to hold at (at endframe time) + + int m_holdBatch,m_holdBatchFrame; // -1 if no hold, else # of batch&frame to hold at (both must be set) + // these can be expired/cleared to -1 if the frame passes without a hit + // may be desirable to re-pause in that event, as user was expecting a hold to occur + + bool m_debugDelayEnable; // allow sleep delay + uint m_debugDelay; // sleep time per hook call in microseconds (for usleep()) + + // pre-draw global toggles / options + bool m_autoClearColor,m_autoClearDepth,m_autoClearStencil; + float m_autoClearColorValues[4]; + + // debug knobs + int m_selKnobIndex; + float m_selKnobMinValue,m_selKnobMaxValue,m_selKnobIncrement; +#endif + +}; + +struct GLMTestParams +{ + GLMContext *m_ctx; + int *m_testList; // -1 termed + + bool m_glErrToDebugger; + bool m_glErrToConsole; + + bool m_intlErrToDebugger; + bool m_intlErrToConsole; + + int m_frameCount; // how many frames to test. +}; + +class GLMTester +{ + public: + + GLMTester(GLMTestParams *params); + ~GLMTester(); + + + // optionally callable by test routines to get basic drawables wired up + void StdSetup( void ); + void StdCleanup( void ); + + // callable by test routines to clear the frame or present it + void Clear( void ); + void Present( int seed ); + + // error reporting + void CheckGLError( char *comment ); // obey m_params setting for console / debugger response + void InternalError( int errcode, char *comment ); // if errcode!=0, obey m_params setting for console / debugger response + + void RunTests(); + + void RunOneTest( int testindex ); + + // test routines themselves + void Test0(); + void Test1(); + void Test2(); + void Test3(); + + GLMTestParams m_params; // copy of caller's params, do not mutate... + + // std-setup stuff + int m_drawWidth, m_drawHeight; + CGLMFBO *m_drawFBO; + CGLMTex *m_drawColorTex; + CGLMTex *m_drawDepthTex; +}; + +class CShowPixelsParams +{ +public: + GLuint m_srcTexName; + int m_width,m_height; + bool m_vsyncEnable; + bool m_fsEnable; // want receiving view to be full screen. for now, just target the main screen. extend later. + bool m_useBlit; // use FBO blit - sending context says it is available. + bool m_noBlit; // the back buffer has already been populated by the caller (perhaps via direct MSAA resolve from multisampled RT tex) + bool m_onlySyncView; // react to full/windowed state change only, do not present bits +}; + + +#define kMaxCrawlFrames 100 +#define kMaxCrawlText (kMaxCrawlFrames * 256) +class CStackCrawlParams +{ + public: + uint m_frameLimit; // input: max frames to retrieve + uint m_frameCount; // output: frames found + void *m_crawl[kMaxCrawlFrames]; // call site addresses + char *m_crawlNames[kMaxCrawlFrames]; // pointers into text following, one per decoded name + char m_crawlText[kMaxCrawlText]; +}; + +#endif diff --git a/mp/src/public/togl/osx/glmgrbasics.h b/mp/src/public/togl/osx/glmgrbasics.h new file mode 100644 index 00000000..559bc10f --- /dev/null +++ b/mp/src/public/togl/osx/glmgrbasics.h @@ -0,0 +1,299 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgrbasics.h +// types, common headers, forward declarations, utilities +// +//=============================================================================== + +#ifndef GLMBASICS_H +#define GLMBASICS_H + +#pragma once + +#ifdef OSX +#include +#include +#include +#include +#include +#include +#include +//#include +#elif defined(LINUX) +#include +#include +#else +#error +#endif + +#include "tier0/platform.h" + +#include "bitmap/imageformat.h" +#include "bitvec.h" +#include "tier1/checksum_md5.h" +#include "tier1/utlvector.h" +#include "tier1/convar.h" + +#include + +#include "dxabstract_types.h" + +// types +struct GLMRect; +typedef void *PseudoGLContextPtr; + + + // 3-d integer box (used for texture lock/unlock etc) +struct GLMRegion +{ + int xmin,xmax; + int ymin,ymax; + int zmin,zmax; +}; + +struct GLMRect // follows GL convention - if coming from the D3D rect you will need to fiddle the Y's +{ + int xmin; // left + int ymin; // bottom + int xmax; // right + int ymax; // top +}; + +// macros + +//#define GLMassert(x) assert(x) + +// forward decls +class GLMgr; // singleton +class GLMContext; // GL context +class CGLMContextTester; // testing class +class CGLMTex; +class CGLMFBO; +class CGLMProgram; +class CGLMBuffer; + + +// utilities + +typedef enum +{ + // D3D codes + eD3D_DEVTYPE, + eD3D_FORMAT, + eD3D_RTYPE, + eD3D_USAGE, + eD3D_RSTATE, // render state + eD3D_SIO, // D3D shader bytecode + eD3D_VTXDECLUSAGE, + + // CGL codes + eCGL_RENDID, + + // OpenGL error codes + eGL_ERROR, + + // OpenGL enums + eGL_ENUM, + eGL_RENDERER + +} GLMThing_t; + +const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const +const char* GLMDecodeMask( GLMThing_t type, unsigned long value ); // decode a bitmask + +void GLMStop( void ); // aka Debugger() +void GLMCheckError( bool noStop = false, bool noLog= false ); +void GLMEnableTrace( bool on ); + +// expose these in release now +// Mimic PIX events so we can decorate debug spew +void GLMBeginPIXEvent( const char *str ); +void GLMEndPIXEvent( void ); + +//=============================================================================== +// knob twiddling +float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value +float GLMKnobToggle( char *knobname ); + +//=============================================================================== +// other stuff + +// helpers for CGLSetOption - no op if no profiler +void GLMProfilerClearTrace( void ); +void GLMProfilerEnableTrace( bool enable ); + +// helpers for CGLSetParameter - no op if no profiler +void GLMProfilerDumpState( void ); + + +//=============================================================================== +// classes + +// helper class making function tracking easier to wire up +#if GLMDEBUG +class GLMFuncLogger +{ + public: + + // simple function log + GLMFuncLogger( const char *funcName ) + { + m_funcName = funcName; + m_earlyOut = false; + + GLMPrintf( ">%s", m_funcName ); + }; + + // more advanced version lets you pass args (i.e. called parameters or anything else of interest) + // no macro for this one, since no easy way to pass through the args as well as the funcname + GLMFuncLogger( const char *funcName, char *fmt, ... ) + { + m_funcName = funcName; + m_earlyOut = false; + + // this acts like GLMPrintf here + // all the indent policy is down in GLMPrintfVA + // which means we need to inject a ">" at the front of the format string to make this work... sigh. + + char modifiedFmt[2000]; + modifiedFmt[0] = '>'; + strcpy( modifiedFmt+1, fmt ); + + va_list vargs; + va_start(vargs, fmt); + GLMPrintfVA( modifiedFmt, vargs ); + va_end( vargs ); + } + + ~GLMFuncLogger( ) + { + if (m_earlyOut) + { + GLMPrintf( "<%s (early out)", m_funcName ); + } + else + { + GLMPrintf( "<%s", m_funcName ); + } + }; + + void EarlyOut( void ) + { + m_earlyOut = true; + }; + + const char *m_funcName; // set at construction time + bool m_earlyOut; +}; + +// handy macro to go with the function tracking class +#define GLM_FUNC GLMFuncLogger _logger_ ( __FUNCTION__ ) +#else +#define GLM_FUNC +#endif + + +// class to keep an in-memory mirror of a file which may be getting edited during run +class CGLMFileMirror +{ +public: + CGLMFileMirror( char *fullpath ); // just associates mirror with file. if file exists it will be read. + //if non existent it will be created with size zero + ~CGLMFileMirror( ); + + bool HasData( void ); // see if data avail + void GetData( char **dataPtr, uint *dataSizePtr ); // read it out + void SetData( char *data, uint dataSize ); // put data in (and write it to disk) + bool PollForChanges( void ); // check disk copy. If different, read it back in and return true. + + void UpdateStatInfo( void ); // make sure stat info is current for our file + void ReadFile( void ); + void WriteFile( void ); + + void OpenInEditor( bool foreground=false ); // pass TRUE if you would like the editor to pop to foreground + + /// how about a "wait for change" method.. + + char *m_path; // fullpath to file + bool m_exists; + struct stat m_stat; // stat results for the file (last time checked) + + char *m_data; // content of file + uint m_size; // length of content + +}; + +// class based on the file mirror, that makes it easy to edit them outside the app. + +// it receives an initial block of text from the engine, and hashes it. ("orig") +// it munges it by duplicating all the text after the "!!" line, and appending it in commented form. ("munged") +// a mirror file is activated, using a filename based on the hash from the orig text. +// if there is already content on disk matching that filename, use that content *unless* the 'blitz' parameter is set. +// (i.e. engine is instructing this subsystem to wipe out any old/modified variants of the text) + + +class CGLMEditableTextItem +{ +public: + CGLMEditableTextItem( char *text, uint size, bool forceOverwrite, char *prefix, char *suffix = NULL ); // create a text blob from text source, optional filename suffix + ~CGLMEditableTextItem( ); + + bool HasData( void ); + bool PollForChanges( void ); // return true if stale i.e. you need to get a new edition + void GetCurrentText( char **textOut, uint *sizeOut ); // query for read access to the active blob (could be the original, could be external edited copy) + void OpenInEditor( bool foreground=false ); // call user attention to this text + + // internal methods + void GenHashOfOrigText( void ); + void GenBaseNameAndFullPath( char *prefix, char *suffix ); + void GenMungedText( bool fromMirror ); + + // members + // orig + uint m_origSize; + char *m_origText; // what was submitted + unsigned char m_origDigest[MD5_DIGEST_LENGTH]; // digest of what was submitted + + // munged + uint m_mungedSize; + char *m_mungedText; // re-processed edition, initial content submission to the file mirror + + // mirror + char *m_mirrorBaseName; // generated from the hash of the orig text, plus the label / prefix + char *m_mirrorFullPath; // base name + CGLMFileMirror *m_mirror; // file mirror itself. holds "official" copy for GetCurrentText to return. +}; + + +// debug font +extern unsigned char g_glmDebugFontMap[16384]; + +// class for cracking multi-part text blobs +// sections are demarcated by beginning-of-line markers submitted in a table by the caller + +struct GLMTextSection +{ + int m_markerIndex; // based on table of markers passed in to constructor + uint m_textOffset; // where is the text - offset + int m_textLength; // how big is the section +}; + +class CGLMTextSectioner +{ +public: + CGLMTextSectioner( char *text, int textSize, char **markers ); // constructor finds all the sections + ~CGLMTextSectioner( ); + + int Count( void ); // how many sections found + void GetSection( int index, uint *offsetOut, uint *lengthOut, int *markerIndexOut ); + // find section, size, what marker + // note that more than one section can be marked similarly. + // so policy isn't made here, you walk the sections and decide what to do if there are dupes. + + //members + + //section table + CUtlVector< GLMTextSection > m_sectionTable; +}; + +#endif diff --git a/mp/src/public/togl/osx/glmgrext.h b/mp/src/public/togl/osx/glmgrext.h new file mode 100644 index 00000000..1fc4edce --- /dev/null +++ b/mp/src/public/togl/osx/glmgrext.h @@ -0,0 +1,93 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgrext.h +// helper file for extension testing and runtime importing of entry points +// +//=============================================================================== + +#pragma once + +#ifdef OSX +#include +#include +#elif defined(LINUX) +#include +#include +#else +#error +#endif + +#ifndef GL_EXT_framebuffer_sRGB + #define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 + #define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif + +#ifndef ARB_texture_rg + #define GL_COMPRESSED_RED 0x8225 + #define GL_COMPRESSED_RG 0x8226 + #define GL_RG 0x8227 + #define GL_RG_INTEGER 0x8228 + #define GL_R8 0x8229 + #define GL_R16 0x822A + #define GL_RG8 0x822B + #define GL_RG16 0x822C + #define GL_R16F 0x822D + #define GL_R32F 0x822E + #define GL_RG16F 0x822F + #define GL_RG32F 0x8230 + #define GL_R8I 0x8231 + #define GL_R8UI 0x8232 + #define GL_R16I 0x8233 + #define GL_R16UI 0x8234 + #define GL_R32I 0x8235 + #define GL_R32UI 0x8236 + #define GL_RG8I 0x8237 + #define GL_RG8UI 0x8238 + #define GL_RG16I 0x8239 + #define GL_RG16UI 0x823A + #define GL_RG32I 0x823B + #define GL_RG32UI 0x823C +#endif + +#ifndef GL_EXT_bindable_uniform + #define GL_UNIFORM_BUFFER_EXT 0x8DEE +#endif + +// unpublished extension enums (thus the "X") + +// from EXT_framebuffer_multisample_blit_scaled.. +#define XGL_SCALED_RESOLVE_FASTEST_EXT 0x90BA +#define XGL_SCALED_RESOLVE_NICEST_EXT 0x90BB + +#ifndef GL_TEXTURE_MINIMIZE_STORAGE_APPLE +#define GL_TEXTURE_MINIMIZE_STORAGE_APPLE 0x85B6 +#endif + +#ifndef GL_ALL_COMPLETED_NV +#define GL_ALL_COMPLETED_NV 0x84F2 +#endif + +#ifndef GL_MAP_READ_BIT +#define GL_MAP_READ_BIT 0x0001 +#endif + +#ifndef GL_MAP_WRITE_BIT +#define GL_MAP_WRITE_BIT 0x0002 +#endif + +#ifndef GL_MAP_INVALIDATE_RANGE_BIT +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#endif + +#ifndef GL_MAP_INVALIDATE_BUFFER_BIT +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#endif + +#ifndef GL_MAP_FLUSH_EXPLICIT_BIT +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#endif + +#ifndef GL_MAP_UNSYNCHRONIZED_BIT +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#endif + diff --git a/mp/src/public/togl/rendermechanism.h b/mp/src/public/togl/rendermechanism.h new file mode 100644 index 00000000..b409c4ac --- /dev/null +++ b/mp/src/public/togl/rendermechanism.h @@ -0,0 +1,70 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef RENDERMECHANISM_H +#define RENDERMECHANISM_H + +#if defined(DX_TO_GL_ABSTRACTION) + +#undef PROTECTED_THINGS_ENABLE + +#include +#include +#include "tier0/basetypes.h" +#include "tier0/platform.h" + +#if defined(LINUX) || defined(_WIN32) + +#include "togl/linuxwin/glmdebug.h" +#include "togl/linuxwin/glbase.h" +#include "togl/linuxwin/glentrypoints.h" +#include "togl/linuxwin/glmdisplay.h" +#include "togl/linuxwin/glmdisplaydb.h" +#include "togl/linuxwin/glmgrbasics.h" +#include "togl/linuxwin/glmgrext.h" +#include "togl/linuxwin/cglmbuffer.h" +#include "togl/linuxwin/cglmtex.h" +#include "togl/linuxwin/cglmfbo.h" +#include "togl/linuxwin/cglmprogram.h" +#include "togl/linuxwin/cglmquery.h" +#include "togl/linuxwin/glmgr.h" +#include "togl/linuxwin/dxabstract_types.h" +#include "togl/linuxwin/dxabstract.h" + +#elif defined(OSX) +#include "togl/osx/glmdebug.h" +//#include "togl/osx/glbase.h" +#include "togl/osx/glentrypoints.h" +#include "togl/osx/glmdisplay.h" +#include "togl/osx/glmdisplaydb.h" +#include "togl/osx/glmgrbasics.h" +#include "togl/osx/glmgrext.h" +#include "togl/osx/cglmbuffer.h" +#include "togl/osx/cglmtex.h" +#include "togl/osx/cglmfbo.h" +#include "togl/osx/cglmprogram.h" +#include "togl/osx/cglmquery.h" +#include "togl/osx/glmgr.h" +#include "togl/osx/dxabstract_types.h" +#include "togl/osx/dxabstract.h" + +#endif + +#else + //USE_ACTUAL_DX + #ifdef WIN32 + #ifdef _X360 + #include "d3d9.h" + #include "d3dx9.h" + #else + #include + #include "../../dx9sdk/include/d3d9.h" + #include "../../dx9sdk/include/d3dx9.h" + #endif + typedef HWND VD3DHWND; + #endif + + #define GLMPRINTF(args) + #define GLMPRINTSTR(args) + #define GLMPRINTTEXT(args) +#endif // defined(DX_TO_GL_ABSTRACTION) + +#endif // RENDERMECHANISM_H diff --git a/mp/src/public/vgui/IVGui.h b/mp/src/public/vgui/IVGui.h index 06a3ec8c..e512538a 100644 --- a/mp/src/public/vgui/IVGui.h +++ b/mp/src/public/vgui/IVGui.h @@ -95,6 +95,10 @@ public: // data accessor for above virtual bool GetShouldVGuiControlSleep() = 0; + + // enables VR mode + virtual void SetVRMode( bool bVRMode ) = 0; + virtual bool GetVRMode() = 0; }; #define VGUI_IVGUI_INTERFACE_VERSION "VGUI_ivgui008" diff --git a/mp/src/thirdparty/protobuf-2.3.0/install-sh b/mp/src/thirdparty/protobuf-2.3.0/install-sh index 97a459c7..a5897de6 100644 --- a/mp/src/thirdparty/protobuf-2.3.0/install-sh +++ b/mp/src/thirdparty/protobuf-2.3.0/install-sh @@ -1,519 +1,519 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2006-12-25.00 - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - trap '(exit $?); exit' 1 2 13 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dst_arg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writeable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - -*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test -z "$d" && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2006-12-25.00 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/mp/src/tier1/lzmaDecoder.cpp b/mp/src/tier1/lzmaDecoder.cpp new file mode 100644 index 00000000..1d7b24a8 --- /dev/null +++ b/mp/src/tier1/lzmaDecoder.cpp @@ -0,0 +1,764 @@ +// +// LZMA Codec. +// +// LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) +// http://www.7-zip.org/ +// +// Modified to use Source platform utilities and memory allocation overrides. +//=====================================================================================// + +#include "tier0/platform.h" +#include "tier0/dbg.h" +#include "tier1/lzmaDecoder.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _LZMA_SYSTEM_SIZE_T */ +/* Use system's size_t. You can use it to enable 64-bit sizes supporting */ + +#ifndef _7ZIP_SIZET_DEFINED +#define _7ZIP_SIZET_DEFINED +#ifdef _LZMA_SYSTEM_SIZE_T +#include +typedef size_t SizeT; +#else +typedef UInt32 SizeT; +#endif +#endif + +/* #define _LZMA_IN_CB */ +/* Use callback for input data */ + +/* #define _LZMA_OUT_READ */ +/* Use read function for output data */ + +#define _LZMA_PROB32 +/* It can increase speed on some 32-bit CPUs, +but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; +#ifdef _LZMA_OUT_READ + UInt32 DictionarySize; +#endif +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + +#ifdef _LZMA_IN_CB + const unsigned char *Buffer; + const unsigned char *BufferLim; +#endif + +#ifdef _LZMA_OUT_READ + unsigned char *Dictionary; + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; + unsigned char TempDictionary[4]; +#endif +} CLzmaDecoderState; + +#ifdef _LZMA_OUT_READ +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } +#endif + +int LzmaDecode(CLzmaDecoderState *vs, +#ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, +#else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, +#endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ +{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + +#ifdef _LZMA_IN_CB + +#define RC_TEST { if (Buffer == BufferLim) \ +{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} + +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 + +#else + +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + +#endif + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ +{ UpdateBit0(p); mi <<= 1; A0; } else \ +{ UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ +{ int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + +#ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } +#endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, +#ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, +#else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, +#endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + +#ifdef _LZMA_OUT_READ + + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; +#ifdef _LZMA_IN_CB + const Byte *Buffer = vs->Buffer; + const Byte *BufferLim = vs->BufferLim; +#else + const Byte *Buffer = inStream; + const Byte *BufferLim = inStream + inSize; +#endif + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + +#ifndef _LZMA_IN_CB + *inSizeProcessed = 0; +#endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; +#ifdef _LZMA_IN_CB + RC_INIT; +#else + RC_INIT(inStream, inSize); +#endif + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + +#else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + +#ifndef _LZMA_IN_CB + *inSizeProcessed = 0; +#endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + +#ifdef _LZMA_IN_CB + RC_INIT; +#else + RC_INIT(inStream, inSize); +#endif + +#endif /* _LZMA_OUT_READ */ + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos +#ifdef _LZMA_OUT_READ + + globalPos +#endif + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos +#ifdef _LZMA_OUT_READ + + globalPos +#endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; +#ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; +#else + matchByte = outStream[nowPos - rep0]; +#endif + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; +#ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; +#endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } +else +{ + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { +#ifdef _LZMA_OUT_READ + UInt32 pos; +#endif + UpdateBit0(prob); + +#ifdef _LZMA_OUT_READ + if (distanceLimit == 0) +#else + if (nowPos == 0) +#endif + return LZMA_RESULT_DATA_ERROR; + + state = state < kNumLitStates ? 9 : 11; +#ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; +#else + previousByte = outStream[nowPos - rep0]; +#endif + outStream[nowPos++] = previousByte; +#ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; +#endif + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; +#ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) +#else + if (rep0 > nowPos) +#endif + return LZMA_RESULT_DATA_ERROR; + +#ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; +#endif + + do + { +#ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; +#else + previousByte = outStream[nowPos - rep0]; +#endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); +} + } + RC_NORMALIZE; + +#ifdef _LZMA_OUT_READ + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; +#endif + +#ifdef _LZMA_IN_CB + vs->Buffer = Buffer; + vs->BufferLim = BufferLim; +#else + *inSizeProcessed = (SizeT)(Buffer - inStream); +#endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} + +//----------------------------------------------------------------------------- +// Returns true if buffer is compressed. +//----------------------------------------------------------------------------- +bool CLZMA::IsCompressed( unsigned char *pInput ) +{ + lzma_header_t *pHeader = (lzma_header_t *)pInput; + if ( pHeader && pHeader->id == LZMA_ID ) + { + return true; + } + + // unrecognized + return false; +} + +//----------------------------------------------------------------------------- +// Returns uncompressed size of compressed input buffer. Used for allocating output +// buffer for decompression. Returns 0 if input buffer is not compressed. +//----------------------------------------------------------------------------- +unsigned int CLZMA::GetActualSize( unsigned char *pInput ) +{ + lzma_header_t *pHeader = (lzma_header_t *)pInput; + if ( pHeader && pHeader->id == LZMA_ID ) + { + return LittleLong( pHeader->actualSize ); + } + + // unrecognized + return 0; +} + +//----------------------------------------------------------------------------- +// Uncompress a buffer, Returns the uncompressed size. Caller must provide an +// adequate sized output buffer or memory corruption will occur. +//----------------------------------------------------------------------------- +unsigned int CLZMA::Uncompress( unsigned char *pInput, unsigned char *pOutput ) +{ + unsigned int actualSize = GetActualSize( pInput ); + if ( !actualSize ) + { + // unrecognized + return 0; + } + + CLzmaDecoderState state; + if ( LzmaDecodeProperties( &state.Properties, ((lzma_header_t *)pInput)->properties, LZMA_PROPERTIES_SIZE ) != LZMA_RESULT_OK ) + { + Assert( 0 ); + } + state.Probs = (CProb *)malloc( LzmaGetNumProbs( &state.Properties ) * sizeof( CProb ) ); + + unsigned int lzmaSize = LittleLong( ((lzma_header_t *)pInput)->lzmaSize ); + + SizeT inProcessed; + SizeT outProcessed; + int result = LzmaDecode( &state, pInput + sizeof( lzma_header_t ), lzmaSize, &inProcessed, pOutput, actualSize, &outProcessed ); + + free( state.Probs ); + + if ( result != LZMA_RESULT_OK || outProcessed != (SizeT)actualSize ) + { + Assert( 0 ); + return 0; + } + + return outProcessed; +} + diff --git a/mp/src/tier1/snappy-stubs-internal.h b/mp/src/tier1/snappy-stubs-internal.h index c585a2e6..f75fd482 100644 --- a/mp/src/tier1/snappy-stubs-internal.h +++ b/mp/src/tier1/snappy-stubs-internal.h @@ -138,12 +138,21 @@ class LogMessage { class LogMessageCrash : public LogMessage { public: LogMessageCrash() { } +#if _MSC_VER == 1700 +// Bogus warning from VS 2012: +// warning C4722: 'snappy::LogMessageCrash::~LogMessageCrash' : destructor never returns, potential memory leak +#pragma warning(push) +#pragma warning(disable : 4722) +#endif ~LogMessageCrash() { fprintf( stderr, "\n" ); // cerr << endl; abort(); } }; +#if _MSC_VER == 1700 +#pragma warning(pop) +#endif // This class is used to explicitly ignore values in the conditional // logging macros. This avoids compiler warnings like "value computed diff --git a/mp/src/tier1/tier1.vpc b/mp/src/tier1/tier1.vpc index 2784d62c..eac035ce 100644 --- a/mp/src/tier1/tier1.vpc +++ b/mp/src/tier1/tier1.vpc @@ -44,7 +44,7 @@ $Project "tier1" $File "interface.cpp" $File "KeyValues.cpp" $File "kvpacker.cpp" - $File "lzmaDecoder.cpp" [!$SOURCESDK] + $File "lzmaDecoder.cpp" $File "lzss.cpp" [!$SOURCESDK] $File "mempool.cpp" $File "memstack.cpp" diff --git a/mp/src/utils/vrad/lightmap.cpp b/mp/src/utils/vrad/lightmap.cpp index b6f8c1f7..bc3d254e 100644 --- a/mp/src/utils/vrad/lightmap.cpp +++ b/mp/src/utils/vrad/lightmap.cpp @@ -661,8 +661,9 @@ bool BuildFacesamples( lightinfo_t *pLightInfo, facelight_t *pFaceLight ) pTex->lightmapVecsLuxelsPerWorldUnits[1] ) ) ); // allocate a large number of samples for creation -- get copied later! - char sampleData[sizeof(sample_t)*SINGLE_BRUSH_MAP*2]; - sample_t *samples = (sample_t*)sampleData; // use a char array to speed up the debug version. + CUtlVector sampleData; + sampleData.SetCount( SINGLE_BRUSH_MAP * 2 ); + sample_t *samples = sampleData.Base(); sample_t *pSamples = samples; // lightmap space winding diff --git a/mp/src/utils/vrad/trace.cpp b/mp/src/utils/vrad/trace.cpp index f049fc40..8069dbe7 100644 --- a/mp/src/utils/vrad/trace.cpp +++ b/mp/src/utils/vrad/trace.cpp @@ -622,14 +622,23 @@ void AddBrushesForRayTrace( void ) for ( int j = 0; j < face->numedges; j++ ) { + if ( j >= MAX_POINTS_ON_WINDING ) + Error( "***** ERROR! MAX_POINTS_ON_WINDING reached!" ); + + if ( face->firstedge + j >= ARRAYSIZE( dsurfedges ) ) + Error( "***** ERROR! face->firstedge + j >= ARRAYSIZE( dsurfedges )!" ); + int surfEdge = dsurfedges[face->firstedge + j]; - short v; + unsigned short v; if (surfEdge < 0) v = dedges[-surfEdge].v[1]; else v = dedges[surfEdge].v[0]; + if ( v >= ARRAYSIZE( dvertexes ) ) + Error( "***** ERROR! v(%u) >= ARRAYSIZE( dvertexes(%d) )!", ( unsigned int )v, ARRAYSIZE( dvertexes ) ); + dvertex_t *dv = &dvertexes[v]; points[j] = dv->point; } diff --git a/mp/src/utils/vrad/vrad_dispcoll.cpp b/mp/src/utils/vrad/vrad_dispcoll.cpp index df69a4ac..7e788d07 100644 --- a/mp/src/utils/vrad/vrad_dispcoll.cpp +++ b/mp/src/utils/vrad/vrad_dispcoll.cpp @@ -665,8 +665,8 @@ void CVRADDispColl::CreateChildPatchesSub( int iParentPatch ) // Split along the longest edge. Vector vecEdges[3]; vecEdges[0] = pParentPatch->winding->p[1] - pParentPatch->winding->p[0]; - vecEdges[1] = pParentPatch->winding->p[2] - pParentPatch->winding->p[0]; - vecEdges[2] = pParentPatch->winding->p[2] - pParentPatch->winding->p[1]; + vecEdges[1] = pParentPatch->winding->p[2] - pParentPatch->winding->p[1]; + vecEdges[2] = pParentPatch->winding->p[0] - pParentPatch->winding->p[2]; // Find the longest edge. float flEdgeLength = 0.0f; diff --git a/mp/src/utils/vrad/vraddisps.cpp b/mp/src/utils/vrad/vraddisps.cpp index 1e8d2606..0bbafd40 100644 --- a/mp/src/utils/vrad/vraddisps.cpp +++ b/mp/src/utils/vrad/vraddisps.cpp @@ -1135,7 +1135,7 @@ void AddPatchLightToRadial( Vector const &patchOrigin, Vector const &patchNormal if( bNeighborBump ) { float flScale = patchNormal.Dot( normals[0] ); - flScale = clamp( flScale, 0.0f, flScale ); + flScale = max( 0.0f, flScale ); float flBumpInfluence = influence * flScale; for( int ndxBump = 0; ndxBump < ( NUM_BUMP_VECTS+1 ); ndxBump++ ) @@ -1148,7 +1148,7 @@ void AddPatchLightToRadial( Vector const &patchOrigin, Vector const &patchNormal else { float flScale = patchNormal.Dot( normals[0] ); - flScale = clamp( flScale, 0.0f, flScale ); + flScale = max( 0.0f, flScale ); float flBumpInfluence = influence * flScale * 0.05f; for( int ndxBump = 0; ndxBump < ( NUM_BUMP_VECTS+1 ); ndxBump++ ) @@ -1162,7 +1162,7 @@ void AddPatchLightToRadial( Vector const &patchOrigin, Vector const &patchNormal else { float flScale = patchNormal.Dot( luxelNormal ); - flScale = clamp( flScale, 0.0f, flScale ); + flScale = max( 0.0f, flScale ); influence *= flScale; pRadial->light[0][ndxRadial].AddWeighted( pPatchLight[0], influence ); @@ -1580,21 +1580,13 @@ bool CVRadDispMgr::BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFace // int ndxU, ndxV; - // NOTE: These allocations are necessary to avoid stack overflow - // FIXME: Solve with storing global per-thread temp buffers if there's - // a performance problem with this solution... - bool bTempAllocationNecessary = ((height + 1) * (width + 1)) > SINGLE_BRUSH_MAP; + CUtlVector samples; + samples.SetCount( SINGLEMAP ); + sample_t *pSamples = samples.Base(); - Vector worldPointBuffer[SINGLE_BRUSH_MAP]; - sample_t sampleBuffer[SINGLE_BRUSH_MAP*2]; - - Vector *pWorldPoints = worldPointBuffer; - sample_t *pSamples = sampleBuffer; - if (bTempAllocationNecessary) - { - pWorldPoints = new Vector[ SINGLEMAP ]; - pSamples = new sample_t[ SINGLEMAP ]; - } + CUtlVector worldPoints; + worldPoints.SetCount( SINGLEMAP ); + Vector *pWorldPoints = worldPoints.Base(); for( ndxV = 0; ndxV < ( height + 1 ); ndxV++ ) { @@ -1607,7 +1599,6 @@ bool CVRadDispMgr::BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFace } } - for( ndxV = 0; ndxV < height; ndxV++ ) { for( ndxU = 0; ndxU < width; ndxU++ ) @@ -1660,7 +1651,7 @@ bool CVRadDispMgr::BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFace pFaceLight->numsamples = width * height; pFaceLight->sample = ( sample_t* )calloc( pFaceLight->numsamples, sizeof( *pFaceLight->sample ) ); if( !pFaceLight->sample ) - goto buildDispSamplesError; + return false; memcpy( pFaceLight->sample, pSamples, pFaceLight->numsamples * sizeof( *pFaceLight->sample ) ); @@ -1669,23 +1660,8 @@ bool CVRadDispMgr::BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFace { Msg( "BuildDispSamples: WARNING - no samples %d\n", pLightInfo->face - g_pFaces ); } - - if (bTempAllocationNecessary) - { - delete[] pWorldPoints; - delete[] pSamples; - } return true; - -buildDispSamplesError: - if (bTempAllocationNecessary) - { - delete[] pWorldPoints; - delete[] pSamples; - } - - return false; } diff --git a/mp/src/vpc_scripts/groups.vgc b/mp/src/vpc_scripts/groups.vgc index 93f7b2c5..c4786f55 100644 --- a/mp/src/vpc_scripts/groups.vgc +++ b/mp/src/vpc_scripts/groups.vgc @@ -23,10 +23,16 @@ $Group "game" "vgui_controls" } +$Group "shaders" +{ + "game_shader_dx9" +} + $Group "everything" { "captioncompiler" "client" + "game_shader_dx9" "glview" "height2normal" "mathlib" diff --git a/mp/src/vpc_scripts/projects.vgc b/mp/src/vpc_scripts/projects.vgc index 649cd85b..9ce86546 100644 --- a/mp/src/vpc_scripts/projects.vgc +++ b/mp/src/vpc_scripts/projects.vgc @@ -19,6 +19,11 @@ $Project "client" "game\client\client_hl2mp.vpc" [($WIN32||$POSIX) && $HL2MP] } +$Project "game_shader_dx9" +{ + "materialsystem\stdshaders\game_shader_dx9_hl2mp.vpc" [$HL2MP] +} + $Project "glview" { "utils\glview\glview.vpc" [$WIN32] diff --git a/mp/src/vpc_scripts/source_base.vpc b/mp/src/vpc_scripts/source_base.vpc index 074b850c..fc70c2e5 100644 --- a/mp/src/vpc_scripts/source_base.vpc +++ b/mp/src/vpc_scripts/source_base.vpc @@ -10,8 +10,8 @@ // This is one file we expect to be different between branches and so it must be merged carefully // Staging branch: -//$Macro STAGING_ONLY "1" +//$Conditional STAGING_ONLY "1" // rel/tf_beta branch: -//$Macro TF_BETA "1" +//$Conditional TF_BETA "1" diff --git a/mp/src/vpc_scripts/source_dll_win32_base.vpc b/mp/src/vpc_scripts/source_dll_win32_base.vpc index 77f577e2..4382efaa 100644 --- a/mp/src/vpc_scripts/source_dll_win32_base.vpc +++ b/mp/src/vpc_scripts/source_dll_win32_base.vpc @@ -130,7 +130,7 @@ $Project $CustomBuildStep { // General - $CommandLine "$QUOTE$(VCInstallDir)bin\ml.exe$QUOTE /c /Cp /Zi /Fo$QUOTE$(IntDir)\$(InputName).obj$QUOTE $QUOTE$(InputPath)$QUOTE" + $CommandLine "$QUOTE$(VCInstallDir)bin\ml.exe$QUOTE /safeseh /c /Cp /Zi /Fo$QUOTE$(IntDir)\$(InputName).obj$QUOTE $QUOTE$(InputPath)$QUOTE" $Description "Compiling pointeroverride.asm" $Outputs "$(IntDir)\$(InputName).obj" } diff --git a/mp/src/vpc_scripts/source_video_base.vpc b/mp/src/vpc_scripts/source_video_base.vpc index b1baa408..dd7f3653 100644 --- a/mp/src/vpc_scripts/source_video_base.vpc +++ b/mp/src/vpc_scripts/source_video_base.vpc @@ -31,7 +31,7 @@ $Macro GL "1" [!$DEDICATED && !$WIN32 && !$WIN64] // If we're using OpenGL, we're implicitly using SDL. -$Macro SDL "1" [$GL && !$OSXALL && !$DEDICATED] +$Macro SDL "1" [$GL && !$DEDICATED] $Configuration { @@ -57,5 +57,14 @@ $Configuration $PreprocessorDefinitions "$BASE;USE_SDL" [$SDL] $AdditionalIncludeDirectories "$BASE;$SRCDIR\thirdparty\SDL2" [$SDL || $DEDICATED] } + +} + +$Project +{ + $Folder "Link Libraries" [$OSXALL && $SDL] + { + $DynamicFile "$SRCDIR\lib\public\$PLATFORM\$_IMPLIB_PREFIXSDL2$_IMPLIB_EXT" + } } diff --git a/mp/src/vpc_scripts/source_win32_base.vpc b/mp/src/vpc_scripts/source_win32_base.vpc index 8be3bcf6..04ef53b8 100644 --- a/mp/src/vpc_scripts/source_win32_base.vpc +++ b/mp/src/vpc_scripts/source_win32_base.vpc @@ -60,10 +60,6 @@ $Configuration $PreprocessorDefinitions "$BASE;WIN64;_WIN64;COMPILER_MSVC64" [$WIN64] $PreprocessorDefinitions "$BASE;COMPILER_MSVC32" [$WIN32] - // The VS 2012 compiler keeps hitting internal compiler errors during /analyze. In order to get these - // fixed we need to report them. - $AdditionalOptions "$BASE /errorReport:send" [$ANALYZE] - // Pass on appropriate branch define to preprocessor $PreprocessorDefinitions "$BASE;STAGING_ONLY" [$STAGING_ONLY] $PreprocessorDefinitions "$BASE;TF_BETA" [$TF_BETA] diff --git a/sp/game/mod_episodic/materials/example_model_material.vmt b/sp/game/mod_episodic/materials/example_model_material.vmt new file mode 100644 index 00000000..219f60f2 --- /dev/null +++ b/sp/game/mod_episodic/materials/example_model_material.vmt @@ -0,0 +1,7 @@ +"Mod_Example_Model" +{ + "$basetexture" "Models/props_c17/Oil_Drum001g" +// "$basetexturetransform" "center 0 0 scale 1 2 rotate 0 translate 0 0" +// "$AlphaTestReference" "0.5" + "$surfaceprop" "metal" +} diff --git a/sp/game/mod_episodic/shaders/fxc/example_model_ps20b.vcs b/sp/game/mod_episodic/shaders/fxc/example_model_ps20b.vcs new file mode 100644 index 00000000..616b536f Binary files /dev/null and b/sp/game/mod_episodic/shaders/fxc/example_model_ps20b.vcs differ diff --git a/sp/game/mod_episodic/shaders/fxc/example_model_vs20.vcs b/sp/game/mod_episodic/shaders/fxc/example_model_vs20.vcs new file mode 100644 index 00000000..633eda48 Binary files /dev/null and b/sp/game/mod_episodic/shaders/fxc/example_model_vs20.vcs differ diff --git a/sp/game/mod_hl2/materials/example_model_material.vmt b/sp/game/mod_hl2/materials/example_model_material.vmt new file mode 100644 index 00000000..219f60f2 --- /dev/null +++ b/sp/game/mod_hl2/materials/example_model_material.vmt @@ -0,0 +1,7 @@ +"Mod_Example_Model" +{ + "$basetexture" "Models/props_c17/Oil_Drum001g" +// "$basetexturetransform" "center 0 0 scale 1 2 rotate 0 translate 0 0" +// "$AlphaTestReference" "0.5" + "$surfaceprop" "metal" +} diff --git a/sp/game/mod_hl2/shaders/fxc/example_model_ps20b.vcs b/sp/game/mod_hl2/shaders/fxc/example_model_ps20b.vcs new file mode 100644 index 00000000..616b536f Binary files /dev/null and b/sp/game/mod_hl2/shaders/fxc/example_model_ps20b.vcs differ diff --git a/sp/game/mod_hl2/shaders/fxc/example_model_vs20.vcs b/sp/game/mod_hl2/shaders/fxc/example_model_vs20.vcs new file mode 100644 index 00000000..633eda48 Binary files /dev/null and b/sp/game/mod_hl2/shaders/fxc/example_model_vs20.vcs differ diff --git a/sp/src/devtools/bin/buildshaderlist.pl b/sp/src/devtools/bin/buildshaderlist.pl new file mode 100644 index 00000000..57790ace --- /dev/null +++ b/sp/src/devtools/bin/buildshaderlist.pl @@ -0,0 +1,22 @@ +use File::DosGlob; +@ARGV = map { + my @g = File::DosGlob::glob($_) if /[*?]/; + @g ? @g : $_; + } @ARGV; + +open FILE, ">__tmpshaderlist.txt"; + +foreach $arg (@ARGV) +{ + if( $arg =~ m/\.fxc$/i || $arg =~ m/\.vsh$/i || $arg =~ m/\.psh$/i ) + { + print $arg . "\n"; + print FILE $arg . "\n"; + } +} + +close FILE; + +system "buildshaders.bat __tmpshaderlist"; + +unlink "__tmpshaderlist.txt"; \ No newline at end of file diff --git a/sp/src/devtools/bin/checkshaderchecksums.pl b/sp/src/devtools/bin/checkshaderchecksums.pl new file mode 100644 index 00000000..e41509f2 --- /dev/null +++ b/sp/src/devtools/bin/checkshaderchecksums.pl @@ -0,0 +1,116 @@ +use String::CRC32; +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; + +sub GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub GetShaderSrc +{ + my $shadername = shift; + if ( $shadername =~ m/^(.*)-----/i ) + { + return $1; + } + else + { + return $shadername; + } +} + +sub GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub GetShaderBase +{ + my $shadername = shift; + if ( $shadername =~ m/-----(.*)$/i ) + { + return $1; + } + else + { + my $shadertype = &GetShaderType( $shadername ); + $shadername =~ s/\.$shadertype//i; + return $shadername; + } +} + +$g_x360 = 0; +$g_vcsext = ".vcs"; + +while( 1 ) +{ + $inputbase = shift; + + if( $inputbase =~ m/-x360/ ) + { + $g_x360 = 1; + $g_vcsext = ".360.vcs"; + } + else + { + last; + } +} + +# rip the txt off the end if it's there. +$inputbase =~ s/\.txt//i; + +my @srcfiles = &LoadShaderListFile( $inputbase ); + +foreach $srcfile ( @srcfiles ) +{ + my $shadertype = &GetShaderType( $srcfile ); + my $shaderbase = &GetShaderBase( $srcfile ); + my $shadersrc = &GetShaderSrc( $srcfile ); + my $vcsFileName = "..\\..\\..\\game\\hl2\\shaders\\$shadertype\\$shaderbase" . $g_vcsext; +# print "shadersrc: $shadersrc vcsFileName: $vcsFileName\n"; + + if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) ) + { + next; # skip _ps20 files for 360 + } + + &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 1 ); +} diff --git a/sp/src/devtools/bin/copyshaderincfiles.pl b/sp/src/devtools/bin/copyshaderincfiles.pl new file mode 100644 index 00000000..21702d8f --- /dev/null +++ b/sp/src/devtools/bin/copyshaderincfiles.pl @@ -0,0 +1,75 @@ +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; +use Cwd; +use String::CRC32; + +my $txtfilename = shift; +my $arg = shift; + +my $is360 = 0; +my $platformextension = ""; +if( $arg =~ m/-x360/i ) +{ + $is360 = 1; + $platformextension = ".360"; +} + +open TXTFILE, "<$txtfilename"; + +my $src; +my $dst; +while( $src = ) +{ + # get rid of comments + $src =~ s,//.*,,g; + + # skip blank lines + if( $src =~ m/^\s*$/ ) + { + next; + } + + # Get rid of newlines. + $src =~ s/\n//g; + + # Save off the shader source filename. + my $dst = $src; + + $dst =~ s/_tmp//gi; + + # Does the dst exist? + my $dstexists = -e $dst; + my $srcexists = -e $src; + # What are the time stamps for the src and dst? + my $srcmodtime = ( stat $src )[9]; + my $dstmodtime = ( stat $dst )[9]; + + # Open for edit or add if different than what is in perforce already. + if( !$dstexists || ( $srcmodtime != $dstmodtime ) ) + { + # Make the target writable if it exists + if( $dstexists ) + { + MakeFileWritable( $dst ); + } + + my $dir = $dst; + $dir =~ s,([^/\\]*$),,; # rip the filename off the end + my $filename = $1; + + # create the target directory if it doesn't exist + if( !$dstexists ) + { + &MakeDirHier( $dir, 0777 ); + } + + # copy the file to its targets. . . we want to see STDERR here if there is an error. + my $cmd = "copy $src $dst > nul"; +# print STDERR "$cmd\n"; + system $cmd; + + MakeFileReadOnly( $dst ); + } +} + +close TXTFILE; diff --git a/sp/src/devtools/bin/copyshaders.pl b/sp/src/devtools/bin/copyshaders.pl new file mode 100644 index 00000000..53839298 --- /dev/null +++ b/sp/src/devtools/bin/copyshaders.pl @@ -0,0 +1,172 @@ +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; +use Cwd; +use String::CRC32; + +sub ReadInputFileWithIncludes +{ + local( $filename ) = shift; + + local( *INPUT ); + local( $output ); + + open INPUT, "<$filename" || die; + + local( $line ); + local( $linenum ) = 1; + while( $line = ) + { + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + $output.= ReadInputFileWithIncludes( $1 ); + } + else + { + $output .= $line; + } + } + + close INPUT; + return $output; +} + +sub PatchCRC +{ + my $filename = shift; + my $crc = shift; +# print STDERR "PatchCRC( $filename, $crc )\n"; + local( *FP ); + open FP, "+<$filename" || die; + binmode( FP ); + seek FP, 6 * 4, 0; + my $uInt = "I"; + if( $filename =~ m/360/ ) + { + $uInt = "N"; + } + print FP pack $uInt, $crc; + close FP; +} + +my $txtfilename = shift; +my $arg = shift; + +my $is360 = 0; +my $platformextension = ""; +if( $arg =~ m/-x360/i ) +{ + $is360 = 1; + $platformextension = ".360"; +} + +# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist. +my $changelistnumber = `valve_p4_create_changelist.cmd ..\\..\\..\\game\\hl2\\shaders \"Shader Auto Checkout VCS\"`; +# Get rid of the newline +$changelistnumber =~ s/\n//g; + +my $changelistarg = ""; +if( $changelistnumber != 0 ) +{ + $changelistarg = "-c $changelistnumber" +} + +open TXTFILE, "<$txtfilename"; + +my $src; +my $dst; +while( $src = ) +{ + # get rid of comments + $src =~ s,//.*,,g; + + # skip blank lines + if( $src =~ m/^\s*$/ ) + { + next; + } + + # Get rid of newlines. + $src =~ s/\n//g; + + # Save off the shader source filename. + my $shadersrcfilename = $src; + $shadersrcfilename =~ s/-----.*$//; + # use only target basename. + $src =~ s/^.*-----//; + + # where the binary vcs file is + my $spath = ""; + + if ( $shadersrcfilename =~ m@\.fxc@i ) + { + $spath = "shaders\\fxc\\"; + } + if ( $shadersrcfilename =~ m@\.vsh@i ) + { + $spath = "shaders\\vsh\\"; + } + if ( $shadersrcfilename =~ m@\.psh@i ) + { + $spath = "shaders\\psh\\"; + } + + # make the source have path and extension + $src = $spath . $src . $platformextension . ".vcs"; + + # build the dest filename. + $dst = $src; + + $dst =~ s/shaders\\/..\\..\\..\\game\\hl2\\shaders\\/i; + + # Does the dst exist? + my $dstexists = -e $dst; + my $srcexists = -e $src; + # What are the time stamps for the src and dst? + my $srcmodtime = ( stat $src )[9]; + my $dstmodtime = ( stat $dst )[9]; + + # Write $dst to a file so that we can do perforce stuff to it later. + local( *VCSLIST ); + open VCSLIST, ">>vcslist.txt" || die; + print VCSLIST $dst . "\n"; + close VCSLIST; + + # Open for edit or add if different than what is in perforce already. + if( !$dstexists || ( $srcmodtime != $dstmodtime ) ) + { + if ( $srcexists && $shadersrcfilename =~ m@\.fxc@i ) + { + # Get the CRC for the source file. + my $srccode = ReadInputFileWithIncludes( $shadersrcfilename ); + my $crc = crc32( $srccode ); + + # Patch the source VCS file with the CRC32 of the source code used to build that file. + PatchCRC( $src, $crc ); + } + + # Make the target vcs writable if it exists + if( $dstexists ) + { + MakeFileWritable( $dst ); + } + + my $dir = $dst; + $dir =~ s,([^/\\]*$),,; # rip the filename off the end + my $filename = $1; + + # create the target directory if it doesn't exist + if( !$dstexists ) + { + &MakeDirHier( $dir, 0777 ); + } + + # copy the file to its targets. . . we want to see STDERR here if there is an error. + my $cmd = "copy $src $dst > nul"; +# print STDERR "$cmd\n"; + system $cmd; + + MakeFileReadOnly( $dst ); + } +} + +close TXTFILE; diff --git a/sp/src/devtools/bin/d3dx9_33.dll b/sp/src/devtools/bin/d3dx9_33.dll new file mode 100644 index 00000000..a005f8fa Binary files /dev/null and b/sp/src/devtools/bin/d3dx9_33.dll differ diff --git a/sp/src/devtools/bin/fix_particle_operator_names.pl b/sp/src/devtools/bin/fix_particle_operator_names.pl new file mode 100644 index 00000000..86fd0f0f --- /dev/null +++ b/sp/src/devtools/bin/fix_particle_operator_names.pl @@ -0,0 +1,110 @@ +#!perl +use File::Find; + +&BuildRemapTable; + +find(\&convert, "." ); + + +sub convert + { + return unless (/\.pcf$/i); + return if (/^tmp\.pcf$/i); + return if (/^tmp2\.pcf$/i); + return if (/360\.pcf$/i); + print STDERR "process ", $File::Find::name," ($_) dir=",`cd`," \n"; + my $fname=$_; + print `p4 edit $fname`; + print `dmxconvert -i $_ -o tmp.pcf -oe keyvalues2`; + open(TMP, "tmp.pcf" ) || return; + open(OUT, ">tmp2.pcf" ) || die; + while() + { + s/[\n\r]//g; + if ( (/^(\s*\"functionName\"\s*\"string\"\s*\")(.*)\"(.*)$/) && + length($map{$2}) ) + { + $_=$1.$map{$2}.'"'.$3; + } + if ( (/^(\s*\"name\"\s*\"string\"\s*\")(.*)\"(.*)$/) && + length($map{$2}) ) + { + $_=$1.$map{$2}.'"'.$3; + } + print OUT "$_\n"; + } + close OUT; + close TMP; + print `dmxconvert -i tmp2.pcf -o $fname -ie keyvalues2 -oe binary`; + unlink "tmp.pcf"; + unlink "tmp2.pcf"; +} + + + + + + + + + + + + +sub BuildRemapTable +{ + $map{"alpha_fade"}= "Alpha Fade and Decay"; + $map{"alpha_fade_in_random"}= "Alpha Fade In Random"; + $map{"alpha_fade_out_random"}= "Alpha Fade Out Random"; + $map{"basic_movement"}= "Movement Basic"; + $map{"color_fade"}= "Color Fade"; + $map{"controlpoint_light"}= "Color Light From Control Point"; + $map{"Dampen Movement Relative to Control Point"}= "Movement Dampen Relative to Control Point"; + $map{"Distance Between Control Points Scale"}= "Remap Distance Between Two Control Points to Scalar"; + $map{"Distance to Control Points Scale"}= "Remap Distance to Control Point to Scalar"; + $map{"lifespan_decay"}= "Lifespan Decay"; + $map{"lock to bone"}= "Movement Lock to Bone"; + $map{"postion_lock_to_controlpoint"}= "Movement Lock to Control Point"; + $map{"maintain position along path"}= "Movement Maintain Position Along Path"; + $map{"Match Particle Velocities"}= "Movement Match Particle Velocities"; + $map{"Max Velocity"}= "Movement Max Velocity"; + $map{"noise"}= "Noise Scalar"; + $map{"vector noise"}= "Noise Vector"; + $map{"oscillate_scalar"}= "Oscillate Scalar"; + $map{"oscillate_vector"}= "Oscillate Vector"; + $map{"Orient Rotation to 2D Direction"}= "Rotation Orient to 2D Direction"; + $map{"radius_scale"}= "Radius Scale"; + $map{"Random Cull"}= "Cull Random"; + $map{"remap_scalar"}= "Remap Scalar"; + $map{"rotation_movement"}= "Rotation Basic"; + $map{"rotation_spin"}= "Rotation Spin Roll"; + $map{"rotation_spin yaw"}= "Rotation Spin Yaw"; + $map{"alpha_random"}= "Alpha Random"; + $map{"color_random"}= "Color Random"; + $map{"create from parent particles"}= "Position From Parent Particles"; + $map{"Create In Hierarchy"}= "Position In CP Hierarchy"; + $map{"random position along path"}= "Position Along Path Random"; + $map{"random position on model"}= "Position on Model Random"; + $map{"sequential position along path"}= "Position Along Path Sequential"; + $map{"position_offset_random"}= "Position Modify Offset Random"; + $map{"position_warp_random"}= "Position Modify Warp Random"; + $map{"position_within_box"}= "Position Within Box Random"; + $map{"position_within_sphere"}= "Position Within Sphere Random"; + $map{"Inherit Velocity"}= "Velocity Inherit from Control Point"; + $map{"Initial Repulsion Velocity"}= "Velocity Repulse from World"; + $map{"Initial Velocity Noise"}= "Velocity Noise"; + $map{"Initial Scalar Noise"}= "Remap Noise to Scalar"; + $map{"Lifespan from distance to world"}= "Lifetime from Time to Impact"; + $map{"Pre-Age Noise"}= "Lifetime Pre-Age Noise"; + $map{"lifetime_random"}= "Lifetime Random"; + $map{"radius_random"}= "Radius Random"; + $map{"random yaw"}= "Rotation Yaw Random"; + $map{"Randomly Flip Yaw"}= "Rotation Yaw Flip Random"; + $map{"rotation_random"}= "Rotation Random"; + $map{"rotation_speed_random"}= "Rotation Speed Random"; + $map{"sequence_random"}= "Sequence Random"; + $map{"second_sequence_random"}= "Sequence Two Random"; + $map{"trail_length_random"}= "Trail Length Random"; + $map{"velocity_random"}= "Velocity Random"; +} + diff --git a/sp/src/devtools/bin/linux/ccache b/sp/src/devtools/bin/linux/ccache index 9846e22d..3ef6b8e9 100755 Binary files a/sp/src/devtools/bin/linux/ccache and b/sp/src/devtools/bin/linux/ccache differ diff --git a/sp/src/devtools/bin/osx32/ccache b/sp/src/devtools/bin/osx32/ccache index 36a7081d..86afc048 100755 Binary files a/sp/src/devtools/bin/osx32/ccache and b/sp/src/devtools/bin/osx32/ccache differ diff --git a/sp/src/devtools/bin/shaderinfo.pl b/sp/src/devtools/bin/shaderinfo.pl new file mode 100644 index 00000000..ae0b96c8 --- /dev/null +++ b/sp/src/devtools/bin/shaderinfo.pl @@ -0,0 +1,36 @@ +#! perl + +my $fname=shift || die "format is shaderinfo blah.vcs"; + +open(SHADER, $fname) || die "can't open $fname"; +binmode SHADER; + +read(SHADER,$header,20); +($ver,$ntotal,$ndynamic,$flags,$centroidmask)=unpack("LLLLL",$header); + +#print "Version $ver total combos=$ntotal, num dynamic combos=$ndynamic,\n flags=$flags, centroid mask=$centroidmask\n"; + +read(SHADER,$refsize,4); +$refsize=unpack("L",$refsize); +#print "Size of reference shader for diffing=$refsize\n"; + +seek(SHADER,$refsize,1); + +$nskipped_combos=0; +for(1..$ntotal) + { + read(SHADER,$combodata,8); + ($ofs,$combosize)=unpack("LL",$combodata); + if ( $ofs == 0xffffffff) + { + $nskipped_combos++; + } + else + { + } + } +#print "$nskipped_combos skipped, for an actual total of ",$ntotal-$nskipped_combos,"\n"; +#print "Real to skipped ratio = ",($ntotal-$nskipped_combos)/$ntotal,"\n"; +# csv output - name, real combos, virtual combos, dynamic combos +my $real_combos=$ntotal-$nskipped_combos; +print "$fname,$real_combos,$ntotal,$ndynamic\n"; diff --git a/sp/src/devtools/bin/splitdiff3.pl b/sp/src/devtools/bin/splitdiff3.pl new file mode 100644 index 00000000..e38b493a --- /dev/null +++ b/sp/src/devtools/bin/splitdiff3.pl @@ -0,0 +1,54 @@ +$infilename = shift; +$outfilename1 = shift; +$outfilename2 = shift; +open INPUT, $infilename || die; +@input = ; +close INPUT; + +open MERGEDMINE, ">$outfilename1" || die; +open MERGEDTHEIRS, ">$outfilename2" || die; + +for( $i = 0; $i < scalar( @input ); $i++ ) +{ + $line = $input[$i]; + + if( $line =~ m/^(.*)<<<<<<>>>>>>/ ) + { + $first = $second = 0; + print MERGEDTHEIRS $1; + next; + } + + if( $first ) + { + print MERGEDMINE $line; + } + elsif( $second ) + { + print MERGEDTHEIRS $line; + } + else + { + print MERGEDMINE $line; + print MERGEDTHEIRS $line; + } +} + +close MERGEDMINE; +close MERGEDTHEIRS; diff --git a/sp/src/devtools/bin/uniqifylist.pl b/sp/src/devtools/bin/uniqifylist.pl new file mode 100644 index 00000000..d8d40afd --- /dev/null +++ b/sp/src/devtools/bin/uniqifylist.pl @@ -0,0 +1,6 @@ +foreach $_ (sort <> ) +{ + next if( defined( $prevline ) && $_ eq $prevline ); + $prevline = $_; + print; +} diff --git a/sp/src/devtools/bin/valve_perl_helpers.pl b/sp/src/devtools/bin/valve_perl_helpers.pl new file mode 100644 index 00000000..5cd2aa04 --- /dev/null +++ b/sp/src/devtools/bin/valve_perl_helpers.pl @@ -0,0 +1,558 @@ +sub BackToForwardSlash +{ + my( $path ) = shift; + $path =~ s,\\,/,g; + return $path; +} + +sub RemoveFileName +{ + my( $in ) = shift; + $in = &BackToForwardSlash( $in ); + $in =~ s,/[^/]*$,,; + return $in; +} + +sub RemovePath +{ + my( $in ) = shift; + $in = &BackToForwardSlash( $in ); + $in =~ s,^(.*)/([^/]*)$,$2,; + return $in; +} + +sub MakeDirHier +{ + my( $in ) = shift; +# print "MakeDirHier( $in )\n"; + $in = &BackToForwardSlash( $in ); + my( @path ); + while( $in =~ m,/, ) # while $in still has a slash + { + my( $end ) = &RemovePath( $in ); + push @path, $end; +# print $in . "\n"; + $in = &RemoveFileName( $in ); + } + my( $i ); + my( $numelems ) = scalar( @path ); + my( $curpath ); + for( $i = $numelems - 1; $i >= 0; $i-- ) + { + $curpath .= "/" . $path[$i]; + my( $dir ) = $in . $curpath; + if( !stat $dir ) + { +# print "mkdir $dir\n"; + mkdir $dir, 0777; + } + } +} + +sub FileExists +{ + my $filename = shift; + my @statresult = stat $filename; + my $iswritable = @statresult != 0; + return $iswritable; +} + +sub MakeFileWritable +{ + my $filename = shift; + if ( &FileExists( $filename ) ) + { + chmod 0666, $filename || die; + } +} + +sub MakeFileReadOnly +{ + my $filename = shift; + chmod 0444, $filename || die; +} + +# Run a command and get stdout and stderr to an array +sub RunCommand +{ + my $cmd = shift; +# print STDERR "command: $cmd\n"; + system "$cmd > cmdout.txt 2>&1" || die; + local( *FILE ); + open FILE, "; +# print STDERR "command output: @output\n"; + close FILE; + unlink "cmdout.txt" || die; + return @output; +} + +sub PerforceEditOrAdd +{ + return; + my $filename = shift; + my $changelistarg = shift; + + # Is the file on the client? + my $cmd = "p4 fstat \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $p4output = join "", @p4output; + if( $p4output =~ m/no such file/ ) + { + # not on client. . add + my $cmd = "p4 add $changelistarg $filename"; + my @p4output = &RunCommand( $cmd ); + my $p4output = join "", @p4output; + if( $p4output =~ m/opened for add/ ) + { + print $p4output; + return; + } + print "ERROR: $p4output"; + return; + } + + # The file is known to be on the client at this point. + + # Is it open for edit? + if( $p4output =~ m/action edit/ ) + { + # Is is open for edit, let's see if it's still different. + # check for opened files that are not different from the revision in the depot. + my $cmd = "p4 diff -sr \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + # check for empty string + if( !( $outputstring =~ m/^\s*$/ ) ) + { + my $cmd = "p4 revert \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + print $outputstring; + return; + } + } + + # check for unopened files that are different from the revision in the depot. + my $cmd = "p4 diff -se \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + # check for empty string + if( $outputstring =~ m/^\s*$/ ) + { + &MakeFileReadOnly( $filename ); + return; + } + + # We need to edit the file since it is known to be different here. + my $cmd = "p4 edit $changelistarg \"$filename\""; + my @p4output = &RunCommand( $cmd ); + + my $line; + foreach $line ( @p4output ) + { + if( $line =~ m/not on client/ ) + { + #print "notonclient..."; + print "ERROR: @p4output\n"; + return; + } + if( $line =~ m/currently opened for edit/ ) + { + return; + } + if( $line =~ m/opened for edit/ ) + { + print $line; + } + } +} + +sub FileIsWritable +{ + local( $filename ) = shift; + local( @statresult ) = stat $filename; + local( $mode, $iswritable ); + $mode = oct( $statresult[2] ); + $iswritable = ( $mode & 2 ) != 0; + return $iswritable; +} + +sub TouchFile +{ + my $filename = shift; + if( !&FileExists( $filename ) ) + { + if( !open FILE, ">$filename" ) + { + die; + } + close FILE; + } + my $now = time; + local( *FILE ); + utime $now, $now, $filename; +} + +sub FileExistsInPerforce +{ + my $filename = shift; + my @output = &RunCommand( "p4 fstat $filename" ); + my $line; + foreach $line (@output) + { + if( $line =~ m/no such file/ ) + { + return 0; + } + } + return 1; +} + +sub PerforceWriteFile +{ + my $filename = shift; + my $filecontents = shift; +# my $changelistname = shift; + + # Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist. +# my $changelistnumber = `valve_p4_create_changelist.cmd . \"$changelistname\"`; + # Get rid of the newline +# $changelistnumber =~ s/\n//g; + +# my $changelistarg = ""; +# if( $changelistnumber != 0 ) +# { +# $changelistarg = "-c $changelistnumber" +# } + + # Make the target vcs writable if it exists + MakeFileWritable( $filename ); + + # Write the file. + local( *FP ); + open FP, ">$filename"; + print FP $filecontents; + close FP; + + # Do whatever needs to happen with perforce for this file. +# &PerforceEditOrAdd( $filename, $changelistarg ); +} + +sub WriteFile +{ + my $filename = shift; + my $filecontents = shift; + + # Make the target vcs writable if it exists + MakeFileWritable( $filename ); + + # Write the file. + local( *FP ); + open FP, ">$filename"; + print FP $filecontents; + close FP; +} + +sub PrintCleanPerforceOutput +{ + my $line; + while( $line = shift ) + { + if( $line =~ m/currently opened/i ) + { + next; + } + if( $line =~ m/already opened for edit/i ) + { + next; + } + if( $line =~ m/also opened/i ) + { + next; + } + if( $line =~ m/add of existing file/i ) + { + next; + } + print $line; + } +} + +# HACK!!!! Need to pass something in to do this rather than hard coding. +sub NormalizePerforceFilename +{ + my $line = shift; + + # remove newlines. + $line =~ s/\n//; + # downcase. + $line =~ tr/[A-Z]/[a-z]/; + # backslash to forwardslash + $line =~ s,\\,/,g; + + # for inc files HACK! + $line =~ s/^.*(fxctmp9.*)/$1/i; + $line =~ s/^.*(vshtmp9.*)/$1/i; + + # for vcs files. HACK! + $line =~ s,^.*game/hl2/shaders/,,i; + + return $line; +} + +sub MakeSureFileExists +{ + local( $filename ) = shift; + local( $testexists ) = shift; + local( $testwrite ) = shift; + + local( @statresult ) = stat $filename; + if( !@statresult && $testexists ) + { + die "$filename doesn't exist!\n"; + } + local( $mode, $iswritable ); + $mode = oct( $statresult[2] ); + $iswritable = ( $mode & 2 ) != 0; + if( !$iswritable && $testwrite ) + { + die "$filename isn't writable!\n"; + } +} + +sub LoadShaderListFile_GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub LoadShaderListFile_GetShaderSrc +{ + my $shadername = shift; + if ( $shadername =~ m/^(.*)-----/i ) + { + return $1; + } + else + { + return $shadername; + } +} + +sub LoadShaderListFile_GetShaderBase +{ + my $shadername = shift; + if ( $shadername =~ m/-----(.*)$/i ) + { + return $1; + } + else + { + my $shadertype = &LoadShaderListFile_GetShaderType( $shadername ); + $shadername =~ s/\.$shadertype//i; + return $shadername; + } +} + +sub LoadShaderListFile +{ + my $inputbase = shift; + + my @srcfiles; + &MakeSureFileExists( "$inputbase.txt", 1, 0 ); + + open SHADERLISTFILE, "<$inputbase.txt" || die; + my $line; + while( $line = ) + { + $line =~ s/\/\/.*$//; # remove comments "//..." + $line =~ s/^\s*//; # trim leading whitespace + $line =~ s/\s*$//; # trim trailing whitespace + next if( $line =~ m/^\s*$/ ); + if( $line =~ m/\.fxc/ || $line =~ m/\.vsh/ || $line =~ m/\.psh/ ) + { + my $shaderbase = &LoadShaderListFile_GetShaderBase( $line ); + + if( $ENV{"DIRECTX_FORCE_MODEL"} =~ m/^30$/i ) # forcing all shaders to be ver. 30 + { + my $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps30/i; + $targetbase =~ s/_ps20b/_ps30/i; + $targetbase =~ s/_ps20/_ps30/i; + $targetbase =~ s/_vs20/_vs30/i; + $targetbase =~ s/_vsxx/_vs30/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + else + { + if( $shaderbase =~ m/_ps2x/i ) + { + my $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps20/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + + $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps20b/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + elsif( $shaderbase =~ m/_vsxx/i ) + { + my $targetbase = $shaderbase; + $targetbase =~ s/_vsxx/_vs11/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + + $targetbase = $shaderbase; + $targetbase =~ s/_vsxx/_vs20/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + else + { + push @srcfiles, ( $line . "-----" . $shaderbase ); + } + } + } + } + close SHADERLISTFILE; + return @srcfiles; +} + +sub ReadInputFileWithIncludes +{ + local( $filename ) = shift; +# print STDERR "ReadInputFileWithIncludes: $filename\n"; + + local( *INPUT ); + local( $output ); + +# print STDERR "before open\n"; + open INPUT, "<$filename" || die; +# print STDERR "after open\n"; + + local( $line ); + while( $line = ) + { +# print STDERR $line; + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + $output.= ReadInputFileWithIncludes( $1 ); + } + else + { + $output .= $line; + } + } + + close INPUT; + return $output; +} + +sub GetCRCFromSourceFile +{ + my $filename = shift; + my $data = &ReadInputFileWithIncludes( $filename ); +# print STDERR $data; + $crc = crc32( $data ); +# print STDERR "GetCRCFromSourceFile: $crc\n"; + return $crc; +} + +sub GetCRCFromVCSFile +{ + my $filename = shift; +# print STDERR "GetCRCFromVCSFile $filename\n"; + local( *FP ); + open FP, "<$filename" || die "GetCRCFromVCSFile: can't open file $filename\n"; + binmode( FP ); + + # unpack arguments + my $sInt = "i"; + my $uInt = "I"; + if( $filename =~ m/\.360\./ ) + { + # Change arguments to "big endian long" + $sInt = "N"; + $uInt = "N"; + } + + my $header; + read FP, $header, 7 * 4 || die "updateshaders.pl:GetCRCFromVCSFile: can't read header for $filename\n"; + my $version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc; + ($version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc) = unpack "$sInt$sInt$sInt$uInt$uInt$uInt$uInt", $header; + unless( $version == 4 || $version == 5 || $version == 6 ) + { + print STDERR "ERROR: GetCRCFromVCSFile: $filename is version $version\n"; + return 0; + } +# print STDERR "version: $version\n"; +# print STDERR "numCombos: $numCombos\n"; +# print STDERR "numDynamicCombos: $numDynamicCombos\n"; +# print STDERR "flags: $flags\n"; +# print STDERR "centroidMask: $centroidMask\n"; +# print STDERR "refSize: $refSize\n"; +# print STDERR "GetCRCFromVCSFile: $crc\n"; + close( FP ); + return $crc; +} + +sub CheckCRCAgainstTarget +{ + my $srcFileName = shift; + my $vcsFileName = shift; + my $warn = shift; + + # Make sure both files exist. +# print STDERR "$srcFileName doesn't exist\n" if( !( -e $srcFileName ) ); +# print STDERR "$vcsFileName doesn't exist\n" if( !( -e $vcsFileName ) ); + if( !( -e $srcFileName ) ) + { + if( $warn ) + { + print "$srcFileName missing\n"; + } + return 0; + } + if( !( -e $vcsFileName ) ) + { + if( $warn ) + { + print "$vcsFileName missing\n"; + } + return 0; + } +# print STDERR "CheckCRCAgainstTarget( $srcFileName, $vcsFileName );\n"; +# print STDERR "vcsFileName: $vcsFileName\n"; +# print STDERR "vcsFileName: $srcFileName\n"; + my $vcsCRC = &GetCRCFromVCSFile( $vcsFileName ); + my $srcCRC = &GetCRCFromSourceFile( $srcFileName ); + if( $warn && ( $vcsCRC != $srcCRC ) ) + { + print "$vcsFileName checksum ($vcsCRC) != $srcFileName checksum: ($srcCRC)\n"; + } + +# return 0; # use this to skip crc checking. +# if( $vcsCRC == $srcCRC ) +# { +# print STDERR "CRC passed for $srcFileName $vcsFileName $vcsCRC\n"; +# } + return $vcsCRC == $srcCRC; +} + +1; diff --git a/sp/src/devtools/bin/vpc.exe b/sp/src/devtools/bin/vpc.exe index 0c084858..ddc1328c 100644 Binary files a/sp/src/devtools/bin/vpc.exe and b/sp/src/devtools/bin/vpc.exe differ diff --git a/sp/src/devtools/bin/vpc_linux b/sp/src/devtools/bin/vpc_linux index 31263d23..21679b4f 100755 Binary files a/sp/src/devtools/bin/vpc_linux and b/sp/src/devtools/bin/vpc_linux differ diff --git a/sp/src/devtools/bin/vpc_osx b/sp/src/devtools/bin/vpc_osx index 65058d46..0ca6b8c4 100755 Binary files a/sp/src/devtools/bin/vpc_osx and b/sp/src/devtools/bin/vpc_osx differ diff --git a/sp/src/devtools/makefile_base_posix.mak b/sp/src/devtools/makefile_base_posix.mak index f4689c4b..7ad95035 100644 --- a/sp/src/devtools/makefile_base_posix.mak +++ b/sp/src/devtools/makefile_base_posix.mak @@ -1,503 +1,509 @@ -# -# Base makefile for Linux and OSX -# -# !!!!! Note to future editors !!!!! -# -# before you make changes, make sure you grok: -# 1. the difference between =, :=, +=, and ?= -# 2. how and when this base makefile gets included in the generated makefile(s) -# ( see http://www.gnu.org/software/make/manual/make.html#Flavors ) -# -# Command line prefixes: -# - errors are ignored -# @ command is not printed to stdout before being executed -# + command is executed even if Make is invoked in "do not exec" mode - -OS := $(shell uname) -HOSTNAME := $(shell hostname) - --include $(SRCROOT)/devtools/steam_def.mak --include $(SRCROOT)/devtools/sourcesdk_def.mak - -# To build with clang, set the following in your environment: -# CC = clang -# CXX = clang++ - -ifeq ($(CFG), release) - # With gcc 4.6.3, engine.so went from 7,383,765 to 8,429,109 when building with -O3. - # There also was no speed difference running at 1280x1024. May 2012, mikesart. - # tonyp: The size increase was likely caused by -finline-functions and -fipa-cp-clone getting switched on with -O3. - # -fno-omit-frame-pointer: need this for stack traces with perf. - OptimizerLevel_CompilerSpecific = -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer -ftree-vectorize -fpredictive-commoning -funswitch-loops -else - OptimizerLevel_CompilerSpecific = -O0 - #-O1 -finline-functions -endif - -# CPPFLAGS == "c/c++ *preprocessor* flags" - not "cee-plus-plus flags" -ARCH_FLAGS = -BUILDING_MULTI_ARCH = 0 -CPPFLAGS = $(DEFINES) $(addprefix -I, $(abspath $(INCLUDEDIRS) )) -CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE -CXXFLAGS = $(CFLAGS) -DEFINES += -DVPROF_LEVEL=1 -DGNUC -DNO_HOOK_MALLOC -DNO_MALLOC_OVERRIDE -LDFLAGS = $(CFLAGS) $(GCC_ExtraLinkerFlags) $(OptimizerLevel) -GENDEP_CXXFLAGS = -MD -MP -MF $(@:.o=.P) -MAP_FLAGS = -Srv_GAMEOUTPUTFILE = -COPY_DLL_TO_SRV = 0 - - -ifeq ($(STEAM_BRANCH),1) - WARN_FLAGS = -Wall -Wextra -Wshadow -Wno-invalid-offsetof -else - WARN_FLAGS = -Wno-write-strings -Wno-multichar -endif - -WARN_FLAGS += -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Werror=return-type -fdiagnostics-show-option -Wformat -Wformat-security - - -ifeq ($(OS),Linux) - # We should always specify -Wl,--build-id, as documented at: - # http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId - LDFLAGS += -Wl,--build-id - # Set USE_VALVE_BINDIR to build with /Steam/tools/linux in the /valve/bin path. - # Dedicated server uses this. - ifeq ($(USE_VALVE_BINDIR),1) - # dedicated server flags - ifeq ($(TARGET_PLATFORM),linux64) - VALVE_BINDIR = /valve/bin64/ - MARCH_TARGET = nocona - else - VALVE_BINDIR = /valve/bin/ - MARCH_TARGET = pentium4 - endif - STRIP_FLAGS = - else - # linux desktop client flags - VALVE_BINDIR = - # If the steam-runtime is available, use it. We should just default to using it when - # buildbot and everyone has a bit of time to get it installed. - ifneq "$(wildcard /valve/steam-runtime/bin/)" "" - # The steam-runtime is incompatible with clang at this point, so disable it - # if clang is enabled. - ifneq ($(CXX),clang++) - VALVE_BINDIR = /valve/steam-runtime/bin/ - endif - endif - GCC_VER = - MARCH_TARGET = pentium4 - # On dedicated servers, some plugins depend on global variable symbols in addition to functions. - # So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2. - STRIP_FLAGS = -x - endif - - ifeq ($(CXX),clang++) - # Clang does not support -mfpmath=sse because it uses whatever - # instruction set extensions are available by default. - SSE_GEN_FLAGS = -msse2 - else - SSE_GEN_FLAGS = -msse2 -mfpmath=sse - endif - - CCACHE := $(SRCROOT)/devtools/bin/linux/ccache - - ifeq ($(origin GCC_VER), undefined) - GCC_VER=-4.6 - endif - ifeq ($(origin AR), default) - AR = $(VALVE_BINDIR)ar crs - endif - ifeq ($(origin CC),default) - CC = $(CCACHE) $(VALVE_BINDIR)gcc$(GCC_VER) - endif - ifeq ($(origin CXX), default) - CXX = $(CCACHE) $(VALVE_BINDIR)g++$(GCC_VER) - endif - # Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to - # a ccache quirk. Could also upgrade ccache. - # http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html - ifeq ($(CC),clang) - CC = $(CCACHE) $(VALVE_BINDIR)clang -Qunused-arguments - endif - ifeq ($(CXX),clang++) - CXX = $(CCACHE) $(VALVE_BINDIR)clang++ -Qunused-arguments - endif - LINK ?= $(CC) - - ifeq ($(TARGET_PLATFORM),linux64) - # nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2) - ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2 - LD_SO = ld-linux-x86_64.so.2 - LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.a) - LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++-pic.a) - else - # pentium4 = MMX, SSE, SSE2 - no SSE3 (added in prescott) # -msse3 -mfpmath=sse - ARCH_FLAGS += -m32 -march=$(MARCH_TARGET) -mtune=core2 $(SSE_GEN_FLAGS) - LD_SO = ld-linux.so.2 - LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) - LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) - LDFLAGS += -m32 - endif - - GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh - ifeq ($(CFG),release) - STRIP ?= strip $(STRIP_FLAGS) -S - # CFLAGS += -ffunction-sections -fdata-sections - # LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections - else - STRIP ?= true - endif - VSIGN ?= true - - ifeq ($(SOURCE_SDK), 1) - Srv_GAMEOUTPUTFILE := $(GAMEOUTPUTFILE:.so=_srv.so) - COPY_DLL_TO_SRC := 1 - endif - - LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map - - SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined - - _WRAP := -Xlinker --wrap= - PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \ - $(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \ - $(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \ - $(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \ - $(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath - - LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group - LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread - - LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group - LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt - -endif - -ifeq ($(OS),Darwin) - CCACHE := $(SRCROOT)/devtools/bin/osx32/ccache - MAC_SDK_VER ?= 10.6 - MAC_SDK := macosx$(MAC_SDK_VER) - SYSROOT := $(shell xcodebuild -sdk $(MAC_SDK) -version Path) - - ifneq ($(origin MAC_SDK_VER), file) - $(warning Attempting build with SDK version $(MAC_SDK_VER), only 10.6 is supported and recommended!) - endif - - ifeq ($(SYSROOT),) - FIRSTSDK := $(firstword $(sort $(shell xcodebuild -showsdks | grep macosx | sed 's/.*macosx//'))) - $(error Could not find SDK version $(MAC_SDK_VER). Install and configure Xcode 4.3, or build with: make MAC_SDK_VER=$(FIRSTSDK)) - endif - - ifeq ($(origin CC), default) - # Test to see if you have a compiler in the right place, if you - # don't abort with an error - CLANG := $(shell xcrun -sdk $(MAC_SDK) -find clang) - ifeq ($(wildcard $(CLANG)),) - $(error Unable to find C compiler, install and configure Xcode 4.3) - endif - - CC := $(CCACHE) $(CLANG) -Qunused-arguments - endif - - ifeq ($(origin CXX), default) - CXXLANG := $(shell xcrun -sdk $(MAC_SDK) -find clang++) - ifeq ($(wildcard $(CXXLANG)),) - $(error Unable to find C++ compiler, install and configure Xcode 4.3) - endif - - CXX := $(CCACHE) $(CXXLANG) -Qunused-arguments - endif - LINK ?= $(CXX) - - ifeq ($(origin AR), default) - AR := $(shell xcrun -sdk $(MAC_SDK) -find libtool) -static -o - endif - - ifeq ($(TARGET_PLATFORM),osx64) - ARCH_FLAGS += -arch x86_64 -m64 -march=core2 - else ifeq (,$(findstring -arch x86_64,$(GCC_ExtraCompilerFlags))) - ARCH_FLAGS += -arch i386 -m32 -march=prescott -momit-leaf-frame-pointer -mtune=core2 - else - # dirty hack to build a universal binary - don't specify the architecture - ARCH_FLAGS += -arch i386 -Xarch_i386 -march=prescott -Xarch_i386 -mtune=core2 -Xarch_i386 -momit-leaf-frame-pointer -Xarch_x86_64 -march=core2 - endif - - GEN_SYM ?= $(shell xcrun -sdk $(MAC_SDK) -find dsymutil) - ifeq ($(CFG),release) - STRIP ?= strip -S - else - STRIP ?= true - endif - ifeq ($(SOURCE_SDK), 1) - VSIGN ?= true - else - VSIGN ?= $(SRCROOT)/devtools/bin/vsign - endif - - CPPFLAGS += -I$(SYSROOT)/usr/include/malloc - CFLAGS += -isysroot $(SYSROOT) -mmacosx-version-min=10.5 -fasm-blocks - - LIB_START_EXE = -lm -ldl -lpthread - LIB_END_EXE = - - LIB_START_SHLIB = - LIB_END_SHLIB = - - SHLIBLDFLAGS = $(LDFLAGS) -bundle -flat_namespace -undefined suppress -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms - - ifeq (lib,$(findstring lib,$(GAMEOUTPUTFILE))) - SHLIBLDFLAGS = $(LDFLAGS) -dynamiclib -current_version 1.0 -compatibility_version 1.0 -install_name @rpath/$(basename $(notdir $(GAMEOUTPUTFILE))).dylib $(SystemLibraries) -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms - endif - -endif - -# -# Profile-directed optimizations. -# Note: Last time these were tested 3/5/08, it actually slowed down the server benchmark by 5%! -# -# First, uncomment these, build, and test. It will generate .gcda and .gcno files where the .o files are. -# PROFILE_LINKER_FLAG=-fprofile-arcs -# PROFILE_COMPILER_FLAG=-fprofile-arcs -# -# Then, comment the above flags out again and rebuild with this flag uncommented: -# PROFILE_COMPILER_FLAG=-fprofile-use -# - -############################################################################# -# The compiler command lne for each src code file to compile -############################################################################# - -OBJ_DIR = ./obj_$(NAME)_$(TARGET_PLATFORM)$(TARGET_PLATFORM_EXT)/$(CFG) -CPP_TO_OBJ = $(CPPFILES:.cpp=.o) -CXX_TO_OBJ = $(CPP_TO_OBJ:.cxx=.o) -CC_TO_OBJ = $(CXX_TO_OBJ:.cc=.o) -MM_TO_OBJ = $(CC_TO_OBJ:.mm=.o) -C_TO_OBJ = $(MM_TO_OBJ:.c=.o) -OBJS = $(addprefix $(OBJ_DIR)/, $(notdir $(C_TO_OBJ))) - -ifeq ($(MAKE_VERBOSE),1) - QUIET_PREFIX = - QUIET_ECHO_POSTFIX = -else - QUIET_PREFIX = @ - QUIET_ECHO_POSTFIX = > /dev/null -endif - -ifeq ($(MAKE_CC_VERBOSE),1) -CC += -v -endif - -ifeq ($(CONFTYPE),lib) - LIB_File = $(OUTPUTFILE) -endif - -ifeq ($(CONFTYPE),dll) - SO_File = $(OUTPUTFILE) -endif - -ifeq ($(CONFTYPE),exe) - EXE_File = $(OUTPUTFILE) -endif - -# we generate dependencies as a side-effect of compilation now -GEN_DEP_FILE= - -PRE_COMPILE_FILE = - -POST_COMPILE_FILE = - -ifeq ($(BUILDING_MULTI_ARCH),1) - SINGLE_ARCH_CXXFLAGS=$(subst -arch x86_64,,$(CXXFLAGS)) - COMPILE_FILE = \ - $(QUIET_PREFIX) \ - echo "---- $(lastword $(subst /, ,$<)) as MULTIARCH----";\ - mkdir -p $(OBJ_DIR) && \ - $(CXX) $(SINGLE_ARCH_CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< && \ - $(CXX) $(CXXFLAGS) -o $@ -c $< -else - COMPILE_FILE = \ - $(QUIET_PREFIX) \ - echo "---- $(lastword $(subst /, ,$<)) ----";\ - mkdir -p $(OBJ_DIR) && \ - $(CXX) $(CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< -endif - -ifneq "$(origin VALVE_NO_AUTO_P4)" "undefined" - P4_EDIT_START = chmod -R +w - P4_EDIT_END = || true - P4_REVERT_START = true - P4_REVERT_END = -else - ifndef P4_EDIT_CHANGELIST - # You can use an environment variable to specify what changelist to check the Linux Binaries out into. Normally the default - # setting is best, but here is an alternate example: - # export P4_EDIT_CHANGELIST_CMD="echo 1424335" - # ?= means that if P4_EDIT_CHANGELIST_CMD is already set it won't be changed. - P4_EDIT_CHANGELIST_CMD ?= p4 changes -c `p4 client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1 - P4_EDIT_CHANGELIST := $(shell $(P4_EDIT_CHANGELIST_CMD)) - endif - ifeq ($(P4_EDIT_CHANGELIST),) - # If we haven't found a changelist to check out to then create one. The name must match the one from a few - # lines above or else a new changelist will be created each time. - # Warning: the behavior of 'echo' is not consistent. In bash you need the "-e" option in order for \n to be - # interpreted as a line-feed, but in dash you do not, and if "-e" is passed along then it is printed, which - # confuses p4. So, if you run this command from the bash shell don't forget to add "-e" to the echo command. - P4_EDIT_CHANGELIST = $(shell echo "Change: new\nDescription: POSIX Auto Checkout" | p4 change -i | cut -f 2 -d ' ') - endif - - P4_EDIT_START := for f in - P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - edit -c $(P4_EDIT_CHANGELIST); else p4 edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) - P4_REVERT_START := for f in - P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - revert; else p4 revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) -endif - -ifeq ($(CONFTYPE),dll) -all: $(OTHER_DEPENDENCIES) $(OBJS) $(GAMEOUTPUTFILE) - @echo $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX) -else -all: $(OTHER_DEPENDENCIES) $(OBJS) $(OUTPUTFILE) - @echo $(OUTPUTFILE) $(QUIET_ECHO_POSTFIX) -endif - -.PHONY: clean cleantargets cleanandremove rebuild relink RemoveOutputFile SingleFile - - -rebuild : - $(MAKE) -f $(firstword $(MAKEFILE_LIST)) cleanandremove - $(MAKE) -f $(firstword $(MAKEFILE_LIST)) - - -# Use the relink target to force to relink the project. -relink: RemoveOutputFile all - -RemoveOutputFile: - rm -f $(OUTPUTFILE) - - -# This rule is so you can say "make SingleFile SingleFilename=/home/myname/valve_main/src/engine/language.cpp" and have it only build that file. -# It basically just translates the full filename to create a dependency on the appropriate .o file so it'll build that. -SingleFile : RemoveSingleFile $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o - @echo "" - -RemoveSingleFile: - $(QUIET_PREFIX) rm -f $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o - -clean: -ifneq "$(OBJ_DIR)" "" - $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)" - $(QUIET_PREFIX) rm -rf $(OBJ_DIR) -endif -ifneq "$(OUTPUTFILE)" "" - $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ - echo "p4 revert $(OUTPUTFILE)"; \ - $(P4_REVERT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END); \ - fi; -endif -ifneq "$(OTHER_DEPENDENCIES)" "" - $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)" - $(QUIET_PREFIX) rm -f $(OTHER_DEPENDENCIES) -endif -ifneq "$(GAMEOUTPUTFILE)" "" - $(QUIET_PREFIX) echo "p4 revert $(GAMEOUTPUTFILE)" - $(QUIET_PREFIX) $(P4_REVERT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END) -endif - - -# Do the above cleaning, except with p4 edit and rm. Reason being ar crs adds and replaces obj files to the -# archive. However if you've renamed or deleted a source file, $(AR) won't remove it. This can leave -# us with archive files that have extra unused symbols, and also potentially cause compilation errors -# when you rename a file and have many duplicate symbols. -cleanandremove: -ifneq "$(OBJ_DIR)" "" - $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)" - $(QUIET_PREFIX) -rm -rf $(OBJ_DIR) -endif -ifneq "$(OUTPUTFILE)" "" - $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ - echo "p4 edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \ - $(P4_EDIT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); \ - fi; - $(QUIET_PREFIX) -rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT); -endif -ifneq "$(OTHER_DEPENDENCIES)" "" - $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)" - $(QUIET_PREFIX) -rm -f $(OTHER_DEPENDENCIES) -endif -ifneq "$(GAMEOUTPUTFILE)" "" - $(QUIET_PREFIX) echo "p4 edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)" - $(QUIET_PREFIX) $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END) - $(QUIET_PREFIX) -rm -f $(GAMEOUTPUTFILE) -endif - - -# This just deletes the final targets so it'll do a relink next time we build. -cleantargets: - $(QUIET_PREFIX) rm -f $(OUTPUTFILE) $(GAMEOUTPUTFILE) - - -$(LIB_File): $(OTHER_DEPENDENCIES) $(OBJS) - $(QUIET_PREFIX) -$(P4_EDIT_START) $(LIB_File) $(P4_EDIT_END); - $(QUIET_PREFIX) $(AR) $(LIB_File) $(OBJS) $(LIBFILES); - -SO_GameOutputFile = $(GAMEOUTPUTFILE) - -# Remove the target before installing a file over it; this prevents existing -# instances of the game from crashing due to the overwrite. -$(SO_GameOutputFile): $(SO_File) - $(QUIET_PREFIX) \ - $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END) && \ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- COPYING TO $@ [$(CFG)] ----";\ - echo "----" $(QUIET_ECHO_POSTFIX); - $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END); - $(QUIET_PREFIX) -mkdir -p `dirname $(GAMEOUTPUTFILE)` > /dev/null; - $(QUIET_PREFIX) rm -f $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX); - $(QUIET_PREFIX) cp -v $(OUTPUTFILE) $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX); - $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); - $(QUIET_PREFIX) $(GEN_SYM) $(GAMEOUTPUTFILE); - $(QUIET_PREFIX) -$(STRIP) $(GAMEOUTPUTFILE); - $(QUIET_PREFIX) $(VSIGN) -signvalve $(GAMEOUTPUTFILE); - $(QUIET_PREFIX) if [ "$(COPY_DLL_TO_SRV)" = "1" ]; then\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- COPYING TO $(Srv_GAMEOUTPUTFILE) ----";\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - cp -v $(GAMEOUTPUTFILE) $(Srv_GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);\ - cp -v $(GAMEOUTPUTFILE)$(SYM_EXT) $(Srv_GAMEOUTPUTFILE)$(SYM_EXT) $(QUIET_ECHO_POSTFIX);\ - fi; - $(QUIET_PREFIX) if [ "$(IMPORTLIBRARY)" != "" ]; then\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- COPYING TO IMPORT LIBRARY $(IMPORTLIBRARY) ----";\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - $(P4_EDIT_START) $(IMPORTLIBRARY) $(P4_EDIT_END) && \ - mkdir -p `dirname $(IMPORTLIBRARY)` > /dev/null && \ - cp -v $(OUTPUTFILE) $(IMPORTLIBRARY); \ - fi; - - -$(SO_File): $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES) - $(QUIET_PREFIX) \ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- LINKING $@ [$(CFG)] ----";\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - \ - $(LINK) $(LINK_MAP_FLAGS) $(SHLIBLDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_SHLIB) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_SHLIB); - $(VSIGN) -signvalve $(OUTPUTFILE); - - -$(EXE_File) : $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES) - $(QUIET_PREFIX) \ - echo "----" $(QUIET_ECHO_POSTFIX);\ - echo "---- LINKING EXE $@ [$(CFG)] ----";\ - echo "----" $(QUIET_ECHO_POSTFIX);\ - \ - $(P4_EDIT_START) $(OUTPUTFILE) $(P4_EDIT_END);\ - $(LINK) $(LINK_MAP_FLAGS) $(LDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_EXE) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_EXE); - $(QUIET_PREFIX) -$(P4_EDIT_START) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); - $(QUIET_PREFIX) $(GEN_SYM) $(OUTPUTFILE); - $(QUIET_PREFIX) -$(STRIP) $(OUTPUTFILE); - $(QUIET_PREFIX) $(VSIGN) -signvalve $(OUTPUTFILE); - - -tags: - etags -a -C -o $(SRCROOT)/TAGS *.cpp *.cxx *.h *.hxx +# +# Base makefile for Linux and OSX +# +# !!!!! Note to future editors !!!!! +# +# before you make changes, make sure you grok: +# 1. the difference between =, :=, +=, and ?= +# 2. how and when this base makefile gets included in the generated makefile(s) +# ( see http://www.gnu.org/software/make/manual/make.html#Flavors ) +# +# Command line prefixes: +# - errors are ignored +# @ command is not printed to stdout before being executed +# + command is executed even if Make is invoked in "do not exec" mode + +OS := $(shell uname) +HOSTNAME := $(shell hostname) + +-include $(SRCROOT)/devtools/steam_def.mak +-include $(SRCROOT)/devtools/sourcesdk_def.mak + +# To build with clang, set the following in your environment: +# CC = clang +# CXX = clang++ + +ifeq ($(CFG), release) + # With gcc 4.6.3, engine.so went from 7,383,765 to 8,429,109 when building with -O3. + # There also was no speed difference running at 1280x1024. May 2012, mikesart. + # tonyp: The size increase was likely caused by -finline-functions and -fipa-cp-clone getting switched on with -O3. + # -fno-omit-frame-pointer: need this for stack traces with perf. + OptimizerLevel_CompilerSpecific = -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer -ftree-vectorize -fpredictive-commoning -funswitch-loops +else + OptimizerLevel_CompilerSpecific = -O0 + #-O1 -finline-functions +endif + +# CPPFLAGS == "c/c++ *preprocessor* flags" - not "cee-plus-plus flags" +ARCH_FLAGS = +BUILDING_MULTI_ARCH = 0 +CPPFLAGS = $(DEFINES) $(addprefix -I, $(abspath $(INCLUDEDIRS) )) +CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE +# In -std=gnu++0x mode we get lots of errors about "error: narrowing conversion". -fpermissive +# turns these into warnings in gcc, and -Wno-c++11-narrowing suppresses them entirely in clang 3.1+. +ifeq ($(CXX),clang++) + CXXFLAGS = $(CFLAGS) -Wno-c++11-narrowing -Wno-dangling-else +else + CXXFLAGS = $(CFLAGS) -fpermissive +endif +DEFINES += -DVPROF_LEVEL=1 -DGNUC -DNO_HOOK_MALLOC -DNO_MALLOC_OVERRIDE +LDFLAGS = $(CFLAGS) $(GCC_ExtraLinkerFlags) $(OptimizerLevel) +GENDEP_CXXFLAGS = -MD -MP -MF $(@:.o=.P) +MAP_FLAGS = +Srv_GAMEOUTPUTFILE = +COPY_DLL_TO_SRV = 0 + + +ifeq ($(STEAM_BRANCH),1) + WARN_FLAGS = -Wall -Wextra -Wshadow -Wno-invalid-offsetof +else + WARN_FLAGS = -Wno-write-strings -Wno-multichar +endif + +WARN_FLAGS += -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Werror=return-type -fdiagnostics-show-option -Wformat -Wformat-security + + +ifeq ($(OS),Linux) + # We should always specify -Wl,--build-id, as documented at: + # http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId + LDFLAGS += -Wl,--build-id + # Set USE_VALVE_BINDIR to build with /Steam/tools/linux in the /valve/bin path. + # Dedicated server uses this. + ifeq ($(USE_VALVE_BINDIR),1) + # dedicated server flags + ifeq ($(TARGET_PLATFORM),linux64) + VALVE_BINDIR = /valve/bin64/ + MARCH_TARGET = nocona + else + VALVE_BINDIR = /valve/bin/ + MARCH_TARGET = pentium4 + endif + STRIP_FLAGS = + else + # linux desktop client flags + VALVE_BINDIR = + # If the steam-runtime is available, use it. We should just default to using it when + # buildbot and everyone has a bit of time to get it installed. + ifneq "$(wildcard /valve/steam-runtime/bin/)" "" + # The steam-runtime is incompatible with clang at this point, so disable it + # if clang is enabled. + ifneq ($(CXX),clang++) + VALVE_BINDIR = /valve/steam-runtime/bin/ + endif + endif + GCC_VER = + MARCH_TARGET = pentium4 + # On dedicated servers, some plugins depend on global variable symbols in addition to functions. + # So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2. + STRIP_FLAGS = -x + endif + + ifeq ($(CXX),clang++) + # Clang does not support -mfpmath=sse because it uses whatever + # instruction set extensions are available by default. + SSE_GEN_FLAGS = -msse2 + else + SSE_GEN_FLAGS = -msse2 -mfpmath=sse + endif + + CCACHE := $(SRCROOT)/devtools/bin/linux/ccache + + ifeq ($(origin GCC_VER), undefined) + GCC_VER=-4.6 + endif + ifeq ($(origin AR), default) + AR = $(VALVE_BINDIR)ar crs + endif + ifeq ($(origin CC),default) + CC = $(CCACHE) $(VALVE_BINDIR)gcc$(GCC_VER) + endif + ifeq ($(origin CXX), default) + CXX = $(CCACHE) $(VALVE_BINDIR)g++$(GCC_VER) + endif + # Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to + # a ccache quirk. Could also upgrade ccache. + # http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html + ifeq ($(CC),clang) + CC = $(CCACHE) $(VALVE_BINDIR)clang -Qunused-arguments + endif + ifeq ($(CXX),clang++) + CXX = $(CCACHE) $(VALVE_BINDIR)clang++ -Qunused-arguments + endif + LINK ?= $(CC) + + ifeq ($(TARGET_PLATFORM),linux64) + # nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2) + ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2 + LD_SO = ld-linux-x86_64.so.2 + LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.a) + LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++-pic.a) + else + # pentium4 = MMX, SSE, SSE2 - no SSE3 (added in prescott) # -msse3 -mfpmath=sse + ARCH_FLAGS += -m32 -march=$(MARCH_TARGET) -mtune=core2 $(SSE_GEN_FLAGS) + LD_SO = ld-linux.so.2 + LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) + LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) + LDFLAGS += -m32 + endif + + GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh + ifeq ($(CFG),release) + STRIP ?= strip $(STRIP_FLAGS) -S + # CFLAGS += -ffunction-sections -fdata-sections + # LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections + else + STRIP ?= true + endif + VSIGN ?= true + + ifeq ($(SOURCE_SDK), 1) + Srv_GAMEOUTPUTFILE := $(GAMEOUTPUTFILE:.so=_srv.so) + COPY_DLL_TO_SRV := 1 + endif + + LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map + + SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined + + _WRAP := -Xlinker --wrap= + PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \ + $(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \ + $(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \ + $(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \ + $(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath + + LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group + LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread + + LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group + LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt + +endif + +ifeq ($(OS),Darwin) + CCACHE := $(SRCROOT)/devtools/bin/osx32/ccache + MAC_SDK_VER ?= 10.6 + MAC_SDK := macosx$(MAC_SDK_VER) + SYSROOT := $(shell xcodebuild -sdk $(MAC_SDK) -version Path) + + ifneq ($(origin MAC_SDK_VER), file) + $(warning Attempting build with SDK version $(MAC_SDK_VER), only 10.6 is supported and recommended!) + endif + + ifeq ($(SYSROOT),) + FIRSTSDK := $(firstword $(sort $(shell xcodebuild -showsdks | grep macosx | sed 's/.*macosx//'))) + $(error Could not find SDK version $(MAC_SDK_VER). Install and configure Xcode 4.3, or build with: make MAC_SDK_VER=$(FIRSTSDK)) + endif + + ifeq ($(origin CC), default) + # Test to see if you have a compiler in the right place, if you + # don't abort with an error + CLANG := $(shell xcrun -sdk $(MAC_SDK) -find clang) + ifeq ($(wildcard $(CLANG)),) + $(error Unable to find C compiler, install and configure Xcode 4.3) + endif + + CC := $(CCACHE) $(CLANG) -Qunused-arguments + endif + + ifeq ($(origin CXX), default) + CXXLANG := $(shell xcrun -sdk $(MAC_SDK) -find clang++) + ifeq ($(wildcard $(CXXLANG)),) + $(error Unable to find C++ compiler, install and configure Xcode 4.3) + endif + + CXX := $(CCACHE) $(CXXLANG) -Qunused-arguments + endif + LINK ?= $(CXX) + + ifeq ($(origin AR), default) + AR := $(shell xcrun -sdk $(MAC_SDK) -find libtool) -static -o + endif + + ifeq ($(TARGET_PLATFORM),osx64) + ARCH_FLAGS += -arch x86_64 -m64 -march=core2 + else ifeq (,$(findstring -arch x86_64,$(GCC_ExtraCompilerFlags))) + ARCH_FLAGS += -arch i386 -m32 -march=prescott -momit-leaf-frame-pointer -mtune=core2 + else + # dirty hack to build a universal binary - don't specify the architecture + ARCH_FLAGS += -arch i386 -Xarch_i386 -march=prescott -Xarch_i386 -mtune=core2 -Xarch_i386 -momit-leaf-frame-pointer -Xarch_x86_64 -march=core2 + endif + + GEN_SYM ?= $(shell xcrun -sdk $(MAC_SDK) -find dsymutil) + ifeq ($(CFG),release) + STRIP ?= strip -S + else + STRIP ?= true + endif + ifeq ($(SOURCE_SDK), 1) + VSIGN ?= true + else + VSIGN ?= $(SRCROOT)/devtools/bin/vsign + endif + + CPPFLAGS += -I$(SYSROOT)/usr/include/malloc + CFLAGS += -isysroot $(SYSROOT) -mmacosx-version-min=10.5 -fasm-blocks + + LIB_START_EXE = -lm -ldl -lpthread + LIB_END_EXE = + + LIB_START_SHLIB = + LIB_END_SHLIB = + + SHLIBLDFLAGS = $(LDFLAGS) -bundle -flat_namespace -undefined suppress -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms + + ifeq (lib,$(findstring lib,$(GAMEOUTPUTFILE))) + SHLIBLDFLAGS = $(LDFLAGS) -dynamiclib -current_version 1.0 -compatibility_version 1.0 -install_name @rpath/$(basename $(notdir $(GAMEOUTPUTFILE))).dylib $(SystemLibraries) -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms + endif + +endif + +# +# Profile-directed optimizations. +# Note: Last time these were tested 3/5/08, it actually slowed down the server benchmark by 5%! +# +# First, uncomment these, build, and test. It will generate .gcda and .gcno files where the .o files are. +# PROFILE_LINKER_FLAG=-fprofile-arcs +# PROFILE_COMPILER_FLAG=-fprofile-arcs +# +# Then, comment the above flags out again and rebuild with this flag uncommented: +# PROFILE_COMPILER_FLAG=-fprofile-use +# + +############################################################################# +# The compiler command lne for each src code file to compile +############################################################################# + +OBJ_DIR = ./obj_$(NAME)_$(TARGET_PLATFORM)$(TARGET_PLATFORM_EXT)/$(CFG) +CPP_TO_OBJ = $(CPPFILES:.cpp=.o) +CXX_TO_OBJ = $(CPP_TO_OBJ:.cxx=.o) +CC_TO_OBJ = $(CXX_TO_OBJ:.cc=.o) +MM_TO_OBJ = $(CC_TO_OBJ:.mm=.o) +C_TO_OBJ = $(MM_TO_OBJ:.c=.o) +OBJS = $(addprefix $(OBJ_DIR)/, $(notdir $(C_TO_OBJ))) + +ifeq ($(MAKE_VERBOSE),1) + QUIET_PREFIX = + QUIET_ECHO_POSTFIX = +else + QUIET_PREFIX = @ + QUIET_ECHO_POSTFIX = > /dev/null +endif + +ifeq ($(MAKE_CC_VERBOSE),1) +CC += -v +endif + +ifeq ($(CONFTYPE),lib) + LIB_File = $(OUTPUTFILE) +endif + +ifeq ($(CONFTYPE),dll) + SO_File = $(OUTPUTFILE) +endif + +ifeq ($(CONFTYPE),exe) + EXE_File = $(OUTPUTFILE) +endif + +# we generate dependencies as a side-effect of compilation now +GEN_DEP_FILE= + +PRE_COMPILE_FILE = + +POST_COMPILE_FILE = + +ifeq ($(BUILDING_MULTI_ARCH),1) + SINGLE_ARCH_CXXFLAGS=$(subst -arch x86_64,,$(CXXFLAGS)) + COMPILE_FILE = \ + $(QUIET_PREFIX) \ + echo "---- $(lastword $(subst /, ,$<)) as MULTIARCH----";\ + mkdir -p $(OBJ_DIR) && \ + $(CXX) $(SINGLE_ARCH_CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< && \ + $(CXX) $(CXXFLAGS) -o $@ -c $< +else + COMPILE_FILE = \ + $(QUIET_PREFIX) \ + echo "---- $(lastword $(subst /, ,$<)) ----";\ + mkdir -p $(OBJ_DIR) && \ + $(CXX) $(CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< +endif + +ifneq "$(origin VALVE_NO_AUTO_P4)" "undefined" + P4_EDIT_START = chmod -R +w + P4_EDIT_END = || true + P4_REVERT_START = true + P4_REVERT_END = +else + ifndef P4_EDIT_CHANGELIST + # You can use an environment variable to specify what changelist to check the Linux Binaries out into. Normally the default + # setting is best, but here is an alternate example: + # export P4_EDIT_CHANGELIST_CMD="echo 1424335" + # ?= means that if P4_EDIT_CHANGELIST_CMD is already set it won't be changed. + P4_EDIT_CHANGELIST_CMD ?= p4 changes -c `p4 client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1 + P4_EDIT_CHANGELIST := $(shell $(P4_EDIT_CHANGELIST_CMD)) + endif + ifeq ($(P4_EDIT_CHANGELIST),) + # If we haven't found a changelist to check out to then create one. The name must match the one from a few + # lines above or else a new changelist will be created each time. + # Warning: the behavior of 'echo' is not consistent. In bash you need the "-e" option in order for \n to be + # interpreted as a line-feed, but in dash you do not, and if "-e" is passed along then it is printed, which + # confuses p4. So, if you run this command from the bash shell don't forget to add "-e" to the echo command. + P4_EDIT_CHANGELIST = $(shell echo "Change: new\nDescription: POSIX Auto Checkout" | p4 change -i | cut -f 2 -d ' ') + endif + + P4_EDIT_START := for f in + P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - edit -c $(P4_EDIT_CHANGELIST); else p4 edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) + P4_REVERT_START := for f in + P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - revert; else p4 revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) +endif + +ifeq ($(CONFTYPE),dll) +all: $(OTHER_DEPENDENCIES) $(OBJS) $(GAMEOUTPUTFILE) + @echo $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX) +else +all: $(OTHER_DEPENDENCIES) $(OBJS) $(OUTPUTFILE) + @echo $(OUTPUTFILE) $(QUIET_ECHO_POSTFIX) +endif + +.PHONY: clean cleantargets cleanandremove rebuild relink RemoveOutputFile SingleFile + + +rebuild : + $(MAKE) -f $(firstword $(MAKEFILE_LIST)) cleanandremove + $(MAKE) -f $(firstword $(MAKEFILE_LIST)) + + +# Use the relink target to force to relink the project. +relink: RemoveOutputFile all + +RemoveOutputFile: + rm -f $(OUTPUTFILE) + + +# This rule is so you can say "make SingleFile SingleFilename=/home/myname/valve_main/src/engine/language.cpp" and have it only build that file. +# It basically just translates the full filename to create a dependency on the appropriate .o file so it'll build that. +SingleFile : RemoveSingleFile $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o + @echo "" + +RemoveSingleFile: + $(QUIET_PREFIX) rm -f $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o + +clean: +ifneq "$(OBJ_DIR)" "" + $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)" + $(QUIET_PREFIX) rm -rf $(OBJ_DIR) +endif +ifneq "$(OUTPUTFILE)" "" + $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ + echo "p4 revert $(OUTPUTFILE)"; \ + $(P4_REVERT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END); \ + fi; +endif +ifneq "$(OTHER_DEPENDENCIES)" "" + $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)" + $(QUIET_PREFIX) rm -f $(OTHER_DEPENDENCIES) +endif +ifneq "$(GAMEOUTPUTFILE)" "" + $(QUIET_PREFIX) echo "p4 revert $(GAMEOUTPUTFILE)" + $(QUIET_PREFIX) $(P4_REVERT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END) +endif + + +# Do the above cleaning, except with p4 edit and rm. Reason being ar crs adds and replaces obj files to the +# archive. However if you've renamed or deleted a source file, $(AR) won't remove it. This can leave +# us with archive files that have extra unused symbols, and also potentially cause compilation errors +# when you rename a file and have many duplicate symbols. +cleanandremove: +ifneq "$(OBJ_DIR)" "" + $(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)" + $(QUIET_PREFIX) -rm -rf $(OBJ_DIR) +endif +ifneq "$(OUTPUTFILE)" "" + $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ + echo "p4 edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \ + $(P4_EDIT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); \ + fi; + $(QUIET_PREFIX) -rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT); +endif +ifneq "$(OTHER_DEPENDENCIES)" "" + $(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)" + $(QUIET_PREFIX) -rm -f $(OTHER_DEPENDENCIES) +endif +ifneq "$(GAMEOUTPUTFILE)" "" + $(QUIET_PREFIX) echo "p4 edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)" + $(QUIET_PREFIX) $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END) + $(QUIET_PREFIX) -rm -f $(GAMEOUTPUTFILE) +endif + + +# This just deletes the final targets so it'll do a relink next time we build. +cleantargets: + $(QUIET_PREFIX) rm -f $(OUTPUTFILE) $(GAMEOUTPUTFILE) + + +$(LIB_File): $(OTHER_DEPENDENCIES) $(OBJS) + $(QUIET_PREFIX) -$(P4_EDIT_START) $(LIB_File) $(P4_EDIT_END); + $(QUIET_PREFIX) $(AR) $(LIB_File) $(OBJS) $(LIBFILES); + +SO_GameOutputFile = $(GAMEOUTPUTFILE) + +# Remove the target before installing a file over it; this prevents existing +# instances of the game from crashing due to the overwrite. +$(SO_GameOutputFile): $(SO_File) + $(QUIET_PREFIX) \ + $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END) && \ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- COPYING TO $@ [$(CFG)] ----";\ + echo "----" $(QUIET_ECHO_POSTFIX); + $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END); + $(QUIET_PREFIX) -mkdir -p `dirname $(GAMEOUTPUTFILE)` > /dev/null; + $(QUIET_PREFIX) rm -f $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX); + $(QUIET_PREFIX) cp -v $(OUTPUTFILE) $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX); + $(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); + $(QUIET_PREFIX) $(GEN_SYM) $(GAMEOUTPUTFILE); + $(QUIET_PREFIX) -$(STRIP) $(GAMEOUTPUTFILE); + $(QUIET_PREFIX) $(VSIGN) -signvalve $(GAMEOUTPUTFILE); + $(QUIET_PREFIX) if [ "$(COPY_DLL_TO_SRV)" = "1" ]; then\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- COPYING TO $(Srv_GAMEOUTPUTFILE) ----";\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + cp -v $(GAMEOUTPUTFILE) $(Srv_GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);\ + cp -v $(GAMEOUTPUTFILE)$(SYM_EXT) $(Srv_GAMEOUTPUTFILE)$(SYM_EXT) $(QUIET_ECHO_POSTFIX);\ + fi; + $(QUIET_PREFIX) if [ "$(IMPORTLIBRARY)" != "" ]; then\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- COPYING TO IMPORT LIBRARY $(IMPORTLIBRARY) ----";\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + $(P4_EDIT_START) $(IMPORTLIBRARY) $(P4_EDIT_END) && \ + mkdir -p `dirname $(IMPORTLIBRARY)` > /dev/null && \ + cp -v $(OUTPUTFILE) $(IMPORTLIBRARY); \ + fi; + + +$(SO_File): $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES) + $(QUIET_PREFIX) \ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- LINKING $@ [$(CFG)] ----";\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + \ + $(LINK) $(LINK_MAP_FLAGS) $(SHLIBLDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_SHLIB) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_SHLIB); + $(VSIGN) -signvalve $(OUTPUTFILE); + + +$(EXE_File) : $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES) + $(QUIET_PREFIX) \ + echo "----" $(QUIET_ECHO_POSTFIX);\ + echo "---- LINKING EXE $@ [$(CFG)] ----";\ + echo "----" $(QUIET_ECHO_POSTFIX);\ + \ + $(P4_EDIT_START) $(OUTPUTFILE) $(P4_EDIT_END);\ + $(LINK) $(LINK_MAP_FLAGS) $(LDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_EXE) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_EXE); + $(QUIET_PREFIX) -$(P4_EDIT_START) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); + $(QUIET_PREFIX) $(GEN_SYM) $(OUTPUTFILE); + $(QUIET_PREFIX) -$(STRIP) $(OUTPUTFILE); + $(QUIET_PREFIX) $(VSIGN) -signvalve $(OUTPUTFILE); + + +tags: + etags -a -C -o $(SRCROOT)/TAGS *.cpp *.cxx *.h *.hxx diff --git a/sp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll b/sp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll new file mode 100644 index 00000000..56c9aa02 Binary files /dev/null and b/sp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll differ diff --git a/sp/src/dx9sdk/utilities/dx_proxy.dll b/sp/src/dx9sdk/utilities/dx_proxy.dll new file mode 100644 index 00000000..0afc595e Binary files /dev/null and b/sp/src/dx9sdk/utilities/dx_proxy.dll differ diff --git a/sp/src/game/client/c_baseanimating.cpp b/sp/src/game/client/c_baseanimating.cpp index 137923d4..1086c301 100644 --- a/sp/src/game/client/c_baseanimating.cpp +++ b/sp/src/game/client/c_baseanimating.cpp @@ -1543,6 +1543,8 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater ApplyBoneMatrixTransform( GetBoneForWrite( i ) ); } } + + } //----------------------------------------------------------------------------- @@ -3233,7 +3235,7 @@ int C_BaseAnimating::InternalDrawModel( int flags ) if ( !GetModelPtr() ) return 0; - UpdateBoneAttachments( flags ); + UpdateBoneAttachments( ); if ( IsEffectActive( EF_ITEM_BLINK ) ) { @@ -6255,7 +6257,7 @@ bool C_BaseAnimating::ShouldResetSequenceOnNewModel( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_BaseAnimating::UpdateBoneAttachments( int flags ) +void C_BaseAnimating::UpdateBoneAttachments( void ) { if ( !m_pAttachedTo ) return; diff --git a/sp/src/game/client/c_baseanimating.h b/sp/src/game/client/c_baseanimating.h index d1c99868..5f30d8f8 100644 --- a/sp/src/game/client/c_baseanimating.h +++ b/sp/src/game/client/c_baseanimating.h @@ -228,7 +228,7 @@ public: int GetNumBoneAttachments(); C_BaseAnimating* GetBoneAttachment( int i ); virtual void NotifyBoneAttached( C_BaseAnimating* attachTarget ); - virtual void UpdateBoneAttachments( int flags ); + virtual void UpdateBoneAttachments( void ); //bool solveIK(float a, float b, const Vector &Foot, const Vector &Knee1, Vector &Knee2); //void DebugIK( mstudioikchain_t *pikchain ); diff --git a/sp/src/game/client/c_baseentity.h b/sp/src/game/client/c_baseentity.h index 955e80c5..3ea4b7fd 100644 --- a/sp/src/game/client/c_baseentity.h +++ b/sp/src/game/client/c_baseentity.h @@ -743,6 +743,7 @@ public: virtual void SetHealth(int iHealth) {} virtual int GetHealth() const { return 0; } virtual int GetMaxHealth() const { return 1; } + virtual bool IsVisibleToTargetID( void ) { return false; } // Returns the health fraction float HealthFraction() const; @@ -1004,6 +1005,7 @@ public: virtual bool IsBaseObject( void ) const { return false; } virtual bool IsBaseCombatWeapon( void ) const { return false; } virtual class C_BaseCombatWeapon *MyCombatWeaponPointer() { return NULL; } + virtual bool IsCombatItem( void ) const { return false; } virtual bool IsBaseTrain( void ) const { return false; } diff --git a/sp/src/game/client/c_team_objectiveresource.cpp b/sp/src/game/client/c_team_objectiveresource.cpp index 7d31036d..e0412d27 100644 --- a/sp/src/game/client/c_team_objectiveresource.cpp +++ b/sp/src/game/client/c_team_objectiveresource.cpp @@ -87,7 +87,10 @@ IMPLEMENT_CLIENTCLASS_DT_NOBASE(C_BaseTeamObjectiveResource, DT_BaseTeamObjectiv RecvPropArray3( RECVINFO_ARRAY(m_iTeamInZone), RecvPropInt( RECVINFO(m_iTeamInZone[0]) ) ), RecvPropArray3( RECVINFO_ARRAY(m_bBlocked), RecvPropInt( RECVINFO(m_bBlocked[0]) ) ), RecvPropArray3( RECVINFO_ARRAY(m_iOwner), RecvPropInt( RECVINFO(m_iOwner[0]), 0, RecvProxy_Owner ) ), + RecvPropArray3( RECVINFO_ARRAY(m_bCPCapRateScalesWithPlayers), RecvPropBool( RECVINFO(m_bCPCapRateScalesWithPlayers[0]) ) ), RecvPropString( RECVINFO(m_pszCapLayoutInHUD), 0, RecvProxy_CapLayout ), + RecvPropFloat( RECVINFO(m_flCustomPositionX) ), + RecvPropFloat( RECVINFO(m_flCustomPositionY) ), END_RECV_TABLE() C_BaseTeamObjectiveResource *g_pObjectiveResource = NULL; @@ -151,6 +154,9 @@ C_BaseTeamObjectiveResource::C_BaseTeamObjectiveResource() m_flNodeHillData[i] = 0; } + m_flCustomPositionX = -1.f; + m_flCustomPositionY = -1.f; + g_pObjectiveResource = this; } @@ -173,6 +179,9 @@ void C_BaseTeamObjectiveResource::OnPreDataChanged( DataUpdateType_t updateType m_iOldUpdateCapHudParity = m_iUpdateCapHudParity; m_bOldControlPointsReset = m_bControlPointsReset; + m_flOldCustomPositionX = m_flCustomPositionX; + m_flOldCustomPositionY = m_flCustomPositionY; + memcpy( m_flOldLazyCapPerc, m_flLazyCapPerc, sizeof(float)*m_iNumControlPoints ); memcpy( m_flOldUnlockTimes, m_flUnlockTimes, sizeof(float)*m_iNumControlPoints ); memcpy( m_flOldCPTimerTimes, m_flCPTimerTimes, sizeof(float)*m_iNumControlPoints ); @@ -229,6 +238,11 @@ void C_BaseTeamObjectiveResource::OnDataChanged( DataUpdateType_t updateType ) } } } + + if ( m_flOldCustomPositionX != m_flCustomPositionX || m_flOldCustomPositionY != m_flCustomPositionY ) + { + UpdateControlPoint( "controlpoint_updatelayout" ); + } } //----------------------------------------------------------------------------- @@ -373,7 +387,7 @@ void C_BaseTeamObjectiveResource::ClientThink() if ( iPlayersCapping > 0 ) { float flReduction = gpGlobals->curtime - m_flCapLastThinkTime[i]; - if ( mp_capstyle.GetInt() == 1 ) + if ( mp_capstyle.GetInt() == 1 && m_bCPCapRateScalesWithPlayers[i] ) { // Diminishing returns for successive players. for ( int iPlayer = 1; iPlayer < iPlayersCapping; iPlayer++ ) @@ -423,7 +437,8 @@ void C_BaseTeamObjectiveResource::ClientThink() if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->TeamMayCapturePoint(m_iCappingTeam[i],i) ) { float flCapLength = m_flTeamCapTime[ TEAM_ARRAY(i,m_iCappingTeam[i]) ]; - float flDecrease = (flCapLength / mp_capdeteriorate_time.GetFloat()) * (gpGlobals->curtime - m_flCapLastThinkTime[i]); + float flDecreaseScale = m_bCPCapRateScalesWithPlayers[i] ? mp_capdeteriorate_time.GetFloat() : flCapLength; + float flDecrease = (flCapLength / flDecreaseScale) * (gpGlobals->curtime - m_flCapLastThinkTime[i]); if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->InOvertime() ) { flDecrease *= 6; diff --git a/sp/src/game/client/c_team_objectiveresource.h b/sp/src/game/client/c_team_objectiveresource.h index ca75d8dc..588971c3 100644 --- a/sp/src/game/client/c_team_objectiveresource.h +++ b/sp/src/game/client/c_team_objectiveresource.h @@ -163,6 +163,7 @@ public: } const char *GetCapLayoutInHUD( void ) { return m_pszCapLayoutInHUD; } + void GetCapLayoutCustomPosition( float& flCustomPositionX, float& flCustomPositionY ) { flCustomPositionX = m_flCustomPositionX; flCustomPositionY = m_flCustomPositionY; } bool PlayingMiniRounds( void ){ return m_bPlayingMiniRounds; } bool IsInMiniRound( int index ) { return m_bInMiniRound[index]; } @@ -313,6 +314,7 @@ protected: int m_iTeamInZone[MAX_CONTROL_POINTS]; bool m_bBlocked[MAX_CONTROL_POINTS]; int m_iOwner[MAX_CONTROL_POINTS]; + bool m_bCPCapRateScalesWithPlayers[MAX_CONTROL_POINTS]; // client calculated state float m_flCapTimeLeft[MAX_CONTROL_POINTS]; @@ -321,6 +323,10 @@ protected: bool m_bWarnedOnFinalCap[MAX_CONTROL_POINTS]; float m_flLastCapWarningTime[MAX_CONTROL_POINTS]; char m_pszCapLayoutInHUD[MAX_CAPLAYOUT_LENGTH]; + float m_flOldCustomPositionX; + float m_flOldCustomPositionY; + float m_flCustomPositionX; + float m_flCustomPositionY; // hill data for multi-escort payload maps int m_nNumNodeHillData[TEAM_TRAIN_MAX_TEAMS]; diff --git a/sp/src/game/client/cdll_client_int.cpp b/sp/src/game/client/cdll_client_int.cpp index 0e96b11c..c8f7f40b 100644 --- a/sp/src/game/client/cdll_client_int.cpp +++ b/sp/src/game/client/cdll_client_int.cpp @@ -104,6 +104,7 @@ #include "replay/vgui/replayperformanceeditor.h" #endif #include "vgui/ILocalize.h" +#include "vgui/IVGui.h" #include "ixboxsystem.h" #include "ipresence.h" #include "engine/imatchmaking.h" @@ -982,6 +983,8 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi g_pSourceVR->GetViewportBounds( ISourceVirtualReality::VREye_Left, NULL, NULL, &nViewportWidth, &nViewportHeight ); vgui::surface()->SetFullscreenViewport( 0, 0, nViewportWidth, nViewportHeight ); + + vgui::ivgui()->SetVRMode( true ); } if (!Initializer::InitializeAllObjects()) diff --git a/sp/src/game/client/client_virtualreality.cpp b/sp/src/game/client/client_virtualreality.cpp index 69f6e63a..1eb59a59 100644 --- a/sp/src/game/client/client_virtualreality.cpp +++ b/sp/src/game/client/client_virtualreality.cpp @@ -635,34 +635,6 @@ bool CClientVirtualReality::OverrideStereoView( CViewSetup *pViewMiddle, CViewSe g_pSourceVR->GetEyeProjectionMatrix ( &pViewLeft->m_ViewToProjection, ISourceVirtualReality::VREye_Left, pViewMiddle->zNear, pViewMiddle->zFar, 1.0f/headtrackFovScale ); g_pSourceVR->GetEyeProjectionMatrix ( &pViewRight->m_ViewToProjection, ISourceVirtualReality::VREye_Right, pViewMiddle->zNear, pViewMiddle->zFar, 1.0f/headtrackFovScale ); - static ConVarRef vr_distortion_grow_outside( "vr_distortion_grow_outside" ); - static ConVarRef vr_distortion_grow_inside( "vr_distortion_grow_inside" ); - static ConVarRef vr_distortion_grow_above( "vr_distortion_grow_above" ); - static ConVarRef vr_distortion_grow_below( "vr_distortion_grow_below" ); - - float StereoDistortionGrowOutside = vr_distortion_grow_outside.GetFloat(); - float StereoDistortionGrowInside = vr_distortion_grow_inside.GetFloat(); - float StereoDistortionGrowAbove = vr_distortion_grow_above.GetFloat(); - float StereoDistortionGrowBelow = vr_distortion_grow_below.GetFloat(); - if ( ( StereoDistortionGrowOutside != 0.0f ) || (StereoDistortionGrowInside != 0.0f ) ) - { - float ScaleX = 2.0f / ( StereoDistortionGrowInside + StereoDistortionGrowOutside + 2.0f ); - float OffsetX = 0.5f * ScaleX * ( StereoDistortionGrowInside - StereoDistortionGrowOutside ); - pViewLeft ->m_ViewToProjection.m[0][0] *= ScaleX; - pViewLeft ->m_ViewToProjection.m[0][2] = ( pViewLeft ->m_ViewToProjection.m[0][2] * ScaleX ) + OffsetX; - pViewRight->m_ViewToProjection.m[0][0] *= ScaleX; - pViewRight->m_ViewToProjection.m[0][2] = ( pViewRight->m_ViewToProjection.m[0][2] * ScaleX ) - OffsetX; - } - if ( ( StereoDistortionGrowAbove != 0.0f ) || (StereoDistortionGrowBelow != 0.0f ) ) - { - float ScaleY = 2.0f / ( StereoDistortionGrowBelow + StereoDistortionGrowAbove + 2.0f ); - float OffsetY = -0.5f * ScaleY * ( StereoDistortionGrowBelow - StereoDistortionGrowAbove ); // Why is this -0.5 and not +0.5? I wish I knew. - pViewLeft ->m_ViewToProjection.m[1][1] *= ScaleY; - pViewLeft ->m_ViewToProjection.m[1][2] = ( pViewLeft ->m_ViewToProjection.m[1][2] * ScaleY ) + OffsetY; - pViewRight->m_ViewToProjection.m[1][1] *= ScaleY; - pViewRight->m_ViewToProjection.m[1][2] = ( pViewRight->m_ViewToProjection.m[1][2] * ScaleY ) + OffsetY; - } - // And bodge together some sort of average for our cyclops friends. pViewMiddle->m_bViewToProjectionOverride = true; for ( int i = 0; i < 4; i++ ) diff --git a/sp/src/game/client/glow_outline_effect.cpp b/sp/src/game/client/glow_outline_effect.cpp index 600b15d7..a6d80b7f 100644 --- a/sp/src/game/client/glow_outline_effect.cpp +++ b/sp/src/game/client/glow_outline_effect.cpp @@ -312,37 +312,20 @@ void CGlowObjectManager::ApplyEntityGlowEffects( const CViewSetup *pSetup, int n void CGlowObjectManager::GlowObjectDefinition_t::DrawModel() { - C_BaseEntity *pEntity = m_hEntity.Get(); - if ( !pEntity ) - return; - - if ( pEntity->GetMoveParent() != NULL ) + if ( m_hEntity.Get() ) { - C_BaseAnimating *pBaseAnimating = pEntity->GetBaseAnimating(); - if ( pBaseAnimating ) - { - pBaseAnimating->InvalidateBoneCache(); - } - } + m_hEntity->DrawModel( STUDIO_RENDER ); + C_BaseEntity *pAttachment = m_hEntity->FirstMoveChild(); - pEntity->DrawModel( STUDIO_RENDER ); - - C_BaseEntity *pAttachment = pEntity->FirstMoveChild(); - while ( pAttachment != NULL ) - { - if ( !g_GlowObjectManager.HasGlowEffect( pAttachment ) && pAttachment->ShouldDraw() ) + while ( pAttachment != NULL ) { - C_BaseAnimating *pBaseAnimating = pAttachment->GetBaseAnimating(); - if ( pBaseAnimating ) + if ( !g_GlowObjectManager.HasGlowEffect( pAttachment ) && pAttachment->ShouldDraw() ) { - pBaseAnimating->InvalidateBoneCache(); + pAttachment->DrawModel( STUDIO_RENDER ); } - - pAttachment->DrawModel( STUDIO_RENDER ); + pAttachment = pAttachment->NextMovePeer(); } - - pAttachment = pAttachment->NextMovePeer(); } } -#endif // GLOWS_ENABLE +#endif // GLOWS_ENABLE \ No newline at end of file diff --git a/sp/src/game/client/hud_controlpointicons.cpp b/sp/src/game/client/hud_controlpointicons.cpp index 20d6150b..a8c390ae 100644 --- a/sp/src/game/client/hud_controlpointicons.cpp +++ b/sp/src/game/client/hud_controlpointicons.cpp @@ -1107,7 +1107,23 @@ void CHudControlPointIcons::PerformLayout( void ) } // Setup the main panel - SetBounds( (ScreenWidth() - iWidest) * 0.5, ScreenHeight() - iTall - m_nHeightOffset, iWidest, iTall ); + float flPositionX = (ScreenWidth() - iWidest) * 0.5; + float flPositionY = ScreenHeight() - iTall - m_nHeightOffset; + if ( ObjectiveResource() ) + { + float flCustomPositionX = -1.f; + float flCustomPositionY = -1.f; + ObjectiveResource()->GetCapLayoutCustomPosition( flCustomPositionX, flCustomPositionY ); + if ( flCustomPositionX != -1.f ) + { + flPositionX = flCustomPositionX * ScreenWidth(); + } + if ( flCustomPositionY != -1.f ) + { + flPositionY = flCustomPositionY * ScreenHeight(); + } + } + SetBounds( flPositionX, flPositionY, iWidest, iTall ); // Now that we know how wide we are, and how many icons are in each line, // we can lay the icons out, centered in the lines. diff --git a/sp/src/game/client/in_mouse.cpp b/sp/src/game/client/in_mouse.cpp index 207e7508..16cdd15e 100644 --- a/sp/src/game/client/in_mouse.cpp +++ b/sp/src/game/client/in_mouse.cpp @@ -10,9 +10,6 @@ #define _WIN32_WINNT 0x0502 #include #endif -#ifdef OSX -#include -#endif #include "cbase.h" #include "hud.h" #include "cdll_int.h" @@ -105,12 +102,7 @@ static ConVar m_mousespeed( "m_mousespeed", "1", FCVAR_ARCHIVE, "Windows mouse a static ConVar m_mouseaccel1( "m_mouseaccel1", "0", FCVAR_ARCHIVE, "Windows mouse acceleration initial threshold (2x movement).", true, 0, false, 0.0f ); static ConVar m_mouseaccel2( "m_mouseaccel2", "0", FCVAR_ARCHIVE, "Windows mouse acceleration secondary threshold (4x movement).", true, 0, false, 0.0f ); -#if defined( OSX ) -// On OSX, this needs to stick at 0. -static ConVar m_rawinput( "m_rawinput", "0", FCVAR_ARCHIVE, "Raw Mouse input is unavailable on OSX", true, 0.0, true, 0.0); -#else static ConVar m_rawinput( "m_rawinput", "0", FCVAR_ARCHIVE, "Use Raw Input for mouse input."); -#endif #if DEBUG ConVar cl_mouselook( "cl_mouselook", "1", FCVAR_ARCHIVE, "Set to 1 to use mouse for look, 0 for keyboard look." ); @@ -604,7 +596,7 @@ void CInput::AccumulateMouse( void ) m_flAccumulatedMouseXMovement += current_posx - x; m_flAccumulatedMouseYMovement += current_posy - y; -#elif defined( USE_SDL ) || defined( OSX ) +#elif defined( USE_SDL ) int dx, dy; engine->GetMouseDelta( dx, dy ); m_flAccumulatedMouseXMovement += dx; diff --git a/sp/src/game/client/input.h b/sp/src/game/client/input.h index bd371c80..00bbb02f 100644 --- a/sp/src/game/client/input.h +++ b/sp/src/game/client/input.h @@ -18,7 +18,7 @@ #include "ehandle.h" #include "inputsystem/AnalogCode.h" -typedef unsigned long CRC32_t; +typedef unsigned int CRC32_t; //----------------------------------------------------------------------------- // Purpose: diff --git a/sp/src/game/server/ai_activity.cpp b/sp/src/game/server/ai_activity.cpp index ba9c8432..25e5c441 100644 --- a/sp/src/game/server/ai_activity.cpp +++ b/sp/src/game/server/ai_activity.cpp @@ -2147,4 +2147,10 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_PRIMARY3_END ); ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_PRIMARY3_END ); ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_PRIMARY3 ); + + ADD_ACTIVITY_TO_SR( ACT_MP_THROW ); + ADD_ACTIVITY_TO_SR( ACT_THROWABLE_VM_DRAW ); + ADD_ACTIVITY_TO_SR( ACT_THROWABLE_VM_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_THROWABLE_VM_FIRE ); + } diff --git a/sp/src/game/server/ai_networkmanager.cpp b/sp/src/game/server/ai_networkmanager.cpp index 953e2884..00826e02 100644 --- a/sp/src/game/server/ai_networkmanager.cpp +++ b/sp/src/game/server/ai_networkmanager.cpp @@ -2633,7 +2633,7 @@ void CAI_NetworkBuilder::InitVisibility(CAI_Network *pNetwork, CAI_Node *pNode) if ( DebuggingConnect( pNode->m_iID, testnode ) ) { - DevMsg( "" ); // break here.. + DevMsg( " " ); // break here.. } // We know we can view ourself @@ -2814,7 +2814,7 @@ void CAI_NetworkBuilder::InitNeighbors(CAI_Network *pNetwork, CAI_Node *pNode) { if ( DebuggingConnect( pNode->m_iID, checknode ) ) { - DevMsg( "" ); // break here.. + DevMsg( " " ); // break here.. } // I'm not a neighbor of myself @@ -3204,7 +3204,7 @@ void CAI_NetworkBuilder::InitLinks(CAI_Network *pNetwork, CAI_Node *pNode) if ( DebuggingConnect( pNode->m_iID, i ) ) { - DevMsg( "" ); // break here.. + DevMsg( " " ); // break here.. } if ( !(pNode->m_eNodeInfo & bits_NODE_FALLEN) && !(pDestNode->m_eNodeInfo & bits_NODE_FALLEN) ) diff --git a/sp/src/game/server/basecombatcharacter.cpp b/sp/src/game/server/basecombatcharacter.cpp index 58767184..7fb5cce1 100644 --- a/sp/src/game/server/basecombatcharacter.cpp +++ b/sp/src/game/server/basecombatcharacter.cpp @@ -3522,6 +3522,10 @@ void CBaseCombatCharacter::ChangeTeam( int iTeamNum ) // old team member no longer in the nav mesh ClearLastKnownArea(); +#ifdef GLOWS_ENABLE + RemoveGlowEffect(); +#endif // GLOWS_ENABLE + BaseClass::ChangeTeam( iTeamNum ); } diff --git a/sp/src/game/server/baseentity.h b/sp/src/game/server/baseentity.h index 26d81804..016915ca 100644 --- a/sp/src/game/server/baseentity.h +++ b/sp/src/game/server/baseentity.h @@ -948,6 +948,7 @@ public: bool IsBSPModel() const; bool IsCombatCharacter() { return MyCombatCharacterPointer() == NULL ? false : true; } bool IsInWorld( void ) const; + virtual bool IsCombatItem( void ) const { return false; } virtual bool IsBaseCombatWeapon( void ) const { return false; } virtual bool IsWearable( void ) const { return false; } diff --git a/sp/src/game/server/cbase.cpp b/sp/src/game/server/cbase.cpp index f1f9b0d6..944e6841 100644 --- a/sp/src/game/server/cbase.cpp +++ b/sp/src/game/server/cbase.cpp @@ -278,14 +278,32 @@ void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBa if ( ev->m_flDelay ) { char szBuffer[256]; - Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), ev->m_flDelay, STRING(ev->m_iParameter) ); + Q_snprintf( szBuffer, + sizeof(szBuffer), + "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n", + engine->GetServerTime(), + pCaller ? STRING(pCaller->m_iClassname) : "NULL", + pCaller ? STRING(pCaller->GetEntityName()) : "NULL", + STRING(ev->m_iTarget), + STRING(ev->m_iTargetInput), + ev->m_flDelay, + STRING(ev->m_iParameter) ); + DevMsg( 2, "%s", szBuffer ); ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); } else { char szBuffer[256]; - Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), STRING(ev->m_iParameter) ); + Q_snprintf( szBuffer, + sizeof(szBuffer), + "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n", + engine->GetServerTime(), + pCaller ? STRING(pCaller->m_iClassname) : "NULL", + pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), + STRING(ev->m_iTargetInput), + STRING(ev->m_iParameter) ); + DevMsg( 2, "%s", szBuffer ); ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); } @@ -749,7 +767,7 @@ void CEventQueue::Dump( void ) { EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; - Msg("Dumping event queue. Current time is: %.2f\n", gpGlobals->curtime ); + Msg( "Dumping event queue. Current time is: %.2f\n", engine->GetServerTime() ); while ( pe != NULL ) { @@ -777,7 +795,7 @@ void CEventQueue::AddEvent( const char *target, const char *targetInput, variant { // build the new event EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t; - newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // priority key in the priority queue + newEvent->m_flFireTime = engine->GetServerTime() + fireDelay; // priority key in the priority queue newEvent->m_iTarget = MAKE_STRING( target ); newEvent->m_pEntTarget = NULL; newEvent->m_iTargetInput = MAKE_STRING( targetInput ); @@ -796,7 +814,7 @@ void CEventQueue::AddEvent( CBaseEntity *target, const char *targetInput, varian { // build the new event EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t; - newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // primary priority key in the priority queue + newEvent->m_flFireTime = engine->GetServerTime() + fireDelay; // primary priority key in the priority queue newEvent->m_iTarget = NULL_STRING; newEvent->m_pEntTarget = target; newEvent->m_iTargetInput = MAKE_STRING( targetInput ); @@ -867,7 +885,7 @@ void CEventQueue::ServiceEvents( void ) EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; - while ( pe != NULL && pe->m_flFireTime <= gpGlobals->curtime ) + while ( pe != NULL && pe->m_flFireTime <= engine->GetServerTime() ) { MDLCACHE_CRITICAL_SECTION(); @@ -1150,11 +1168,23 @@ int CEventQueue::Restore( IRestore &restore ) // add the restored event into the list if ( tmpEvent.m_pEntTarget ) { - AddEvent( tmpEvent.m_pEntTarget, STRING(tmpEvent.m_iTargetInput), tmpEvent.m_VariantValue, tmpEvent.m_flFireTime - gpGlobals->curtime, tmpEvent.m_pActivator, tmpEvent.m_pCaller, tmpEvent.m_iOutputID ); + AddEvent( tmpEvent.m_pEntTarget, + STRING(tmpEvent.m_iTargetInput), + tmpEvent.m_VariantValue, + tmpEvent.m_flFireTime - engine->GetServerTime(), + tmpEvent.m_pActivator, + tmpEvent.m_pCaller, + tmpEvent.m_iOutputID ); } else { - AddEvent( STRING(tmpEvent.m_iTarget), STRING(tmpEvent.m_iTargetInput), tmpEvent.m_VariantValue, tmpEvent.m_flFireTime - gpGlobals->curtime, tmpEvent.m_pActivator, tmpEvent.m_pCaller, tmpEvent.m_iOutputID ); + AddEvent( STRING(tmpEvent.m_iTarget), + STRING(tmpEvent.m_iTargetInput), + tmpEvent.m_VariantValue, + tmpEvent.m_flFireTime - engine->GetServerTime(), + tmpEvent.m_pActivator, + tmpEvent.m_pCaller, + tmpEvent.m_iOutputID ); } } diff --git a/sp/src/game/server/doors.cpp b/sp/src/game/server/doors.cpp index d44d6632..53abb829 100644 --- a/sp/src/game/server/doors.cpp +++ b/sp/src/game/server/doors.cpp @@ -21,6 +21,10 @@ #include "KeyValues.h" #endif +#ifdef TF_DLL +#include "tf_gamerules.h" +#endif // TF_DLL + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -332,6 +336,17 @@ void CBaseDoor::Spawn() } CreateVPhysics(); + +#ifdef TF_DLL + if ( TFGameRules() && TFGameRules()->IsMultiplayer() ) + { + if ( !m_flBlockDamage ) + { + // Never block doors in TF2 - to prevent various exploits. + m_flBlockDamage = 10.f; + } + } +#endif // TF_DLL } void CBaseDoor::MovingSoundThink( void ) diff --git a/sp/src/game/server/functorutils.h b/sp/src/game/server/functorutils.h index 8b4657b2..d07f0597 100644 --- a/sp/src/game/server/functorutils.h +++ b/sp/src/game/server/functorutils.h @@ -5,8 +5,10 @@ #ifndef _FUNCTOR_UTILS_H_ #define _FUNCTOR_UTILS_H_ +#ifdef NEXT_BOT #include "NextBotInterface.h" #include "NextBotManager.h" +#endif // NEXT_BOT //-------------------------------------------------------------------------------------------------------- /** @@ -321,12 +323,14 @@ inline bool ForEachActor( Functor &func ) if ( !player->IsConnected() ) continue; +#ifdef NEXT_BOT // skip bots - ForEachCombatCharacter will catch them INextBot *bot = player->MyNextBotPointer(); if ( bot ) { continue; } +#endif // NEXT_BOT if ( func( player ) == false ) { @@ -334,8 +338,12 @@ inline bool ForEachActor( Functor &func ) } } +#ifdef NEXT_BOT // iterate all NextBots return TheNextBots().ForEachCombatCharacter( func ); +#else + return true; +#endif // NEXT_BOT } @@ -385,12 +393,14 @@ inline bool ForEachActor( IActorFunctor &func ) if ( !player->IsConnected() ) continue; +#ifdef NEXT_BOT // skip bots - ForEachCombatCharacter will catch them INextBot *bot = dynamic_cast< INextBot * >( player ); if ( bot ) { continue; } +#endif // NEXT_BOT if ( func( player ) == false ) { @@ -399,11 +409,13 @@ inline bool ForEachActor( IActorFunctor &func ) } } +#ifdef NEXT_BOT if ( !isComplete ) { // iterate all NextBots isComplete = TheNextBots().ForEachCombatCharacter( func ); } +#endif // NEXT_BOT func.OnEndIteration( isComplete ); diff --git a/sp/src/game/server/gameinterface.cpp b/sp/src/game/server/gameinterface.cpp index 9f707419..b4d09bae 100644 --- a/sp/src/game/server/gameinterface.cpp +++ b/sp/src/game/server/gameinterface.cpp @@ -98,14 +98,17 @@ #include "tf/tf_gc_server.h" #include "tf_gamerules.h" #include "tf_lobby.h" -#include "player_vs_environment/tf_populator.h" +#include "player_vs_environment/tf_population_manager.h" extern ConVar tf_mm_trusted; extern ConVar tf_mm_servermode; #endif -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH #include "nav_mesh.h" +#endif + +#ifdef NEXT_BOT #include "NextBotManager.h" #endif @@ -730,7 +733,7 @@ bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory, debugoverlay = (IVDebugOverlay *)appSystemFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL ); #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH // create the Navigation Mesh interface TheNavMesh = NavMeshFactory(); #endif @@ -776,7 +779,7 @@ void CServerGameDLL::DLLShutdown( void ) #endif #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH // destroy the Navigation Mesh interface if ( TheNavMesh ) { @@ -1125,7 +1128,7 @@ void CServerGameDLL::ServerActivate( edict_t *pEdictList, int edictCount, int cl } #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH // load the Navigation Mesh for this map TheNavMesh->Load(); TheNavMesh->OnServerActivate(); @@ -1220,9 +1223,11 @@ void CServerGameDLL::GameFrame( bool simulating ) GameStartFrame(); #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH TheNavMesh->Update(); +#endif +#ifdef NEXT_BOT TheNextBots().Update(); #endif @@ -1388,7 +1393,7 @@ void CServerGameDLL::LevelShutdown( void ) g_nCurrentChapterIndex = -1; #ifndef _XBOX -#ifdef NEXT_BOT +#ifdef USE_NAV_MESH // reset the Navigation Mesh if ( TheNavMesh ) { diff --git a/sp/src/game/server/hl2/combine_mine.cpp b/sp/src/game/server/hl2/combine_mine.cpp index 6d49f94e..d3e40b56 100644 --- a/sp/src/game/server/hl2/combine_mine.cpp +++ b/sp/src/game/server/hl2/combine_mine.cpp @@ -244,7 +244,7 @@ int CBounceBomb::DrawDebugTextOverlays(void) if (m_debugOverlays & OVERLAY_TEXT_BIT) { char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr), pszMineStateNames[m_iMineState] ); + Q_snprintf(tempstr,sizeof(tempstr), "%s", pszMineStateNames[m_iMineState] ); EntityText(text_offset,tempstr,0); text_offset++; } diff --git a/sp/src/game/server/nav_area.h b/sp/src/game/server/nav_area.h index cbabe493..6eba5966 100644 --- a/sp/src/game/server/nav_area.h +++ b/sp/src/game/server/nav_area.h @@ -313,10 +313,12 @@ public: bool HasAvoidanceObstacle( float maxObstructionHeight = StepHeight ) const; // is there a large, immobile object obstructing this area float GetAvoidanceObstacleHeight( void ) const; // returns the maximum height of the obstruction above the ground +#ifdef NEXT_BOT bool HasPrerequisite( CBaseCombatCharacter *actor = NULL ) const; // return true if this area has a prerequisite that applies to the given actor const CUtlVector< CHandle< CFuncNavPrerequisite > > &GetPrerequisiteVector( void ) const; // return vector of prerequisites that must be met before this area can be traversed void RemoveAllPrerequisites( void ); void AddPrerequisite( CFuncNavPrerequisite *prereq ); +#endif void ClearAllNavCostEntities( void ); // clear set of func_nav_cost entities that affect this area void AddFuncNavCostEntity( CFuncNavCost *cost ); // add the given func_nav_cost entity to the cost of this area @@ -722,7 +724,9 @@ private: void CalcDebugID(); +#ifdef NEXT_BOT CUtlVector< CHandle< CFuncNavPrerequisite > > m_prerequisiteVector; // list of prerequisites that must be met before this area can be traversed +#endif CNavArea *m_prevHash, *m_nextHash; // for hash table in CNavMesh @@ -764,6 +768,8 @@ extern NavAreaVector TheNavAreas; // Inlines // +#ifdef NEXT_BOT + //-------------------------------------------------------------------------------------------------------------- inline bool CNavArea::HasPrerequisite( CBaseCombatCharacter *actor ) const { @@ -790,6 +796,7 @@ inline void CNavArea::AddPrerequisite( CFuncNavPrerequisite *prereq ) m_prerequisiteVector.AddToTail( prereq ); } } +#endif //-------------------------------------------------------------------------------------------------------------- inline float CNavArea::GetDangerDecayRate( void ) const diff --git a/sp/src/game/server/nav_colors.cpp b/sp/src/game/server/nav_colors.cpp index 8f2035be..50ba6cac 100644 --- a/sp/src/game/server/nav_colors.cpp +++ b/sp/src/game/server/nav_colors.cpp @@ -79,8 +79,8 @@ void NavDrawLine( const Vector& from, const Vector& to, NavEditColor navColor ) const Vector offset( 0, 0, 1 ); Color color = NavColors[navColor]; - NDebugOverlay::Line( from + offset, to + offset, color[0]/2, color[1]/2, color[2]/2, true, 0.1f ); - NDebugOverlay::Line( from + offset, to + offset, color[0], color[1], color[2], false, 0.15f ); + NDebugOverlay::Line( from + offset, to + offset, color[0], color[1], color[2], false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); + NDebugOverlay::Line( from + offset, to + offset, color[0]/2, color[1]/2, color[2]/2, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } @@ -113,8 +113,8 @@ void NavDrawHorizontalArrow( const Vector& from, const Vector& to, float width, const Vector offset( 0, 0, 1 ); Color color = NavColors[navColor]; - NDebugOverlay::HorzArrow( from + offset, to + offset, width, color[0]/2, color[1]/2, color[2]/2, 255, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); NDebugOverlay::HorzArrow( from + offset, to + offset, width, color[0], color[1], color[2], 255, false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); + NDebugOverlay::HorzArrow( from + offset, to + offset, width, color[0]/2, color[1]/2, color[2]/2, 255, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } @@ -142,8 +142,8 @@ void NavDrawDashedLine( const Vector& from, const Vector& to, NavEditColor navCo distance += solidLen + gapLen; - NDebugOverlay::Line( start + offset, end + offset, color[0]/2, color[1]/2, color[2]/2, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); NDebugOverlay::Line( start + offset, end + offset, color[0], color[1], color[2], false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); + NDebugOverlay::Line( start + offset, end + offset, color[0]/2, color[1]/2, color[2]/2, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } } diff --git a/sp/src/game/server/nav_edit.cpp b/sp/src/game/server/nav_edit.cpp index cea4e41d..512d5dda 100644 --- a/sp/src/game/server/nav_edit.cpp +++ b/sp/src/game/server/nav_edit.cpp @@ -732,9 +732,6 @@ void CNavMesh::DrawEditMode( void ) static ConVarRef host_thread_mode( "host_thread_mode" ); host_thread_mode.SetValue( 0 ); - static ConVarRef sb_perf_collect( "sb_perf_collect" ); - sb_perf_collect.SetValue( 0 ); - const float maxRange = 1000.0f; // 500 #if DEBUG_NAV_NODES @@ -908,7 +905,7 @@ void CNavMesh::DrawEditMode( void ) { V_snprintf( buffer, sizeof( buffer ), "Ladder #%d\n", m_selectedLadder->GetID() ); } - NDebugOverlay::ScreenText( 0.5, 0.53, buffer, 255, 255, 0, 128, nav_show_area_info.GetBool() ? 0.1 : 0.5 ); + NDebugOverlay::ScreenText( 0.5, 0.53, buffer, 255, 255, 0, 128, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } // draw the ladder we are pointing at and all connected areas diff --git a/sp/src/game/server/nav_entities.cpp b/sp/src/game/server/nav_entities.cpp index c7abe838..ef9366cc 100644 --- a/sp/src/game/server/nav_entities.cpp +++ b/sp/src/game/server/nav_entities.cpp @@ -96,7 +96,7 @@ void CFuncNavCost::Spawn( void ) for( char *token = strtok( buffer, " " ); token; token = strtok( NULL, " " ) ) { - m_tags.AddToTail( token ); + m_tags.AddToTail( CFmtStr( "%s", token ) ); } delete [] buffer; @@ -189,6 +189,19 @@ bool CFuncNavCost::IsApplicableTo( CBaseCombatCharacter *who ) const return true; } + // check custom bomb_carrier tags for this bot + for( int i=0; iHasTag( pszTag ) ) + { + return true; + } + } + } + // the bomb carrier only pays attention to bomb_carrier costs return false; } @@ -217,6 +230,11 @@ bool CFuncNavCost::IsApplicableTo( CBaseCombatCharacter *who ) const } } + if ( bot->HasMission( CTFBot::MISSION_REPROGRAMMED ) ) + { + return false; + } + if ( !bot->IsOnAnyMission() ) { if ( HasTag( "common" ) ) diff --git a/sp/src/game/server/nav_mesh.cpp b/sp/src/game/server/nav_mesh.cpp index 095fabb0..05cf7ff7 100644 --- a/sp/src/game/server/nav_mesh.cpp +++ b/sp/src/game/server/nav_mesh.cpp @@ -21,13 +21,15 @@ #endif #include "functorutils.h" +#ifdef NEXT_BOT #include "NextBot/NavMeshEntities/func_nav_prerequisite.h" +#endif // NOTE: This has to be the last file included! #include "tier0/memdbgon.h" -#define DrawLine( from, to, duration, red, green, blue ) NDebugOverlay::Line( from, to, red, green, blue, true, 0.1f ) +#define DrawLine( from, to, duration, red, green, blue ) NDebugOverlay::Line( from, to, red, green, blue, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ) /** @@ -42,6 +44,7 @@ ConVar nav_show_danger( "nav_show_danger", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Sh ConVar nav_show_player_counts( "nav_show_player_counts", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show current player counts in each area." ); ConVar nav_show_func_nav_avoid( "nav_show_func_nav_avoid", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show areas of designer-placed bot avoidance due to func_nav_avoid entities" ); ConVar nav_show_func_nav_prefer( "nav_show_func_nav_prefer", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show areas of designer-placed bot preference due to func_nav_prefer entities" ); +ConVar nav_show_func_nav_prerequisite( "nav_show_func_nav_prerequisite", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show areas of designer-placed bot preference due to func_nav_prerequisite entities" ); ConVar nav_max_vis_delta_list_length( "nav_max_vis_delta_list_length", "64", FCVAR_CHEAT ); extern ConVar nav_show_potentially_visible; @@ -302,6 +305,13 @@ void CNavMesh::Update( void ) DrawFuncNavPrefer(); } +#ifdef NEXT_BOT + if ( nav_show_func_nav_prerequisite.GetBool() ) + { + DrawFuncNavPrerequisite(); + } +#endif + if ( nav_show_potentially_visible.GetBool() ) { CBasePlayer *player = UTIL_GetListenServerHost(); @@ -569,6 +579,7 @@ void CNavMesh::OnServerActivate( void ) } } +#ifdef NEXT_BOT //-------------------------------------------------------------------------------------------------------------- class CRegisterPrerequisite @@ -588,6 +599,8 @@ public: CFuncNavPrerequisite *m_prereq; }; +#endif + //-------------------------------------------------------------------------------------------------------------- /** * Test all areas for blocked status @@ -609,6 +622,7 @@ void CNavMesh::OnRoundRestart( void ) { m_updateBlockedAreasTimer.Start( 1.0f ); +#ifdef NEXT_BOT FOR_EACH_VEC( TheNavAreas, pit ) { CNavArea *area = TheNavAreas[ pit ]; @@ -626,6 +640,7 @@ void CNavMesh::OnRoundRestart( void ) ForAllAreasOverlappingExtent( apply, prereqExtent ); } +#endif } @@ -1420,7 +1435,7 @@ void CNavMesh::DrawPlayerCounts( void ) const if (area->GetPlayerCount() > 0) { - NDebugOverlay::Text( area->GetCenter(), msg.sprintf( "%d (%d/%d)", area->GetPlayerCount(), area->GetPlayerCount(1), area->GetPlayerCount(2) ), false, 0.1f ); + NDebugOverlay::Text( area->GetCenter(), msg.sprintf( "%d (%d/%d)", area->GetPlayerCount(), area->GetPlayerCount(1), area->GetPlayerCount(2) ), false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } } } @@ -1462,6 +1477,26 @@ void CNavMesh::DrawFuncNavPrefer( void ) const } +#ifdef NEXT_BOT +//-------------------------------------------------------------------------------------------------------------- +/** + * Draw bot preference areas from func_nav_prerequisite entities + */ +void CNavMesh::DrawFuncNavPrerequisite( void ) const +{ + FOR_EACH_VEC( TheNavAreas, it ) + { + CNavArea *area = TheNavAreas[ it ]; + + if ( area->HasPrerequisite() ) + { + area->DrawFilled( 0, 0, 255, 255 ); + } + } +} +#endif + + //-------------------------------------------------------------------------------------------------------------- /** * Increase the danger of nav areas containing and near the given position diff --git a/sp/src/game/server/nav_mesh.h b/sp/src/game/server/nav_mesh.h index dd608792..21dc200b 100644 --- a/sp/src/game/server/nav_mesh.h +++ b/sp/src/game/server/nav_mesh.h @@ -340,7 +340,9 @@ public: void DrawPlayerCounts( void ) const; // draw the current player counts for each area void DrawFuncNavAvoid( void ) const; // draw bot avoidance areas from func_nav_avoid entities void DrawFuncNavPrefer( void ) const; // draw bot preference areas from func_nav_prefer entities - +#ifdef NEXT_BOT + void DrawFuncNavPrerequisite( void ) const; // draw bot prerequisite areas from func_nav_prerequisite entities +#endif //------------------------------------------------------------------------------------- // Auto-generation // diff --git a/sp/src/game/server/nav_mesh.vpc b/sp/src/game/server/nav_mesh.vpc new file mode 100644 index 00000000..a9af8574 --- /dev/null +++ b/sp/src/game/server/nav_mesh.vpc @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// NAV_MESH.VPC +// +// Project script for navigation mesh files (no NextBot files) +//----------------------------------------------------------------------------- + +$Configuration +{ + $Compiler + { + $PreprocessorDefinitions "$BASE;USE_NAV_MESH" + } +} + +$Project +{ + $Folder "Source Files" + { + $Folder "Navigation Mesh" + { + $File "nav.h" + $File "nav_area.cpp" + $File "nav_area.h" + $File "nav_colors.cpp" + $File "nav_colors.h" + $File "nav_edit.cpp" + $File "nav_entities.cpp" + $File "nav_entities.h" + $File "nav_file.cpp" + $File "nav_generate.cpp" + $File "nav_ladder.cpp" + $File "nav_ladder.h" + $File "nav_merge.cpp" + $File "nav_mesh.cpp" + $File "nav_mesh.h" + $File "nav_mesh_factory.cpp" + $File "nav_node.cpp" + $File "nav_node.h" + $File "nav_pathfind.h" + $File "nav_simplify.cpp" + } + } +} \ No newline at end of file diff --git a/sp/src/game/server/team_control_point_master.cpp b/sp/src/game/server/team_control_point_master.cpp index 6a579e01..662d8200 100644 --- a/sp/src/game/server/team_control_point_master.cpp +++ b/sp/src/game/server/team_control_point_master.cpp @@ -24,6 +24,9 @@ BEGIN_DATADESC( CTeamControlPointMaster ) DEFINE_KEYFIELD( m_flPartialCapturePointsRate, FIELD_FLOAT, "partial_cap_points_rate" ), + DEFINE_KEYFIELD( m_flCustomPositionX, FIELD_FLOAT, "custom_position_x" ), + DEFINE_KEYFIELD( m_flCustomPositionY, FIELD_FLOAT, "custom_position_y" ), + // DEFINE_FIELD( m_ControlPoints, CUtlMap < int , CTeamControlPoint * > ), // DEFINE_FIELD( m_bFoundPoints, FIELD_BOOLEAN ), // DEFINE_FIELD( m_ControlPointRounds, CUtlVector < CTeamControlPointRound * > ), @@ -40,6 +43,8 @@ BEGIN_DATADESC( CTeamControlPointMaster ) DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ), DEFINE_INPUTFUNC( FIELD_VOID, "RoundActivate", InputRoundActivate ), DEFINE_INPUTFUNC( FIELD_STRING, "SetCapLayout", InputSetCapLayout ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetCapLayoutCustomPositionX", InputSetCapLayoutCustomPositionX ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetCapLayoutCustomPositionY", InputSetCapLayoutCustomPositionY ), DEFINE_FUNCTION( CPMThink ), @@ -70,6 +75,8 @@ int ControlPointRoundSort( CTeamControlPointRound* const *p1, CTeamControlPointR CTeamControlPointMaster::CTeamControlPointMaster() { m_flPartialCapturePointsRate = 0.0f; + m_flCustomPositionX = -1.f; + m_flCustomPositionY = -1.f; } //----------------------------------------------------------------------------- @@ -329,6 +336,7 @@ bool CTeamControlPointMaster::FindControlPointRounds( void ) { g_pObjectiveResource->SetPlayingMiniRounds( bFoundRounds ); g_pObjectiveResource->SetCapLayoutInHUD( STRING(m_iszCapLayoutInHUD) ); + g_pObjectiveResource->SetCapLayoutCustomPosition( m_flCustomPositionX, m_flCustomPositionY ); } return bFoundRounds; @@ -837,15 +845,11 @@ void CTeamControlPointMaster::InputRoundSpawn( inputdata_t &input ) // init the ClientAreas int index = 0; - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, GetTriggerAreaCaptureName() ); - while( pEnt ) + for ( int i=0; i( ITriggerAreaCaptureAutoList::AutoList()[i] ); pArea->SetAreaIndex( index ); index++; - - pEnt = gEntList.FindEntityByClassname( pEnt, GetTriggerAreaCaptureName() ); } ObjectiveResource()->ResetControlPoints(); @@ -889,6 +893,24 @@ void CTeamControlPointMaster::InputSetCapLayout( inputdata_t &inputdata ) g_pObjectiveResource->SetCapLayoutInHUD( STRING(m_iszCapLayoutInHUD) ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTeamControlPointMaster::InputSetCapLayoutCustomPositionX( inputdata_t &inputdata ) +{ + m_flCustomPositionX = inputdata.value.Float(); + g_pObjectiveResource->SetCapLayoutCustomPosition( m_flCustomPositionX, m_flCustomPositionY ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTeamControlPointMaster::InputSetCapLayoutCustomPositionY( inputdata_t &inputdata ) +{ + m_flCustomPositionY = inputdata.value.Float(); + g_pObjectiveResource->SetCapLayoutCustomPosition( m_flCustomPositionX, m_flCustomPositionY ); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/sp/src/game/server/team_control_point_master.h b/sp/src/game/server/team_control_point_master.h index 48265ba6..64b1e9b5 100644 --- a/sp/src/game/server/team_control_point_master.h +++ b/sp/src/game/server/team_control_point_master.h @@ -36,7 +36,6 @@ public: CTeamControlPointMaster(); // Used to find game specific entities - virtual const char *GetTriggerAreaCaptureName( void ) { return "trigger_capture_area"; } virtual const char *GetControlPointName( void ) { return "team_control_point"; } virtual const char *GetControlPointRoundName( void ) { return "team_control_point_round"; } @@ -182,6 +181,8 @@ private: void InputSetWinner( inputdata_t &inputdata ); void InputSetWinnerAndForceCaps( inputdata_t &inputdata ); void InputSetCapLayout( inputdata_t &inputdata ); + void InputSetCapLayoutCustomPositionX( inputdata_t &inputdata ); + void InputSetCapLayoutCustomPositionY( inputdata_t &inputdata ); void InternalSetWinner( int iTeam ); @@ -191,6 +192,9 @@ private: int m_iTeamBaseIcons[MAX_TEAMS]; string_t m_iszCapLayoutInHUD; + float m_flCustomPositionX; + float m_flCustomPositionY; + int m_iInvalidCapWinner; bool m_bSwitchTeamsOnWin; bool m_bScorePerCapture; diff --git a/sp/src/game/server/team_control_point_round.cpp b/sp/src/game/server/team_control_point_round.cpp index cc3d0cc7..c9e36bd7 100644 --- a/sp/src/game/server/team_control_point_round.cpp +++ b/sp/src/game/server/team_control_point_round.cpp @@ -365,33 +365,27 @@ bool CTeamControlPointRound::MakePlayable( void ) if ( !IsPlayable() ) { // we need to try switching the owners of the teams to make this round playable - for ( int i = FIRST_GAME_TEAM ; i < GetNumberOfTeams() ; i++ ) + for ( int iTeam = FIRST_GAME_TEAM ; iTeam < GetNumberOfTeams() ; iTeam++ ) { - for ( int j = 0 ; j < m_ControlPoints.Count() ; j++ ) + for ( int iControlPoint = 0 ; iControlPoint < m_ControlPoints.Count() ; iControlPoint++ ) { - if ( ( !pMaster->IsBaseControlPoint( m_ControlPoints[j]->GetPointIndex() ) ) && // this is NOT the base point for one of the teams (we don't want to assign the base to the wrong team) - ( !WouldNewCPOwnerWinGame( m_ControlPoints[j], i ) ) ) // making this change would make this round playable + if ( ( !pMaster->IsBaseControlPoint( m_ControlPoints[iControlPoint]->GetPointIndex() ) ) && // this is NOT the base point for one of the teams (we don't want to assign the base to the wrong team) + ( !WouldNewCPOwnerWinGame( m_ControlPoints[iControlPoint], iTeam ) ) ) // making this change would make this round playable { // need to find the trigger area associated with this point - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, pMaster->GetTriggerAreaCaptureName() ); - while( pEnt ) + for ( int iObj=0; iObj( pEnt ); - if ( pArea ) - { - if ( pArea->TeamCanCap( i ) ) + CTriggerAreaCapture *pArea = static_cast< CTriggerAreaCapture * >( ITriggerAreaCaptureAutoList::AutoList()[iObj] ); + if ( pArea->TeamCanCap( iTeam ) ) + { + CHandle hPoint = pArea->GetControlPoint(); + if ( hPoint == m_ControlPoints[iControlPoint] ) { - CHandle hPoint = pArea->GetControlPoint(); - if ( hPoint == m_ControlPoints[j] ) - { - // found! - pArea->ForceOwner( i ); // this updates the trigger_area *and* the control_point - return true; - } + // found! + pArea->ForceOwner( iTeam ); // this updates the trigger_area *and* the control_point + return true; } } - - pEnt = gEntList.FindEntityByClassname( pEnt, pMaster->GetTriggerAreaCaptureName() ); } } } diff --git a/sp/src/game/server/team_objectiveresource.cpp b/sp/src/game/server/team_objectiveresource.cpp index 9f8d0e7f..f7dd502e 100644 --- a/sp/src/game/server/team_objectiveresource.cpp +++ b/sp/src/game/server/team_objectiveresource.cpp @@ -61,7 +61,10 @@ IMPLEMENT_SERVERCLASS_ST_NOBASE(CBaseTeamObjectiveResource, DT_BaseTeamObjective SendPropArray3( SENDINFO_ARRAY3(m_iTeamInZone), SendPropInt( SENDINFO_ARRAY(m_iTeamInZone), 4, SPROP_UNSIGNED ) ), SendPropArray3( SENDINFO_ARRAY3(m_bBlocked), SendPropInt( SENDINFO_ARRAY(m_bBlocked), 1, SPROP_UNSIGNED ) ), SendPropArray3( SENDINFO_ARRAY3(m_iOwner), SendPropInt( SENDINFO_ARRAY(m_iOwner), 4, SPROP_UNSIGNED ) ), + SendPropArray3( SENDINFO_ARRAY3(m_bCPCapRateScalesWithPlayers), SendPropBool( SENDINFO_ARRAY(m_bCPCapRateScalesWithPlayers) ) ), SendPropString( SENDINFO(m_pszCapLayoutInHUD) ), + SendPropFloat( SENDINFO( m_flCustomPositionX ) ), + SendPropFloat( SENDINFO( m_flCustomPositionY ) ), END_SEND_TABLE() @@ -72,6 +75,8 @@ BEGIN_DATADESC( CBaseTeamObjectiveResource ) DEFINE_FIELD( m_bPlayingMiniRounds, FIELD_BOOLEAN ), DEFINE_FIELD( m_bControlPointsReset, FIELD_BOOLEAN ), DEFINE_FIELD( m_iUpdateCapHudParity, FIELD_INTEGER ), + DEFINE_FIELD( m_flCustomPositionX, FIELD_FLOAT ), + DEFINE_FIELD( m_flCustomPositionY, FIELD_FLOAT ), DEFINE_ARRAY( m_vCPPositions, FIELD_VECTOR, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_bCPIsVisible, FIELD_INTEGER, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_flLazyCapPerc, FIELD_FLOAT, MAX_CONTROL_POINTS ), @@ -91,6 +96,7 @@ BEGIN_DATADESC( CBaseTeamObjectiveResource ) DEFINE_ARRAY( m_iTeamInZone, FIELD_INTEGER, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_bBlocked, FIELD_BOOLEAN, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_iOwner, FIELD_INTEGER, MAX_CONTROL_POINTS ), + DEFINE_ARRAY( m_bCPCapRateScalesWithPlayers, FIELD_BOOLEAN, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_pszCapLayoutInHUD, FIELD_CHARACTER, MAX_CAPLAYOUT_LENGTH ), DEFINE_ARRAY( m_flCapPercentages, FIELD_FLOAT, MAX_CONTROL_POINTS ), DEFINE_ARRAY( m_iCPGroup, FIELD_INTEGER, MAX_CONTROL_POINTS ), @@ -114,6 +120,8 @@ CBaseTeamObjectiveResource::CBaseTeamObjectiveResource() m_bPlayingMiniRounds = false; m_iUpdateCapHudParity = 0; m_bControlPointsReset = false; + m_flCustomPositionX = -1.f; + m_flCustomPositionY = -1.f; } //----------------------------------------------------------------------------- @@ -153,6 +161,7 @@ void CBaseTeamObjectiveResource::Spawn( void ) m_bCPLocked.Set( i, false ); m_flUnlockTimes.Set( i, 0.0 ); m_flCPTimerTimes.Set( i, -1.0 ); + m_bCPCapRateScalesWithPlayers.Set( i, true ); for ( int team = 0; team < MAX_CONTROL_POINT_TEAMS; team++ ) { @@ -381,6 +390,15 @@ void CBaseTeamObjectiveResource::SetCPTimerTime( int index, float flTime ) m_flCPTimerTimes.Set( index, flTime ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseTeamObjectiveResource::SetCPCapTimeScalesWithPlayers( int index, bool bScales ) +{ + AssertValidIndex(index); + m_bCPCapRateScalesWithPlayers.Set( index, bScales ); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/sp/src/game/server/team_objectiveresource.h b/sp/src/game/server/team_objectiveresource.h index 40d1920c..5cc42009 100644 --- a/sp/src/game/server/team_objectiveresource.h +++ b/sp/src/game/server/team_objectiveresource.h @@ -58,6 +58,7 @@ public: int GetPreviousPointForPoint( int index, int team, int iPrevIndex ); bool TeamCanCapPoint( int index, int team ); void SetCapLayoutInHUD( const char *pszLayout ) { Q_strncpy(m_pszCapLayoutInHUD.GetForModify(), pszLayout, MAX_CAPLAYOUT_LENGTH ); } + void SetCapLayoutCustomPosition( float flPositionX, float flPositionY ) { m_flCustomPositionX = flPositionX; m_flCustomPositionY = flPositionY; } void SetWarnOnCap( int index, int iWarnLevel ); void SetWarnSound( int index, string_t iszSound ); void SetCPGroup( int index, int iCPGroup ); @@ -65,6 +66,7 @@ public: void SetTrackAlarm( int index, bool bAlarm ); void SetCPUnlockTime( int index, float flTime ); void SetCPTimerTime( int index, float flTime ); + void SetCPCapTimeScalesWithPlayers( int index, bool bScales ); // State functions, called many times void SetNumPlayers( int index, int team, int iNumPlayers ); @@ -205,10 +207,15 @@ private: // changes when a point is successfully captured CNetworkArray( int, m_iOwner, MAX_CONTROL_POINTS ); + CNetworkArray( bool, m_bCPCapRateScalesWithPlayers, MAX_CONTROL_POINTS ); // describes how to lay out the cap points in the hud CNetworkString( m_pszCapLayoutInHUD, MAX_CAPLAYOUT_LENGTH ); + // custom screen position for the cap points in the hud + CNetworkVar( float, m_flCustomPositionX ); + CNetworkVar( float, m_flCustomPositionY ); + // the groups the points belong to CNetworkArray( int, m_iCPGroup, MAX_CONTROL_POINTS ); diff --git a/sp/src/game/server/team_train_watcher.cpp b/sp/src/game/server/team_train_watcher.cpp index 27d7a15c..cf6631fb 100644 --- a/sp/src/game/server/team_train_watcher.cpp +++ b/sp/src/game/server/team_train_watcher.cpp @@ -819,17 +819,15 @@ void CTeamTrainWatcher::WatcherActivate( void ) { if ( m_hTrain ) { - CTriggerAreaCapture *pArea = dynamic_cast( gEntList.FindEntityByClassname( NULL, "trigger_capture_area" ) ); - while( pArea ) + for ( int i=0; i( ITriggerAreaCaptureAutoList::AutoList()[i] ); if ( pArea->GetParent() == m_hTrain.Get() ) { // this is the capture area we care about, so let it know that we want updates on the capture numbers pArea->SetTrainWatcher( this ); break; } - - pArea = dynamic_cast( gEntList.FindEntityByClassname( pArea, "trigger_capture_area" ) ); } } diff --git a/sp/src/game/server/trigger_area_capture.cpp b/sp/src/game/server/trigger_area_capture.cpp index fcf3a868..665bd005 100644 --- a/sp/src/game/server/trigger_area_capture.cpp +++ b/sp/src/game/server/trigger_area_capture.cpp @@ -18,10 +18,12 @@ extern ConVar mp_capstyle; extern ConVar mp_blockstyle; extern ConVar mp_capdeteriorate_time; +IMPLEMENT_AUTO_LIST( ITriggerAreaCaptureAutoList ); + BEGIN_DATADESC(CTriggerAreaCapture) // Touch functions - DEFINE_FUNCTION( AreaTouch ), + DEFINE_FUNCTION( CTriggerAreaCaptureShim::Touch ), // Think functions DEFINE_THINKFUNC( CaptureThink ), @@ -96,7 +98,7 @@ void CTriggerAreaCapture::Spawn( void ) m_iAreaIndex = -1; - SetTouch ( &CTriggerAreaCapture::AreaTouch ); + SetTouch ( &CTriggerAreaCaptureShim::Touch ); SetThink( &CTriggerAreaCapture::CaptureThink ); SetNextThink( gpGlobals->curtime + AREA_THINK_TIME ); @@ -250,6 +252,14 @@ void CTriggerAreaCapture::EndTouch(CBaseEntity *pOther) BaseClass::EndTouch( pOther ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTriggerAreaCapture::CaptureModeScalesWithPlayers() const +{ + return mp_capstyle.GetBool(); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -469,7 +479,7 @@ void CTriggerAreaCapture::CaptureThink( void ) float flTimeDelta = gpGlobals->curtime - m_flLastReductionTime; float flReduction = flTimeDelta; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { // Diminishing returns for successive players. for ( int i = 1; i < m_TeamData[m_nTeamInZone].iNumTouching; i++ ) @@ -490,7 +500,7 @@ void CTriggerAreaCapture::CaptureThink( void ) // See if anyone gets credit for the block float flPercentToGo = m_fTimeRemaining / m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { flPercentToGo = m_fTimeRemaining / ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); } @@ -561,7 +571,7 @@ void CTriggerAreaCapture::CaptureThink( void ) } float flTotalTimeToCap = m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { flTotalTimeToCap = ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); } @@ -580,7 +590,8 @@ void CTriggerAreaCapture::CaptureThink( void ) // Caps deteriorate over time if ( TeamplayRoundBasedRules() && m_hPoint && TeamplayRoundBasedRules()->TeamMayCapturePoint(m_nCapturingTeam,m_hPoint->GetPointIndex()) ) { - float flDecrease = (flTotalTimeToCap / mp_capdeteriorate_time.GetFloat()) * flTimeDelta; + float flDecreaseScale = CaptureModeScalesWithPlayers() ? mp_capdeteriorate_time.GetFloat() : flTotalTimeToCap; + float flDecrease = (flTotalTimeToCap / flDecreaseScale) * flTimeDelta; if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->InOvertime() ) { flDecrease *= 6; @@ -649,7 +660,7 @@ void CTriggerAreaCapture::CaptureThink( void ) if ( m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToStartCap ) continue; - if ( mp_capstyle.GetInt() == 0 && m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToCap ) + if ( !CaptureModeScalesWithPlayers() && m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToCap ) continue; StartCapture( i, CAPTURE_NORMAL ); @@ -670,7 +681,7 @@ void CTriggerAreaCapture::SetCapTimeRemaining( float flTime ) if ( m_nCapturingTeam ) { flCapPercentage = m_fTimeRemaining / m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { flCapPercentage = m_fTimeRemaining / ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); } @@ -762,7 +773,7 @@ void CTriggerAreaCapture::StartCapture( int team, int capmode ) UpdateNumPlayers(); - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { SetCapTimeRemaining( ((m_flCapTime * 2) * m_TeamData[team].iNumRequiredToCap) ); } @@ -1017,7 +1028,7 @@ void CTriggerAreaCapture::InputRoundSpawn( inputdata_t &inputdata ) ObjectiveResource()->SetCPRequiredCappers( m_hPoint->GetPointIndex(), i, m_TeamData[i].iNumRequiredToCap ); ObjectiveResource()->SetTeamCanCap( m_hPoint->GetPointIndex(), i, m_TeamData[i].bCanCap ); - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { ObjectiveResource()->SetCPCapTime( m_hPoint->GetPointIndex(), i, (m_flCapTime * 2) * m_TeamData[i].iNumRequiredToCap ); } @@ -1025,6 +1036,8 @@ void CTriggerAreaCapture::InputRoundSpawn( inputdata_t &inputdata ) { ObjectiveResource()->SetCPCapTime( m_hPoint->GetPointIndex(), i, m_flCapTime ); } + + ObjectiveResource()->SetCPCapTimeScalesWithPlayers( m_hPoint->GetPointIndex(), CaptureModeScalesWithPlayers() ); } } } @@ -1125,7 +1138,7 @@ bool CTriggerAreaCapture::CheckIfDeathCausesBlock( CBaseMultiplayerPlayer *pVict // break early incase we kill multiple people in the same frame bool bBreakCap = false; - if ( mp_capstyle.GetInt() == 1 ) + if ( CaptureModeScalesWithPlayers() ) { bBreakCap = ( m_TeamData[m_nCapturingTeam].iBlockedTouching - 1 ) <= 0; } diff --git a/sp/src/game/server/trigger_area_capture.h b/sp/src/game/server/trigger_area_capture.h index e2e494c9..383f3fad 100644 --- a/sp/src/game/server/trigger_area_capture.h +++ b/sp/src/game/server/trigger_area_capture.h @@ -32,9 +32,19 @@ class CTeamTrainWatcher; // Can either be capped by both teams at once, or just by one // Time to capture and number of people required to capture are both passed by the mapper //----------------------------------------------------------------------------- -class CTriggerAreaCapture : public CBaseTrigger +// This class is to get around the fact that DEFINE_FUNCTION doesn't like multiple inheritance +class CTriggerAreaCaptureShim : public CBaseTrigger { - DECLARE_CLASS( CTriggerAreaCapture, CBaseTrigger ); + virtual void AreaTouch( CBaseEntity *pOther ) = 0; +public: + void Touch( CBaseEntity *pOther ) { return AreaTouch( pOther ) ; } +}; + +DECLARE_AUTO_LIST( ITriggerAreaCaptureAutoList ); + +class CTriggerAreaCapture : public CTriggerAreaCaptureShim, public ITriggerAreaCaptureAutoList +{ + DECLARE_CLASS( CTriggerAreaCapture, CTriggerAreaCaptureShim ); public: CTriggerAreaCapture(); @@ -73,10 +83,17 @@ public: void SetTrainWatcher( CTeamTrainWatcher *pTrainWatcher ){ m_hTrainWatcher = pTrainWatcher; } // used for train watchers that control train movement CTeamTrainWatcher *GetTrainWatcher( void ) const { return m_hTrainWatcher; } + virtual void StartTouch(CBaseEntity *pOther) OVERRIDE; + virtual void EndTouch(CBaseEntity *pOther) OVERRIDE; + + float GetCapTime() const { return m_flCapTime; } + +protected: + + virtual bool CaptureModeScalesWithPlayers() const; + private: - void StartTouch(CBaseEntity *pOther); - void EXPORT AreaTouch( CBaseEntity *pOther ); - void EndTouch(CBaseEntity *pOther); + virtual void AreaTouch( CBaseEntity *pOther ) OVERRIDE; void CaptureThink( void ); void StartCapture( int team, int capmode ); diff --git a/sp/src/game/server/vote_controller.cpp b/sp/src/game/server/vote_controller.cpp index f2c8e2f4..a2fcfd99 100644 --- a/sp/src/game/server/vote_controller.cpp +++ b/sp/src/game/server/vote_controller.cpp @@ -346,6 +346,19 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons Assert( nNumVoteOptions >= 2 ); } + // Have the issue start working on it + pCurrentIssue->OnVoteStarted(); + + // Now the vote handling and UI + m_nPotentialVotes = pCurrentIssue->CountPotentialVoters(); + m_acceptingVotesTimer.Start( sv_vote_timer_duration.GetFloat() ); + + // Force the vote holder to agree with a Yes/No vote + if ( m_bIsYesNoVote && !bDedicatedServer ) + { + TryCastVote( iEntIndex, "Option1" ); + } + // Get the data out to the client CBroadcastRecipientFilter filter; filter.MakeReliable(); @@ -357,16 +370,6 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons WRITE_BOOL( m_bIsYesNoVote ); MessageEnd(); - // Force the vote holder to agree with a Yes/No vote - if ( m_bIsYesNoVote && !bDedicatedServer ) - { - TryCastVote( iEntIndex, "Option1" ); - } - - m_nPotentialVotes = pCurrentIssue->CountPotentialVoters(); - m_acceptingVotesTimer.Start( sv_vote_timer_duration.GetFloat() ); - pCurrentIssue->OnVoteStarted(); - if ( !bDedicatedServer ) { TrackVoteCaller( pVoteCaller ); diff --git a/sp/src/game/shared/activitylist.cpp b/sp/src/game/shared/activitylist.cpp index 1b61fb64..a69933c9 100644 --- a/sp/src/game/shared/activitylist.cpp +++ b/sp/src/game/shared/activitylist.cpp @@ -2265,6 +2265,11 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_MP_RELOAD_AIRWALK_PRIMARY3_END ); REGISTER_SHARED_ACTIVITY( ACT_MP_RELOAD_SWIM_PRIMARY3 ); + REGISTER_SHARED_ACTIVITY( ACT_MP_THROW ); + REGISTER_SHARED_ACTIVITY( ACT_THROWABLE_VM_DRAW ); + REGISTER_SHARED_ACTIVITY( ACT_THROWABLE_VM_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_THROWABLE_VM_FIRE ); + AssertMsg( g_HighestActivity == LAST_SHARED_ACTIVITY - 1, "Not all activities from ai_activity.h registered in activitylist.cpp" ); } diff --git a/sp/src/game/shared/ai_activity.h b/sp/src/game/shared/ai_activity.h index 854da726..4e94fca8 100644 --- a/sp/src/game/shared/ai_activity.h +++ b/sp/src/game/shared/ai_activity.h @@ -2095,6 +2095,13 @@ typedef enum ACT_MP_RELOAD_AIRWALK_PRIMARY3_END, ACT_MP_RELOAD_SWIM_PRIMARY3, + // Throwable Animations + ACT_MP_THROW, + + ACT_THROWABLE_VM_DRAW, + ACT_THROWABLE_VM_IDLE, + ACT_THROWABLE_VM_FIRE, + // this is the end of the global activities, private per-monster activities start here. LAST_SHARED_ACTIVITY, } Activity; diff --git a/sp/src/game/shared/baseentity_shared.cpp b/sp/src/game/shared/baseentity_shared.cpp index 470b2d2e..949143b1 100644 --- a/sp/src/game/shared/baseentity_shared.cpp +++ b/sp/src/game/shared/baseentity_shared.cpp @@ -48,6 +48,11 @@ ConVar hl2_episodic( "hl2_episodic", "0", FCVAR_REPLICATED ); #include "prop_portal_shared.h" #endif +#ifdef TF_DLL +#include "tf_gamerules.h" +#include "tf_weaponbase.h" +#endif // TF_DLL + #include "rumble_shared.h" // memdbgon must be the last include file in a .cpp file!!! @@ -1746,6 +1751,17 @@ void CBaseEntity::FireBullets( const FireBulletsInfo_t &info ) { pShootThroughPortal = NULL; } +#elif TF_DLL + CTraceFilterIgnoreFriendlyCombatItems traceFilterCombatItem( this, COLLISION_GROUP_NONE, GetTeamNumber() ); + if ( TFGameRules() && TFGameRules()->GameModeUsesUpgrades() ) + { + CTraceFilterChain traceFilterChain( &traceFilter, &traceFilterCombatItem ); + AI_TraceLine(info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilterChain, &tr); + } + else + { + AI_TraceLine(info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilter, &tr); + } #else AI_TraceLine(info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilter, &tr); #endif //#ifdef PORTAL diff --git a/sp/src/game/shared/gamerules.h b/sp/src/game/shared/gamerules.h index 7564ca59..a8f4c35b 100644 --- a/sp/src/game/shared/gamerules.h +++ b/sp/src/game/shared/gamerules.h @@ -178,11 +178,13 @@ public: virtual void ClientCommandKeyValues( edict_t *pEntity, KeyValues *pKeyValues ) {} - // IsConnectedUserInfoChangeAllowed allows to override FCVAR_NOT_CONNECTED rule when - // player is on team spectator or team unassigned for example - // Default and previous engine implementation will never allow FCVAR_NOT_CONNECTED cvars - // to be changed while connected to a game server - virtual bool IsConnectedUserInfoChangeAllowed( CBasePlayer *pPlayer ) { return !IsMultiplayer(); } + // IsConnectedUserInfoChangeAllowed allows the clients to change + // cvars with the FCVAR_NOT_CONNECTED rule if it returns true + virtual bool IsConnectedUserInfoChangeAllowed( CBasePlayer *pPlayer ) + { + Assert( !IsMultiplayer() ); + return true; + } #ifdef CLIENT_DLL diff --git a/sp/src/game/shared/hl2mp/hl2mp_gamerules.cpp b/sp/src/game/shared/hl2mp/hl2mp_gamerules.cpp index abb36cae..1b7cf70f 100644 --- a/sp/src/game/shared/hl2mp/hl2mp_gamerules.cpp +++ b/sp/src/game/shared/hl2mp/hl2mp_gamerules.cpp @@ -844,7 +844,11 @@ const char *CHL2MPRules::GetGameDescription( void ) return "Deathmatch"; } - +bool CHL2MPRules::IsConnectedUserInfoChangeAllowed( CBasePlayer *pPlayer ) +{ + return true; +} + float CHL2MPRules::GetMapRemainingTime() { // if timelimit is disabled, return 0 diff --git a/sp/src/game/shared/hl2mp/hl2mp_gamerules.h b/sp/src/game/shared/hl2mp/hl2mp_gamerules.h index 84f83999..8cadeab0 100644 --- a/sp/src/game/shared/hl2mp/hl2mp_gamerules.h +++ b/sp/src/game/shared/hl2mp/hl2mp_gamerules.h @@ -145,6 +145,8 @@ public: bool IsTeamplay( void ) { return m_bTeamPlayEnabled; } void CheckAllPlayersReady( void ); + + virtual bool IsConnectedUserInfoChangeAllowed( CBasePlayer *pPlayer ); private: diff --git a/sp/src/game/shared/multiplay_gamerules.cpp b/sp/src/game/shared/multiplay_gamerules.cpp index f933634c..2cbb6f61 100644 --- a/sp/src/game/shared/multiplay_gamerules.cpp +++ b/sp/src/game/shared/multiplay_gamerules.cpp @@ -1223,7 +1223,7 @@ ConVarRef suitcharger( "sk_suitcharger" ); { if ( bForceSpew || V_stricmp( szLastResult, pszResult) ) { - Msg( "Using map cycle file %s.\n", pszResult ); + Msg( "Using map cycle file '%s'.\n", pszResult ); V_strcpy_safe( szLastResult, pszResult ); } return; diff --git a/sp/src/game/shared/particle_property.cpp b/sp/src/game/shared/particle_property.cpp index b1ae32a7..18d278ad 100644 --- a/sp/src/game/shared/particle_property.cpp +++ b/sp/src/game/shared/particle_property.cpp @@ -26,6 +26,12 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" +#ifdef STAGING_ONLY +#ifdef TF_CLIENT_DLL +extern ConVar tf_unusual_effect_offset; +#endif +#endif + //----------------------------------------------------------------------------- // Save/load //----------------------------------------------------------------------------- diff --git a/sp/src/game/shared/playernet_vars.h b/sp/src/game/shared/playernet_vars.h index abb49765..9fdeec0f 100644 --- a/sp/src/game/shared/playernet_vars.h +++ b/sp/src/game/shared/playernet_vars.h @@ -77,10 +77,10 @@ struct fogplayerparams_t { m_hCtrl.Set( NULL ); m_flTransitionTime = -1.0f; - m_OldColor.r = m_OldColor.g = m_OldColor.b = m_OldColor.a = 0; + m_OldColor.r = m_OldColor.g = m_OldColor.g = m_OldColor.a = 0.0f; m_flOldStart = 0.0f; m_flOldEnd = 0.0f; - m_NewColor.r = m_NewColor.g = m_NewColor.b = m_NewColor.a = 0; + m_NewColor.r = m_NewColor.g = m_NewColor.g = m_NewColor.a = 0.0f; m_flNewStart = 0.0f; m_flNewEnd = 0.0f; } diff --git a/sp/src/game/shared/teamplay_round_timer.h b/sp/src/game/shared/teamplay_round_timer.h index 7826cf5b..470a5f16 100644 --- a/sp/src/game/shared/teamplay_round_timer.h +++ b/sp/src/game/shared/teamplay_round_timer.h @@ -79,6 +79,7 @@ public: void SetStopWatch( bool bState ) { m_bStopWatchTimer = bState; } bool IsStopWatchTimer( void ) { return m_bStopWatchTimer; } float GetStopWatchTotalTime( void ) { return m_flTotalTime; } + bool IsRoundMaxTimerSet( void ) { return m_nTimerMaxLength > 0; } private: diff --git a/sp/src/game/shared/teamplayroundbased_gamerules.cpp b/sp/src/game/shared/teamplayroundbased_gamerules.cpp index f737aecf..a843d134 100644 --- a/sp/src/game/shared/teamplayroundbased_gamerules.cpp +++ b/sp/src/game/shared/teamplayroundbased_gamerules.cpp @@ -38,7 +38,7 @@ #if defined(TF_CLIENT_DLL) || defined(TF_DLL) #include "tf_lobby.h" #ifdef GAME_DLL - #include "player_vs_environment/tf_populator.h" + #include "player_vs_environment/tf_population_manager.h" #include "../server/tf/tf_gc_server.h" #include "../server/tf/tf_objective_resource.h" #else diff --git a/sp/src/game/shared/voice_status.cpp b/sp/src/game/shared/voice_status.cpp index 4d295713..ed6c0f2f 100644 --- a/sp/src/game/shared/voice_status.cpp +++ b/sp/src/game/shared/voice_status.cpp @@ -425,7 +425,7 @@ void CVoiceStatus::UpdateServerState(bool bForce) void CVoiceStatus::HandleVoiceMaskMsg(bf_read &msg) { - unsigned long dw; + unsigned int dw; for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) { m_AudiblePlayers.SetDWord(dw, (unsigned long)msg.ReadLong()); @@ -434,8 +434,8 @@ void CVoiceStatus::HandleVoiceMaskMsg(bf_read &msg) if( voice_clientdebug.GetInt()) { Msg("CVoiceStatus::HandleVoiceMaskMsg\n"); - Msg(" - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord(dw)); - Msg(" - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord(dw)); + Msg(" - m_AudiblePlayers[%d] = %u\n", dw, m_AudiblePlayers.GetDWord(dw)); + Msg(" - m_ServerBannedPlayers[%d] = %u\n", dw, m_ServerBannedPlayers.GetDWord(dw)); } } diff --git a/sp/src/lib/osx32/bitmap.a b/sp/src/lib/osx32/bitmap.a index fa34175a..0e5e6579 100644 Binary files a/sp/src/lib/osx32/bitmap.a and b/sp/src/lib/osx32/bitmap.a differ diff --git a/sp/src/lib/osx32/choreoobjects.a b/sp/src/lib/osx32/choreoobjects.a index 7a98cea8..3b49b444 100644 Binary files a/sp/src/lib/osx32/choreoobjects.a and b/sp/src/lib/osx32/choreoobjects.a differ diff --git a/sp/src/lib/osx32/dmxloader.a b/sp/src/lib/osx32/dmxloader.a index c3c36bdc..072ac679 100644 Binary files a/sp/src/lib/osx32/dmxloader.a and b/sp/src/lib/osx32/dmxloader.a differ diff --git a/sp/src/lib/osx32/libtier0.dylib b/sp/src/lib/osx32/libtier0.dylib index d9735016..860f2115 100644 Binary files a/sp/src/lib/osx32/libtier0.dylib and b/sp/src/lib/osx32/libtier0.dylib differ diff --git a/sp/src/lib/osx32/libvstdlib.dylib b/sp/src/lib/osx32/libvstdlib.dylib index 11aa4615..7afad64e 100644 Binary files a/sp/src/lib/osx32/libvstdlib.dylib and b/sp/src/lib/osx32/libvstdlib.dylib differ diff --git a/sp/src/lib/osx32/matsys_controls.a b/sp/src/lib/osx32/matsys_controls.a index af3e6dbd..99b94c5d 100644 Binary files a/sp/src/lib/osx32/matsys_controls.a and b/sp/src/lib/osx32/matsys_controls.a differ diff --git a/sp/src/lib/osx32/particles.a b/sp/src/lib/osx32/particles.a index bc1ca109..0b0ffe95 100644 Binary files a/sp/src/lib/osx32/particles.a and b/sp/src/lib/osx32/particles.a differ diff --git a/sp/src/lib/osx32/tier2.a b/sp/src/lib/osx32/tier2.a index 35d6f3e9..b9140f10 100644 Binary files a/sp/src/lib/osx32/tier2.a and b/sp/src/lib/osx32/tier2.a differ diff --git a/sp/src/lib/osx32/tier3.a b/sp/src/lib/osx32/tier3.a index f6b69894..a53ba55e 100644 Binary files a/sp/src/lib/osx32/tier3.a and b/sp/src/lib/osx32/tier3.a differ diff --git a/sp/src/lib/osx32/vtf.a b/sp/src/lib/osx32/vtf.a index a504702a..977a3b12 100644 Binary files a/sp/src/lib/osx32/vtf.a and b/sp/src/lib/osx32/vtf.a differ diff --git a/sp/src/lib/public/appframework.lib b/sp/src/lib/public/appframework.lib index 785671ff..fb77a6ae 100644 Binary files a/sp/src/lib/public/appframework.lib and b/sp/src/lib/public/appframework.lib differ diff --git a/sp/src/lib/public/bitmap.lib b/sp/src/lib/public/bitmap.lib index d090c73f..739247df 100644 Binary files a/sp/src/lib/public/bitmap.lib and b/sp/src/lib/public/bitmap.lib differ diff --git a/sp/src/lib/public/choreoobjects.lib b/sp/src/lib/public/choreoobjects.lib index 231f9917..e02fca9b 100644 Binary files a/sp/src/lib/public/choreoobjects.lib and b/sp/src/lib/public/choreoobjects.lib differ diff --git a/sp/src/lib/public/dmxloader.lib b/sp/src/lib/public/dmxloader.lib index e5e79056..20bd9a64 100644 Binary files a/sp/src/lib/public/dmxloader.lib and b/sp/src/lib/public/dmxloader.lib differ diff --git a/sp/src/lib/public/fgdlib.lib b/sp/src/lib/public/fgdlib.lib index 9ae43bbc..3531cd7f 100644 Binary files a/sp/src/lib/public/fgdlib.lib and b/sp/src/lib/public/fgdlib.lib differ diff --git a/sp/src/lib/public/linux32/bitmap.a b/sp/src/lib/public/linux32/bitmap.a index 7df39459..35c6d4b2 100644 Binary files a/sp/src/lib/public/linux32/bitmap.a and b/sp/src/lib/public/linux32/bitmap.a differ diff --git a/sp/src/lib/public/linux32/choreoobjects.a b/sp/src/lib/public/linux32/choreoobjects.a index 623b3caf..dfd22f5e 100644 Binary files a/sp/src/lib/public/linux32/choreoobjects.a and b/sp/src/lib/public/linux32/choreoobjects.a differ diff --git a/sp/src/lib/public/linux32/dmxloader.a b/sp/src/lib/public/linux32/dmxloader.a index cecfdd41..eda673b5 100644 Binary files a/sp/src/lib/public/linux32/dmxloader.a and b/sp/src/lib/public/linux32/dmxloader.a differ diff --git a/sp/src/lib/public/linux32/libSDL2-2.0.so.0 b/sp/src/lib/public/linux32/libSDL2-2.0.so.0 new file mode 100644 index 00000000..5908adb7 Binary files /dev/null and b/sp/src/lib/public/linux32/libSDL2-2.0.so.0 differ diff --git a/sp/src/lib/public/linux32/libSDL2.so b/sp/src/lib/public/linux32/libSDL2.so new file mode 100644 index 00000000..d58bb41c --- /dev/null +++ b/sp/src/lib/public/linux32/libSDL2.so @@ -0,0 +1 @@ +libSDL2-2.0.so.0 diff --git a/sp/src/lib/public/linux32/libtier0.so b/sp/src/lib/public/linux32/libtier0.so index 6fe0000a..eb582467 100644 Binary files a/sp/src/lib/public/linux32/libtier0.so and b/sp/src/lib/public/linux32/libtier0.so differ diff --git a/sp/src/lib/public/linux32/libvstdlib.so b/sp/src/lib/public/linux32/libvstdlib.so index 5c35056b..66641ae6 100644 Binary files a/sp/src/lib/public/linux32/libvstdlib.so and b/sp/src/lib/public/linux32/libvstdlib.so differ diff --git a/sp/src/lib/public/linux32/matsys_controls.a b/sp/src/lib/public/linux32/matsys_controls.a index 293d97c8..5707fa0d 100644 Binary files a/sp/src/lib/public/linux32/matsys_controls.a and b/sp/src/lib/public/linux32/matsys_controls.a differ diff --git a/sp/src/lib/public/linux32/particles.a b/sp/src/lib/public/linux32/particles.a index 208a8a3e..15630878 100644 Binary files a/sp/src/lib/public/linux32/particles.a and b/sp/src/lib/public/linux32/particles.a differ diff --git a/sp/src/lib/public/linux32/tier2.a b/sp/src/lib/public/linux32/tier2.a index be6d5671..a219abe3 100644 Binary files a/sp/src/lib/public/linux32/tier2.a and b/sp/src/lib/public/linux32/tier2.a differ diff --git a/sp/src/lib/public/linux32/tier3.a b/sp/src/lib/public/linux32/tier3.a index 47736d4a..d061038e 100644 Binary files a/sp/src/lib/public/linux32/tier3.a and b/sp/src/lib/public/linux32/tier3.a differ diff --git a/sp/src/lib/public/linux32/vtf.a b/sp/src/lib/public/linux32/vtf.a index 7ea19bbb..19cdceef 100644 Binary files a/sp/src/lib/public/linux32/vtf.a and b/sp/src/lib/public/linux32/vtf.a differ diff --git a/sp/src/lib/public/mathlib.lib b/sp/src/lib/public/mathlib.lib index afcad316..2c1c1b8a 100644 Binary files a/sp/src/lib/public/mathlib.lib and b/sp/src/lib/public/mathlib.lib differ diff --git a/sp/src/lib/public/matsys_controls.lib b/sp/src/lib/public/matsys_controls.lib index ffea95ea..c73c99a5 100644 Binary files a/sp/src/lib/public/matsys_controls.lib and b/sp/src/lib/public/matsys_controls.lib differ diff --git a/sp/src/lib/public/nvtristrip.lib b/sp/src/lib/public/nvtristrip.lib index a384bab9..1ad7ee77 100644 Binary files a/sp/src/lib/public/nvtristrip.lib and b/sp/src/lib/public/nvtristrip.lib differ diff --git a/sp/src/lib/public/osx32/libSDL2-2.0.0.dylib b/sp/src/lib/public/osx32/libSDL2-2.0.0.dylib new file mode 100644 index 00000000..d4c32beb Binary files /dev/null and b/sp/src/lib/public/osx32/libSDL2-2.0.0.dylib differ diff --git a/sp/src/lib/public/osx32/libSDL2.dylib b/sp/src/lib/public/osx32/libSDL2.dylib new file mode 100644 index 00000000..4122f22f --- /dev/null +++ b/sp/src/lib/public/osx32/libSDL2.dylib @@ -0,0 +1 @@ +libSDL2-2.0.0.dylib diff --git a/sp/src/lib/public/particles.lib b/sp/src/lib/public/particles.lib index 9774b663..8ceadffa 100644 Binary files a/sp/src/lib/public/particles.lib and b/sp/src/lib/public/particles.lib differ diff --git a/sp/src/lib/public/raytrace.lib b/sp/src/lib/public/raytrace.lib index e32c9151..1b79cf9d 100644 Binary files a/sp/src/lib/public/raytrace.lib and b/sp/src/lib/public/raytrace.lib differ diff --git a/sp/src/lib/public/shaderlib.lib b/sp/src/lib/public/shaderlib.lib new file mode 100644 index 00000000..70742f1e Binary files /dev/null and b/sp/src/lib/public/shaderlib.lib differ diff --git a/sp/src/lib/public/tier0.lib b/sp/src/lib/public/tier0.lib index cd7c6219..dfb2b216 100644 Binary files a/sp/src/lib/public/tier0.lib and b/sp/src/lib/public/tier0.lib differ diff --git a/sp/src/lib/public/tier1.lib b/sp/src/lib/public/tier1.lib index 249a9067..35e3f291 100644 Binary files a/sp/src/lib/public/tier1.lib and b/sp/src/lib/public/tier1.lib differ diff --git a/sp/src/lib/public/tier2.lib b/sp/src/lib/public/tier2.lib index 3148d509..ce24c562 100644 Binary files a/sp/src/lib/public/tier2.lib and b/sp/src/lib/public/tier2.lib differ diff --git a/sp/src/lib/public/tier3.lib b/sp/src/lib/public/tier3.lib index 00f68214..62db10b3 100644 Binary files a/sp/src/lib/public/tier3.lib and b/sp/src/lib/public/tier3.lib differ diff --git a/sp/src/lib/public/vgui_controls.lib b/sp/src/lib/public/vgui_controls.lib index bf81de1a..7c95f669 100644 Binary files a/sp/src/lib/public/vgui_controls.lib and b/sp/src/lib/public/vgui_controls.lib differ diff --git a/sp/src/lib/public/vmpi.lib b/sp/src/lib/public/vmpi.lib index fed70259..69fc7780 100644 Binary files a/sp/src/lib/public/vmpi.lib and b/sp/src/lib/public/vmpi.lib differ diff --git a/sp/src/lib/public/vstdlib.lib b/sp/src/lib/public/vstdlib.lib index d1d830ea..23824470 100644 Binary files a/sp/src/lib/public/vstdlib.lib and b/sp/src/lib/public/vstdlib.lib differ diff --git a/sp/src/lib/public/vtf.lib b/sp/src/lib/public/vtf.lib index e4a169f8..9d2b7605 100644 Binary files a/sp/src/lib/public/vtf.lib and b/sp/src/lib/public/vtf.lib differ diff --git a/sp/src/materialsystem/shaderapidx9/locald3dtypes.h b/sp/src/materialsystem/shaderapidx9/locald3dtypes.h new file mode 100644 index 00000000..31854816 --- /dev/null +++ b/sp/src/materialsystem/shaderapidx9/locald3dtypes.h @@ -0,0 +1,191 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef LOCALD3DTYPES_H +#define LOCALD3DTYPES_H + +#ifdef _WIN32 +#pragma once +#endif + +#if defined( DX10 ) && !defined( DX_TO_GL_ABSTRACTION ) + +#include +#include + +struct IDirect3D10BaseTexture +{ + ID3D10Resource *m_pBaseTexture; + ID3D10ShaderResourceView *m_pSRView; + ID3D10RenderTargetView *m_pRTView; +}; + +class CDx10Types +{ +public: + typedef struct IDirect3D10BaseTexture IDirect3DTexture; + // FIXME: What is this called now ? + // typedef ID3D10TextureCube IDirect3DCubeTexture; + typedef ID3D10Texture3D IDirect3DVolumeTexture; + typedef ID3D10Device IDirect3DDevice; + typedef D3D10_VIEWPORT D3DVIEWPORT; + typedef ID3D10Buffer IDirect3DIndexBuffer; + typedef ID3D10Buffer IDirect3DVertexBuffer; + typedef ID3D10VertexShader IDirect3DVertexShader; + typedef ID3D10PixelShader IDirect3DPixelShader; + typedef ID3D10ShaderResourceView IDirect3DSurface; + typedef ID3DX10Font ID3DXFont; + typedef ID3D10Query ID3DQuery; + + typedef ID3D10Device *LPDIRECT3DDEVICE; + typedef ID3D10Buffer *LPDIRECT3DINDEXBUFFER; + typedef ID3D10Buffer *LPDIRECT3DVERTEXBUFFER; +}; + +#endif // defined( DX10 ) && !defined( DX_TO_GL_ABSTRACTION ) + + +#if !defined( _X360 ) && !defined( DX_TO_GL_ABSTRACTION ) +#ifdef _DEBUG +#define D3D_DEBUG_INFO 1 +#endif +#endif + +struct IDirect3DTexture9; +struct IDirect3DBaseTexture9; +struct IDirect3DCubeTexture9; +struct IDirect3D9; +struct IDirect3DDevice9; +struct IDirect3DSurface9; +struct IDirect3DIndexBuffer9; +struct IDirect3DVertexBuffer9; +struct IDirect3DVertexShader9; +struct IDirect3DPixelShader9; +struct IDirect3DVolumeTexture9; + +typedef struct _D3DLIGHT9 D3DLIGHT9; +typedef struct _D3DADAPTER_IDENTIFIER9 D3DADAPTER_IDENTIFIER9; +typedef struct _D3DCAPS9 D3DCAPS9; +typedef struct _D3DVIEWPORT9 D3DVIEWPORT9; +typedef struct _D3DMATERIAL9 D3DMATERIAL9; +typedef IDirect3DTexture9 IDirect3DTexture; +typedef IDirect3DBaseTexture9 IDirect3DBaseTexture; +typedef IDirect3DCubeTexture9 IDirect3DCubeTexture; +typedef IDirect3DVolumeTexture9 IDirect3DVolumeTexture; +typedef IDirect3DDevice9 IDirect3DDevice; +typedef D3DMATERIAL9 D3DMATERIAL; +typedef D3DLIGHT9 D3DLIGHT; +typedef IDirect3DSurface9 IDirect3DSurface; +typedef D3DCAPS9 D3DCAPS; +typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer; +typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer; +typedef IDirect3DPixelShader9 IDirect3DPixelShader; +typedef IDirect3DDevice *LPDIRECT3DDEVICE; +typedef IDirect3DIndexBuffer *LPDIRECT3DINDEXBUFFER; +typedef IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER; + +class CDx9Types +{ +public: + typedef IDirect3DTexture9 IDirect3DTexture; + typedef IDirect3DBaseTexture9 IDirect3DBaseTexture; + typedef IDirect3DCubeTexture9 IDirect3DCubeTexture; + typedef IDirect3DVolumeTexture9 IDirect3DVolumeTexture; + typedef IDirect3DDevice9 IDirect3DDevice; + typedef D3DMATERIAL9 D3DMATERIAL; + typedef D3DLIGHT9 D3DLIGHT; + typedef IDirect3DSurface9 IDirect3DSurface; + typedef D3DCAPS9 D3DCAPS; + typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer; + typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer; + typedef IDirect3DPixelShader9 IDirect3DPixelShader; + typedef IDirect3DDevice *LPDIRECT3DDEVICE; + typedef IDirect3DIndexBuffer *LPDIRECT3DINDEXBUFFER; + typedef IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER; +}; + +typedef void *HardwareShader_t; + +//----------------------------------------------------------------------------- +// The vertex and pixel shader type +//----------------------------------------------------------------------------- +typedef int VertexShader_t; +typedef int PixelShader_t; + +//----------------------------------------------------------------------------- +// Bitpattern for an invalid shader +//----------------------------------------------------------------------------- +#define INVALID_SHADER ( 0xFFFFFFFF ) +#define INVALID_HARDWARE_SHADER ( NULL ) + +#define D3DSAMP_NOTSUPPORTED D3DSAMP_FORCE_DWORD +#define D3DRS_NOTSUPPORTED D3DRS_FORCE_DWORD + +#include "togl/rendermechanism.h" + +#if defined( _X360 ) + +// not supported, keeping for port ease +#define D3DSAMP_SRGBTEXTURE D3DSAMP_NOTSUPPORTED +#define D3DRS_LIGHTING D3DRS_NOTSUPPORTED +#define D3DRS_DIFFUSEMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_SPECULARENABLE D3DRS_NOTSUPPORTED +#define D3DRS_SHADEMODE D3DRS_NOTSUPPORTED +#define D3DRS_LASTPIXEL D3DRS_NOTSUPPORTED +#define D3DRS_DITHERENABLE D3DRS_NOTSUPPORTED +#define D3DRS_FOGENABLE D3DRS_NOTSUPPORTED +#define D3DRS_FOGCOLOR D3DRS_NOTSUPPORTED +#define D3DRS_FOGTABLEMODE D3DRS_NOTSUPPORTED +#define D3DRS_FOGSTART D3DRS_NOTSUPPORTED +#define D3DRS_FOGEND D3DRS_NOTSUPPORTED +#define D3DRS_FOGDENSITY D3DRS_NOTSUPPORTED +#define D3DRS_RANGEFOGENABLE D3DRS_NOTSUPPORTED +#define D3DRS_TEXTUREFACTOR D3DRS_NOTSUPPORTED +#define D3DRS_CLIPPING D3DRS_NOTSUPPORTED +#define D3DRS_AMBIENT D3DRS_NOTSUPPORTED +#define D3DRS_FOGVERTEXMODE D3DRS_NOTSUPPORTED +#define D3DRS_COLORVERTEX D3DRS_NOTSUPPORTED +#define D3DRS_LOCALVIEWER D3DRS_NOTSUPPORTED +#define D3DRS_NORMALIZENORMALS D3DRS_NOTSUPPORTED +#define D3DRS_SPECULARMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_AMBIENTMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_EMISSIVEMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_VERTEXBLEND D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALEENABLE D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_A D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_B D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_C D3DRS_NOTSUPPORTED +#define D3DRS_PATCHEDGESTYLE D3DRS_NOTSUPPORTED +#define D3DRS_DEBUGMONITORTOKEN D3DRS_NOTSUPPORTED +#define D3DRS_INDEXEDVERTEXBLENDENABLE D3DRS_NOTSUPPORTED +#define D3DRS_TWEENFACTOR D3DRS_NOTSUPPORTED +#define D3DRS_POSITIONDEGREE D3DRS_NOTSUPPORTED +#define D3DRS_NORMALDEGREE D3DRS_NOTSUPPORTED +#define D3DRS_ANTIALIASEDLINEENABLE D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_X D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_Y D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_Z D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_W D3DRS_NOTSUPPORTED +#define D3DRS_ENABLEADAPTIVETESSELLATION D3DRS_NOTSUPPORTED +#define D3DRS_SRGBWRITEENABLE D3DRS_NOTSUPPORTED +#define D3DLOCK_DISCARD 0 +#define D3DUSAGE_DYNAMIC 0 +#define D3DUSAGE_AUTOGENMIPMAP 0 +#define D3DDEVTYPE_REF D3DDEVTYPE_HAL +#define D3DENUM_WHQL_LEVEL 0 +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING D3DCREATE_HARDWARE_VERTEXPROCESSING +#define D3DDMT_ENABLE 0 + +typedef enum D3DSHADEMODE +{ + D3DSHADE_FLAT = 0, + D3DSHADE_GOURAUD = 0, +}; + +#endif // _X360 + +#endif // LOCALD3DTYPES_H diff --git a/sp/src/materialsystem/stdshaders/BaseVSShader.cpp b/sp/src/materialsystem/stdshaders/BaseVSShader.cpp new file mode 100644 index 00000000..ba1f6e15 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BaseVSShader.cpp @@ -0,0 +1,2234 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// This is what all vs/ps (dx8+) shaders inherit from. +//===========================================================================// +#if !defined(_STATIC_LINKED) || defined(STDSHADER_DX8_DLL_EXPORT) || defined(STDSHADER_DX9_DLL_EXPORT) + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "mathlib/bumpvects.h" +#include "cpp_shader_constant_register_map.h" +#include "convar.h" + +#ifndef GAME_SHADER_DLL +#ifdef HDR +#include "vertexlit_and_unlit_generic_hdr_ps20.inc" +#include "vertexlit_and_unlit_generic_hdr_ps20b.inc" +#endif + +#if SUPPORT_DX8 +#include "lightmappedgeneric_flashlight_vs11.inc" +#include "flashlight_ps11.inc" +#endif + +#ifdef STDSHADER_DX9_DLL_EXPORT +#include "lightmappedgeneric_flashlight_vs20.inc" +#endif +#ifdef STDSHADER_DX9_DLL_EXPORT +#include "flashlight_ps20.inc" +#include "flashlight_ps20b.inc" +#endif +#include "unlitgeneric_vs11.inc" +#include "VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14.inc" +#include "VertexLitGeneric_EnvmappedBumpmap_NoLighting.inc" +#include "vertexlitgeneric_flashlight_vs11.inc" +#include "LightmappedGeneric_BaseTexture.inc" +#include "LightmappedGeneric_BumpmappedLightmap_Base_ps14.inc" +#include "LightmappedGeneric_BumpmappedLightmap_Blend_ps14.inc" +#include "lightmappedgeneric_bumpmappedenvmap_ps14.inc" +#include "lightmappedgeneric_bumpmappedenvmap.inc" +#include "lightmappedgeneric_basetextureblend.inc" +#include "lightmappedgeneric_bumpmappedlightmap.inc" +#endif // GAME_SHADER_DLL + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +// These functions are to be called from the shaders. + +//----------------------------------------------------------------------------- +// Pixel and vertex shader constants.... +//----------------------------------------------------------------------------- +void CBaseVSShader::SetPixelShaderConstant( int pixelReg, int constantVar, int constantVar2 ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1) || (constantVar2 == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + IMaterialVar* pPixelVar2 = s_ppParams[constantVar2]; + Assert( pPixelVar2 ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 3 ); + } + else + { + val[0] = val[1] = val[2] = pPixelVar->GetFloatValue(); + } + + val[3] = pPixelVar2->GetFloatValue(); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar, int constantVar2 ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1) || (constantVar2 == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + IMaterialVar* pPixelVar2 = s_ppParams[constantVar2]; + Assert( pPixelVar2 ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 3 ); + } + else + { + val[0] = val[1] = val[2] = pPixelVar->GetFloatValue(); + } + + val[3] = pPixelVar2->GetFloatValue(); + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + val[3]=fWValue; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstant( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetVertexShaderConstantGammaToLinear( int var, float const* pVec, int numConst, bool bForce ) +{ + int i; + for( i = 0; i < numConst; i++ ) + { + float vec[4]; + vec[0] = pVec[i*4+0] > 1.0f ? pVec[i*4+0] : GammaToLinear( pVec[i*4+0] ); + vec[1] = pVec[i*4+1] > 1.0f ? pVec[i*4+1] : GammaToLinear( pVec[i*4+1] ); + vec[2] = pVec[i*4+2] > 1.0f ? pVec[i*4+2] : GammaToLinear( pVec[i*4+2] ); + vec[3] = pVec[i*4+3]; + + s_pShaderAPI->SetVertexShaderConstant( var + i, vec, 1, bForce ); + } +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int var, float const* pVec, int numConst, bool bForce ) +{ + int i; + for( i = 0; i < numConst; i++ ) + { + float vec[4]; + vec[0] = pVec[i*4+0] > 1.0f ? pVec[i*4+0] : GammaToLinear( pVec[i*4+0] ); + vec[1] = pVec[i*4+1] > 1.0f ? pVec[i*4+1] : GammaToLinear( pVec[i*4+1] ); + vec[2] = pVec[i*4+2] > 1.0f ? pVec[i*4+2] : GammaToLinear( pVec[i*4+2] ); + + vec[3] = pVec[i*4+3]; + + s_pShaderAPI->SetPixelShaderConstant( var + i, vec, 1, bForce ); + } +} + +// GR - special version with fix for const/lerp issue +void CBaseVSShader::SetPixelShaderConstantFudge( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 4 ); + val[0] = val[0] * 0.992f + 0.0078f; + val[1] = val[1] * 0.992f + 0.0078f; + val[2] = val[2] * 0.992f + 0.0078f; + val[3] = val[3] * 0.992f + 0.0078f; + } + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue() * 0.992f + 0.0078f; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetVertexShaderConstant( int vertexReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pVertexVar = s_ppParams[constantVar]; + Assert( pVertexVar ); + + float val[4]; + if (pVertexVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pVertexVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pVertexVar->GetFloatValue(); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, val ); +} + +//----------------------------------------------------------------------------- +// Sets normalized light color for pixel shaders. +//----------------------------------------------------------------------------- +void CBaseVSShader::SetPixelShaderLightColors( int pixelReg ) +{ + int i; + int maxLights = s_pShaderAPI->GetMaxLights(); + for( i = 0; i < maxLights; i++ ) + { + const LightDesc_t & lightDesc = s_pShaderAPI->GetLight( i ); + if( lightDesc.m_Type != MATERIAL_LIGHT_DISABLE ) + { + Vector color( lightDesc.m_Color[0], lightDesc.m_Color[1], lightDesc.m_Color[2] ); + VectorNormalize( color ); + float val[4] = { color[0], color[1], color[2], 1.0f }; + s_pShaderAPI->SetPixelShaderConstant( pixelReg + i, val, 1 ); + } + else + { + float zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + s_pShaderAPI->SetPixelShaderConstant( pixelReg + i, zero, 1 ); + } + } +} + + +//----------------------------------------------------------------------------- +// Sets vertex shader texture transforms +//----------------------------------------------------------------------------- +void CBaseVSShader::SetVertexShaderTextureTranslation( int vertexReg, int translationVar ) +{ + float offset[2] = {0, 0}; + + IMaterialVar* pTranslationVar = s_ppParams[translationVar]; + if (pTranslationVar) + { + if (pTranslationVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pTranslationVar->GetVecValue( offset, 2 ); + else + offset[0] = offset[1] = pTranslationVar->GetFloatValue(); + } + + Vector4D translation[2]; + translation[0].Init( 1.0f, 0.0f, 0.0f, offset[0] ); + translation[1].Init( 0.0f, 1.0f, 0.0f, offset[1] ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, translation[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureScale( int vertexReg, int scaleVar ) +{ + float scale[2] = {1, 1}; + + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale, 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + Vector4D scaleMatrix[2]; + scaleMatrix[0].Init( scale[0], 0.0f, 0.0f, 0.0f ); + scaleMatrix[1].Init( 0.0f, scale[1], 0.0f, 0.0f ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, scaleMatrix[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureTransform( int vertexReg, int transformVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureScaledTransform( int vertexReg, int transformVar, int scaleVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); +} + + +//----------------------------------------------------------------------------- +// Sets pixel shader texture transforms +//----------------------------------------------------------------------------- +void CBaseVSShader::SetPixelShaderTextureTranslation( int pixelReg, int translationVar ) +{ + float offset[2] = {0, 0}; + + IMaterialVar* pTranslationVar = s_ppParams[translationVar]; + if (pTranslationVar) + { + if (pTranslationVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pTranslationVar->GetVecValue( offset, 2 ); + else + offset[0] = offset[1] = pTranslationVar->GetFloatValue(); + } + + Vector4D translation[2]; + translation[0].Init( 1.0f, 0.0f, 0.0f, offset[0] ); + translation[1].Init( 0.0f, 1.0f, 0.0f, offset[1] ); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, translation[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureScale( int pixelReg, int scaleVar ) +{ + float scale[2] = {1, 1}; + + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale, 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + Vector4D scaleMatrix[2]; + scaleMatrix[0].Init( scale[0], 0.0f, 0.0f, 0.0f ); + scaleMatrix[1].Init( 0.0f, scale[1], 0.0f, 0.0f ); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, scaleMatrix[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureTransform( int pixelReg, int transformVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, transformation[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureScaledTransform( int pixelReg, int transformVar, int scaleVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, transformation[0].Base(), 2 ); +} + + +//----------------------------------------------------------------------------- +// Moves a matrix into vertex shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::SetVertexShaderMatrix3x4( int vertexReg, int matrixVar ) +{ + IMaterialVar* pTranslationVar = s_ppParams[matrixVar]; + if (pTranslationVar) + { + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &pTranslationVar->GetMatrixValue( )[0][0], 3 ); + } + else + { + VMatrix matrix; + MatrixSetIdentity( matrix ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &matrix[0][0], 3 ); + } +} + +void CBaseVSShader::SetVertexShaderMatrix4x4( int vertexReg, int matrixVar ) +{ + IMaterialVar* pTranslationVar = s_ppParams[matrixVar]; + if (pTranslationVar) + { + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &pTranslationVar->GetMatrixValue( )[0][0], 4 ); + } + else + { + VMatrix matrix; + MatrixSetIdentity( matrix ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &matrix[0][0], 4 ); + } +} + + +//----------------------------------------------------------------------------- +// Loads the view matrix into pixel shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadViewMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix mat, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_VIEW, mat.m[0] ); + + MatrixTranspose( mat, transpose ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transpose.m[0], 3 ); +} + + +//----------------------------------------------------------------------------- +// Loads the projection matrix into pixel shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadProjectionMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix mat, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_PROJECTION, mat.m[0] ); + + MatrixTranspose( mat, transpose ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transpose.m[0], 4 ); +} + + +//----------------------------------------------------------------------------- +// Loads the projection matrix into pixel shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadModelViewMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix view, model, modelView, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_MODEL, model.m[0] ); + MatrixTranspose( model, model ); + s_pShaderAPI->GetMatrix( MATERIAL_VIEW, view.m[0] ); + MatrixTranspose( view, view ); + + MatrixMultiply( view, model, modelView ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, modelView.m[0], 3 ); +} + +//----------------------------------------------------------------------------- +// Loads a scale/offset version of the viewport transform into the specified constant. +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadViewportTransformScaledIntoVertexShaderConstant( int vertexReg ) +{ + ShaderViewport_t viewport; + + s_pShaderAPI->GetViewports( &viewport, 1 ); + + int bbWidth = 0, + bbHeight = 0; + + s_pShaderAPI->GetBackBufferDimensions( bbWidth, bbHeight ); + + // (x, y, z, w) = (Width / bbWidth, Height / bbHeight, MinX / bbWidth, MinY / bbHeight) + Vector4D viewportTransform( + 1.0f * viewport.m_nWidth / bbWidth, + 1.0f * viewport.m_nHeight / bbHeight, + 1.0f * viewport.m_nTopLeftX / bbWidth, + 1.0f * viewport.m_nTopLeftY / bbHeight + ); + + s_pShaderAPI->SetVertexShaderConstant( vertexReg, viewportTransform.Base() ); +} + + + +//----------------------------------------------------------------------------- +// Loads bump lightmap coordinates into the pixel shader +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadBumpLightmapCoordinateAxes_PixelShader( int pixelReg ) +{ + Vector4D basis[3]; + for (int i = 0; i < 3; ++i) + { + memcpy( &basis[i], &g_localBumpBasis[i], 3 * sizeof(float) ); + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, (float*)basis, 3 ); +} + + +//----------------------------------------------------------------------------- +// Loads bump lightmap coordinates into the pixel shader +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadBumpLightmapCoordinateAxes_VertexShader( int vertexReg ) +{ + Vector4D basis[3]; + + // transpose + int i; + for (i = 0; i < 3; ++i) + { + basis[i][0] = g_localBumpBasis[0][i]; + basis[i][1] = g_localBumpBasis[1][i]; + basis[i][2] = g_localBumpBasis[2][i]; + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg, (float*)basis, 3 ); + for (i = 0; i < 3; ++i) + { + memcpy( &basis[i], &g_localBumpBasis[i], 3 * sizeof(float) ); + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg + 3, (float*)basis, 3 ); +} + + +//----------------------------------------------------------------------------- +// Helper methods for pixel shader overbrighting +//----------------------------------------------------------------------------- +void CBaseVSShader::EnablePixelShaderOverbright( int reg, bool bEnable, bool bDivideByTwo ) +{ + // can't have other overbright values with pixel shaders as it stands. + float v[4]; + if( bEnable ) + { + v[0] = v[1] = v[2] = v[3] = bDivideByTwo ? OVERBRIGHT / 2.0f : OVERBRIGHT; + } + else + { + v[0] = v[1] = v[2] = v[3] = bDivideByTwo ? 1.0f / 2.0f : 1.0f; + } + s_pShaderAPI->SetPixelShaderConstant( reg, v, 1 ); +} + + +//----------------------------------------------------------------------------- +// Helper for dealing with modulation +//----------------------------------------------------------------------------- +void CBaseVSShader::SetModulationVertexShaderDynamicState() +{ + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); +} + +void CBaseVSShader::SetModulationPixelShaderDynamicState( int modulationVar ) +{ + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + s_pShaderAPI->SetPixelShaderConstant( modulationVar, color ); +} + +void CBaseVSShader::SetModulationPixelShaderDynamicState_LinearColorSpace( int modulationVar ) +{ + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + color[0] = color[0] > 1.0f ? color[0] : GammaToLinear( color[0] ); + color[1] = color[1] > 1.0f ? color[1] : GammaToLinear( color[1] ); + color[2] = color[2] > 1.0f ? color[2] : GammaToLinear( color[2] ); + + s_pShaderAPI->SetPixelShaderConstant( modulationVar, color ); +} + +void CBaseVSShader::SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int modulationVar, float flScale ) +{ + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + color[0] = ( color[0] > 1.0f ? color[0] : GammaToLinear( color[0] ) ) * flScale; + color[1] = ( color[1] > 1.0f ? color[1] : GammaToLinear( color[1] ) ) * flScale; + color[2] = ( color[2] > 1.0f ? color[2] : GammaToLinear( color[2] ) ) * flScale; + + s_pShaderAPI->SetPixelShaderConstant( modulationVar, color ); +} + + +//----------------------------------------------------------------------------- +// Converts a color + alpha into a vector4 +//----------------------------------------------------------------------------- +void CBaseVSShader::ColorVarsToVector( int colorVar, int alphaVar, Vector4D &color ) +{ + color.Init( 1.0, 1.0, 1.0, 1.0 ); + if ( colorVar != -1 ) + { + IMaterialVar* pColorVar = s_ppParams[colorVar]; + if ( pColorVar->GetType() == MATERIAL_VAR_TYPE_VECTOR ) + { + pColorVar->GetVecValue( color.Base(), 3 ); + } + else + { + color[0] = color[1] = color[2] = pColorVar->GetFloatValue(); + } + } + if ( alphaVar != -1 ) + { + float flAlpha = s_ppParams[alphaVar]->GetFloatValue(); + color[3] = clamp( flAlpha, 0.0f, 1.0f ); + } +} + + +//----------------------------------------------------------------------------- +// Sets a color + alpha into shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::SetColorVertexShaderConstant( int nVertexReg, int colorVar, int alphaVar ) +{ + Vector4D color; + ColorVarsToVector( colorVar, alphaVar, color ); + s_pShaderAPI->SetVertexShaderConstant( nVertexReg, color.Base() ); +} + +void CBaseVSShader::SetColorPixelShaderConstant( int nPixelReg, int colorVar, int alphaVar ) +{ + Vector4D color; + ColorVarsToVector( colorVar, alphaVar, color ); + s_pShaderAPI->SetPixelShaderConstant( nPixelReg, color.Base() ); +} + +#ifdef _DEBUG +ConVar mat_envmaptintoverride( "mat_envmaptintoverride", "-1" ); +ConVar mat_envmaptintscale( "mat_envmaptintscale", "-1" ); +#endif + +//----------------------------------------------------------------------------- +// Helpers for dealing with envmap tint +//----------------------------------------------------------------------------- +// set alphaVar to -1 to ignore it. +void CBaseVSShader::SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar, int alphaVar, bool bConvertFromGammaToLinear ) +{ + float color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + if( g_pConfig->bShowSpecular && mat_fullbright.GetInt() != 2 ) + { + IMaterialVar* pAlphaVar = NULL; + if( alphaVar >= 0 ) + { + pAlphaVar = s_ppParams[alphaVar]; + } + if( pAlphaVar ) + { + color[3] = pAlphaVar->GetFloatValue(); + } + + IMaterialVar* pTintVar = s_ppParams[tintVar]; +#ifdef _DEBUG + pTintVar->GetVecValue( color, 3 ); + + float envmapTintOverride = mat_envmaptintoverride.GetFloat(); + float envmapTintScaleOverride = mat_envmaptintscale.GetFloat(); + + if( envmapTintOverride != -1.0f ) + { + color[0] = color[1] = color[2] = envmapTintOverride; + } + if( envmapTintScaleOverride != -1.0f ) + { + color[0] *= envmapTintScaleOverride; + color[1] *= envmapTintScaleOverride; + color[2] *= envmapTintScaleOverride; + } + + if( bConvertFromGammaToLinear ) + { + color[0] = color[0] > 1.0f ? color[0] : GammaToLinear( color[0] ); + color[1] = color[1] > 1.0f ? color[1] : GammaToLinear( color[1] ); + color[2] = color[2] > 1.0f ? color[2] : GammaToLinear( color[2] ); + } +#else + if( bConvertFromGammaToLinear ) + { + pTintVar->GetLinearVecValue( color, 3 ); + } + else + { + pTintVar->GetVecValue( color, 3 ); + } +#endif + } + else + { + color[0] = color[1] = color[2] = color[3] = 0.0f; + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, color, 1 ); +} + +void CBaseVSShader::SetAmbientCubeDynamicStateVertexShader( ) +{ + s_pShaderAPI->SetVertexShaderStateAmbientLightCube(); +} + +float CBaseVSShader::GetAmbientLightCubeLuminance( ) +{ + return s_pShaderAPI->GetAmbientLightCubeLuminance(); +} + +#ifndef GAME_SHADER_DLL +const char *CBaseVSShader::UnlitGeneric_ComputePixelShaderName( bool bMask, + bool bEnvmap, + bool bBaseTexture, + bool bBaseAlphaEnvmapMask, + bool bDetail, + bool bDetailMultiplyMode, + bool bMaskBaseByDetailAlpha ) +{ + static char const* s_pPixelShaders[] = + { + "UnlitGeneric_NoTexture", + "UnlitGeneric", + "UnlitGeneric_EnvMapNoTexture", + "UnlitGeneric_EnvMap", + "UnlitGeneric_NoTexture", + "UnlitGeneric", + "UnlitGeneric_EnvMapMaskNoTexture", + "UnlitGeneric_EnvMapMask", + + // Detail texture + // The other commented-out versions are used if we want to + // apply the detail *after* the environment map is added + "UnlitGeneric_DetailNoTexture", + "UnlitGeneric_Detail", + "UnlitGeneric_EnvMapNoTexture", //"UnlitGeneric_DetailEnvMapNoTexture", + "UnlitGeneric_DetailEnvMap", + "UnlitGeneric_DetailNoTexture", + "UnlitGeneric_Detail", + "UnlitGeneric_EnvMapMaskNoTexture", //"UnlitGeneric_DetailEnvMapMaskNoTexture", + "UnlitGeneric_DetailEnvMapMask", + }; + + // handle hud elements + if ( bDetail & bDetailMultiplyMode ) + return "alphadist_ps11"; + + if ( bDetail & bMaskBaseByDetailAlpha ) + return "UnlitGeneric_MaskBaseByDetailAlpha_ps11"; + + if (!bMask && bEnvmap && bBaseTexture && bBaseAlphaEnvmapMask) + { + if (!bDetail) + return "UnlitGeneric_BaseAlphaMaskedEnvMap"; + else + return "UnlitGeneric_DetailBaseAlphaMaskedEnvMap"; + } + else + { + int pshIndex = 0; + if (bBaseTexture) + pshIndex |= 0x1; + if (bEnvmap) + pshIndex |= 0x2; + if (bMask) + pshIndex |= 0x4; + if (bDetail) + pshIndex |= 0x8; + return s_pPixelShaders[pshIndex]; + } +} + + +//----------------------------------------------------------------------------- +// Sets up hw morphing state for the vertex shader +//----------------------------------------------------------------------------- +void CBaseVSShader::SetHWMorphVertexShaderState( int nDimConst, int nSubrectConst, VertexTextureSampler_t morphSampler ) +{ +#ifndef _X360 + if ( !s_pShaderAPI->IsHWMorphingEnabled() ) + return; + + int nMorphWidth, nMorphHeight; + s_pShaderAPI->GetStandardTextureDimensions( &nMorphWidth, &nMorphHeight, TEXTURE_MORPH_ACCUMULATOR ); + + int nDim = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_4TUPLE_COUNT ); + float pMorphAccumSize[4] = { nMorphWidth, nMorphHeight, nDim, 0.0f }; + s_pShaderAPI->SetVertexShaderConstant( nDimConst, pMorphAccumSize ); + + int nXOffset = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_X_OFFSET ); + int nYOffset = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_Y_OFFSET ); + int nWidth = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_SUBRECT_WIDTH ); + int nHeight = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_SUBRECT_HEIGHT ); + float pMorphAccumSubrect[4] = { nXOffset, nYOffset, nWidth, nHeight }; + s_pShaderAPI->SetVertexShaderConstant( nSubrectConst, pMorphAccumSubrect ); + + s_pShaderAPI->BindStandardVertexTexture( morphSampler, TEXTURE_MORPH_ACCUMULATOR ); +#endif +} + + +//----------------------------------------------------------------------------- +// Vertex shader unlit generic pass +//----------------------------------------------------------------------------- +void CBaseVSShader::VertexShaderUnlitGenericPass( int baseTextureVar, int frameVar, + int baseTextureTransformVar, + int detailVar, int detailTransform, + bool bDetailTransformIsScale, + int envmapVar, int envMapFrameVar, + int envmapMaskVar, int envmapMaskFrameVar, + int envmapMaskScaleVar, int envmapTintVar, + int alphaTestReferenceVar, + int nDetailBlendModeVar, + int nOutlineVar, + int nOutlineColorVar, + int nOutlineStartVar, + int nOutlineEndVar, + int nSeparateDetailUVsVar ) +{ + IMaterialVar** params = s_ppParams; + + bool bBaseAlphaEnvmapMask = IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK); + bool bEnvmap = (envmapVar >= 0) && params[envmapVar]->IsTexture(); + bool bMask = false; + if (bEnvmap && (envmapMaskVar >= 0)) + { + bMask = params[envmapMaskVar]->IsTexture(); + } + bool bDetail = (detailVar >= 0) && params[detailVar]->IsTexture(); + bool bBaseTexture = (baseTextureVar >= 0) && params[baseTextureVar]->IsTexture(); + bool bVertexColor = IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR); + bool bEnvmapCameraSpace = IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE); + bool bEnvmapSphere = IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE); + + bool bDetailMultiply = ( nDetailBlendModeVar >= 0 ) && ( params[nDetailBlendModeVar]->GetIntValue() == 8 ); + bool bMaskBaseByDetailAlpha = ( nDetailBlendModeVar >= 0 ) && ( params[nDetailBlendModeVar]->GetIntValue() == 9 ); + bool bSeparateDetailUVs = ( nSeparateDetailUVsVar >= 0 ) && ( params[nSeparateDetailUVsVar]->GetIntValue() != 0 ); + + if (IsSnapshotting()) + { + // Alpha test + s_pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + if( alphaTestReferenceVar != -1 && params[alphaTestReferenceVar]->GetFloatValue() > 0.0f ) + { + s_pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[alphaTestReferenceVar]->GetFloatValue() ); + } + + // Base texture on stage 0 + if (bBaseTexture) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + } + + if (bDetail) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + + if (bEnvmap) + { + // envmap on stage 1 + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // envmapmask on stage 2 + if (bMask || bBaseAlphaEnvmapMask ) + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + if (bBaseTexture) + SetDefaultBlendingShadowState( baseTextureVar, true ); + else if (bMask) + SetDefaultBlendingShadowState( envmapMaskVar, false ); + else + SetDefaultBlendingShadowState(); + + int fmt = VERTEX_POSITION; + if( bEnvmap ) + fmt |= VERTEX_NORMAL; + if ( bVertexColor ) + fmt |= VERTEX_COLOR; + + int numTexCoords = 1; + if( bSeparateDetailUVs ) + { + numTexCoords = 2; + } + + s_pShaderShadow->VertexShaderVertexFormat( fmt, numTexCoords, 0, 0 ); + const char *pshName = UnlitGeneric_ComputePixelShaderName( + bMask, + bEnvmap, + bBaseTexture, + bBaseAlphaEnvmapMask, + bDetail, + bDetailMultiply, + bMaskBaseByDetailAlpha ); + s_pShaderShadow->SetPixelShader( pshName ); + + // Compute the vertex shader index. + unlitgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( bDetail ); + vshIndex.SetENVMAP( bEnvmap ); + vshIndex.SetENVMAPCAMERASPACE( bEnvmap && bEnvmapCameraSpace ); + vshIndex.SetENVMAPSPHERE( bEnvmap && bEnvmapSphere ); + vshIndex.SetVERTEXCOLOR( bVertexColor ); + vshIndex.SetSEPARATEDETAILUVS( bSeparateDetailUVs ); + s_pShaderShadow->SetVertexShader( "unlitgeneric_vs11", vshIndex.GetIndex() ); + + DefaultFog(); + } + else + { + if ( s_pShaderAPI->InFlashlightMode() ) // Not snapshotting && flashlight pass + { + Draw( false ); + return; + } + + if (bBaseTexture) + { + BindTexture( SHADER_SAMPLER0, baseTextureVar, frameVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, baseTextureTransformVar ); + } + + if (bDetail) + { + BindTexture( SHADER_SAMPLER3, detailVar, frameVar ); + + if (bDetailTransformIsScale) + { + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, baseTextureTransformVar, detailTransform ); + } + else + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, detailTransform ); + } + } + + if (bEnvmap) + { + BindTexture( SHADER_SAMPLER1, envmapVar, envMapFrameVar ); + + if (bMask || bBaseAlphaEnvmapMask) + { + if (bMask) + BindTexture( SHADER_SAMPLER2, envmapMaskVar, envmapMaskFrameVar ); + else + BindTexture( SHADER_SAMPLER2, baseTextureVar, frameVar ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, baseTextureTransformVar, envmapMaskScaleVar ); + } + + SetEnvMapTintPixelShaderDynamicState( 2, envmapTintVar, -1 ); + + if (bEnvmapSphere || IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + } + + SetModulationVertexShaderDynamicState(); + + float flConsts[12]={ 0, 0, 0, 1, // color + 0, 0, 0, 0, // max + 0, 0, 0, .5, // min + }; + + // set up outline pixel shader constants + if ( bDetailMultiply && ( nOutlineVar != -1 ) && ( params[nOutlineVar]->GetIntValue() ) ) + { + if ( nOutlineColorVar != -1 ) + params[nOutlineColorVar]->GetVecValue( flConsts, 3 ); + if ( nOutlineEndVar != -1 ) + flConsts[7] = params[nOutlineEndVar]->GetFloatValue(); + if ( nOutlineStartVar != -1 ) + flConsts[11] = params[nOutlineStartVar]->GetFloatValue(); + } + + s_pShaderAPI->SetPixelShaderConstant( 0, flConsts, 3 ); + + // Compute the vertex shader index. + unlitgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( s_pShaderAPI->GetCurrentNumBones() > 0 ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + Draw(); +} + + +void CBaseVSShader::DrawWorldBaseTexture( int baseTextureVar, int baseTextureTransformVar, + int frameVar, int colorVar, int alphaVar ) +{ + if( IsSnapshotting() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION, 1, 0, 0 ); + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BaseTexture" ); + SetNormalBlendingShadowState(); + lightmappedgeneric_basetexture_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BaseTexture", vshIndex.GetIndex() ); + + FogToOOOverbright(); + } + else + { + IMaterialVar** params = s_ppParams; + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, baseTextureVar, frameVar ); + } + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, baseTextureTransformVar ); + SetColorPixelShaderConstant( 0, colorVar, alphaVar ); + lightmappedgeneric_basetexture_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +void CBaseVSShader::DrawWorldBumpedDiffuseLighting( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, bool bMultiply, + bool bSSBump ) +{ + if( IsSnapshotting() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( bMultiply ) + { + s_pShaderShadow->EnableBlending( true ); + SingleTextureLightmapBlendMode(); + } + s_pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, 0, 0 ); + + lightmappedgeneric_bumpmappedlightmap_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedLightmap", vshIndex.GetIndex() ); + + if ( bSSBump ) + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_SSBumpmappedLightmap" ); + else + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedLightmap" ); + FogToFogColor(); + } + else + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER0, bumpmapVar, bumpFrameVar ); + } + else + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + LoadBumpLightmapCoordinateAxes_PixelShader( 0 ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, bumpTransformVar ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_bumpmappedlightmap_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +void CBaseVSShader::DrawWorldBumpedDiffuseLighting_Base_ps14( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, + int baseTextureVar, int baseTextureTransformVar, int frameVar ) +{ + if( IsSnapshotting() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + s_pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, 0, 0 ); + + lightmappedgeneric_bumpmappedlightmap_base_ps14_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedLightmap_Base_ps14", vshIndex.GetIndex() ); + + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedLightmap_Base_ps14" ); + FogToFogColor(); + } + else + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER0, bumpmapVar, bumpFrameVar ); + } + else + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + LoadBumpLightmapCoordinateAxes_PixelShader( 0 ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + BindTexture( SHADER_SAMPLER4, baseTextureVar, frameVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, bumpTransformVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, baseTextureTransformVar ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_bumpmappedlightmap_base_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +void CBaseVSShader::DrawWorldBumpedDiffuseLighting_Blend_ps14( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, + int baseTextureVar, int baseTextureTransformVar, + int baseTextureFrameVar, + int baseTexture2Var, int baseTextureTransform2Var, + int baseTextureFrame2Var) +{ + if( IsSnapshotting() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + s_pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, 0, 0 ); + + lightmappedgeneric_bumpmappedlightmap_blend_ps14_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedLightmap_Blend_ps14", vshIndex.GetIndex() ); + + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedLightmap_Blend_ps14" ); + FogToFogColor(); + } + else + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER0, bumpmapVar, bumpFrameVar ); + } + else + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + LoadBumpLightmapCoordinateAxes_PixelShader( 0 ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + BindTexture( SHADER_SAMPLER4, baseTextureVar, baseTextureFrameVar ); + BindTexture( SHADER_SAMPLER5, baseTexture2Var, baseTextureFrame2Var ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, bumpTransformVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, baseTextureTransformVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, baseTextureTransform2Var ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_bumpmappedlightmap_blend_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +//#define USE_DEST_ALPHA +#define USE_NORMALMAP_ALPHA + +void CBaseVSShader::DrawWorldBumpedSpecularLighting( int bumpmapVar, int envmapVar, + int bumpFrameVar, int envmapFrameVar, + int envmapTintVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, + int bumpTransformVar, int fresnelReflectionVar, + bool bBlend, bool bNoWriteZ ) +{ + // + BUMPED CUBEMAP + if( IsSnapshotting() ) + { + SetInitialShadowState( ); + if ( bNoWriteZ ) + { + s_pShaderShadow->EnableDepthWrites( false ); + } + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + if( bBlend ) + { + s_pShaderShadow->EnableBlending( true ); + s_pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + // FIXME: Remove the normal (needed for tangent space gen) + s_pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | + VERTEX_TANGENT_T, 1, 0, 0 ); + + IMaterialVar** params = s_ppParams; + bool bHasNormalMapAlphaEnvMapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + lightmappedgeneric_bumpmappedenvmap_ps14_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedEnvmap_ps14", vshIndex.GetIndex() ); + + int nPshIndex = bHasNormalMapAlphaEnvMapMask ? 1 : 0; + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedEnvmap_ps14", nPshIndex ); + } + else + { + lightmappedgeneric_bumpmappedenvmap_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_BumpmappedEnvmap", vshIndex.GetIndex() ); + + int nPshIndex = bHasNormalMapAlphaEnvMapMask ? 1 : 0; + s_pShaderShadow->SetPixelShader( "LightmappedGeneric_BumpmappedEnvmap", nPshIndex ); + } + FogToBlack(); + } + else + { + IMaterialVar** params = s_ppParams; + s_pShaderAPI->SetDefaultState(); + BindTexture( SHADER_SAMPLER0, bumpmapVar, bumpFrameVar ); + BindTexture( SHADER_SAMPLER3, envmapVar, envmapFrameVar ); + + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALIZATION_CUBEMAP ); + + lightmappedgeneric_bumpmappedenvmap_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + lightmappedgeneric_bumpmappedenvmap_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + SetEnvMapTintPixelShaderDynamicState( 0, envmapTintVar, alphaVar ); + // GR - fudge consts a bit to fix const/lerp issues + SetPixelShaderConstantFudge( 1, envmapContrastVar ); + SetPixelShaderConstantFudge( 2, envmapSaturationVar ); + float greyWeights[4] = { 0.299f, 0.587f, 0.114f, 0.0f }; + s_pShaderAPI->SetPixelShaderConstant( 3, greyWeights ); + + // [ 0, 0 ,0, R(0) ] + float fresnel[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + fresnel[3] = params[fresnelReflectionVar]->GetFloatValue(); + s_pShaderAPI->SetPixelShaderConstant( 4, fresnel ); + // [ 0, 0 ,0, 1-R(0) ] + fresnel[3] = 1.0f - fresnel[3]; + s_pShaderAPI->SetPixelShaderConstant( 6, fresnel ); + + float one[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + s_pShaderAPI->SetPixelShaderConstant( 5, one ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, bumpTransformVar ); + } + Draw(); +} + +void CBaseVSShader::DrawModelBumpedSpecularLighting( int bumpMapVar, int bumpMapFrameVar, + int envMapVar, int envMapVarFrame, + int envMapTintVar, int alphaVar, + int envMapContrastVar, int envMapSaturationVar, + int bumpTransformVar, + bool bBlendSpecular, bool bNoWriteZ ) +{ + IMaterialVar** params = s_ppParams; + + if( IsSnapshotting() ) + { + SetInitialShadowState( ); + if ( bNoWriteZ ) + { + s_pShaderShadow->EnableDepthWrites( false ); + } + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + s_pShaderShadow->EnableAlphaTest( false ); + if( bBlendSpecular ) + { + s_pShaderShadow->EnableBlending( true ); + SetAdditiveBlendingShadowState( -1, false ); + } + else + { + s_pShaderShadow->EnableBlending( false ); + SetNormalBlendingShadowState( -1, false ); + } + + s_pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL, 1, 0, 4 /* userDataSize */ ); + + bool bHasNormalMapAlphaEnvMapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + vertexlitgeneric_envmappedbumpmap_nolighting_ps14_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14", vshIndex.GetIndex() ); + if( bHasNormalMapAlphaEnvMapMask ) + { + s_pShaderShadow->SetPixelShader( "VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha_ps14" ); + } + else + { + s_pShaderShadow->SetPixelShader( "VertexLitGeneric_EnvmappedBumpmapV2_ps14" ); + } + } + else + { + vertexlitgeneric_envmappedbumpmap_nolighting_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "VertexLitGeneric_EnvmappedBumpmap_NoLighting", vshIndex.GetIndex() ); + // This version does not multiply by lighting + // NOTE: We don't support multiplying by lighting for bumped specular stuff. + if( bHasNormalMapAlphaEnvMapMask ) + { + s_pShaderShadow->SetPixelShader( "VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha" ); + } + else + { + s_pShaderShadow->SetPixelShader( "VertexLitGeneric_EnvmappedBumpmapV2" ); + } + } + FogToBlack(); + } + else + { + s_pShaderAPI->SetDefaultState(); + BindTexture( SHADER_SAMPLER0, bumpMapVar, bumpMapFrameVar ); + BindTexture( SHADER_SAMPLER3, envMapVar, envMapVarFrame ); + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALIZATION_CUBEMAP ); + } + + if( bBlendSpecular ) + { + SetEnvMapTintPixelShaderDynamicState( 0, envMapTintVar, -1 ); + } + else + { + SetEnvMapTintPixelShaderDynamicState( 0, envMapTintVar, alphaVar ); + } + // GR - fudge consts a bit to fix const/lerp issues + SetPixelShaderConstantFudge( 1, envMapContrastVar ); + SetPixelShaderConstantFudge( 2, envMapSaturationVar ); + float greyWeights[4] = { 0.299f, 0.587f, 0.114f, 0.0f }; + s_pShaderAPI->SetPixelShaderConstant( 3, greyWeights ); + + // handle scrolling of bump texture + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, bumpTransformVar ); + + if( g_pHardwareConfig->SupportsPixelShaders_1_4() ) + { + vertexlitgeneric_envmappedbumpmap_nolighting_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( s_pShaderAPI->GetCurrentNumBones() > 0 ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + vertexlitgeneric_envmappedbumpmap_nolighting_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( s_pShaderAPI->GetCurrentNumBones() > 0 ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + Draw(); +} + +void CBaseVSShader::DrawBaseTextureBlend( int baseTextureVar, int baseTextureTransformVar, + int baseTextureFrameVar, + int baseTexture2Var, int baseTextureTransform2Var, + int baseTextureFrame2Var, int colorVar, int alphaVar ) +{ + if( IsSnapshotting() ) + { + SetInitialShadowState(); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + s_pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | + SHADER_DRAW_LIGHTMAP_TEXCOORD1 ); + // FIXME: Remove the normal (needed for tangent space gen) + s_pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION, 2, 0, 0 ); + + lightmappedgeneric_basetextureblend_Static_Index vshIndex; + s_pShaderShadow->SetVertexShader( "lightmappedgeneric_basetextureblend", vshIndex.GetIndex() ); + + s_pShaderShadow->SetPixelShader( "lightmappedgeneric_basetextureblend", 0 ); + FogToOOOverbright(); + } + else + { + IMaterialVar** params = s_ppParams; + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + + s_pShaderAPI->SetDefaultState(); + if( bLightingOnly ) + { + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, baseTextureVar, baseTextureFrameVar ); + BindTexture( SHADER_SAMPLER1, baseTexture2Var, baseTextureFrame2Var ); + } + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_LIGHTMAP ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, baseTextureTransformVar ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, baseTextureTransform2Var ); + SetColorPixelShaderConstant( 0, colorVar, alphaVar ); + lightmappedgeneric_basetextureblend_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); +} + +void CBaseVSShader::DrawWorldBumpedUsingVertexShader( int baseTextureVar, int baseTextureTransformVar, + int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, + int envmapMaskVar, int envmapMaskFrame, + int envmapVar, + int envmapFrameVar, + int envmapTintVar, int colorVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, + int frameVar, int fresnelReflectionVar, + bool doBaseTexture2, + int baseTexture2Var, int baseTextureTransform2Var, + int baseTextureFrame2Var, + bool bSSBump + ) +{ + IMaterialVar** params = s_ppParams; + // Draw base texture + bool bMultiplyDiffuseLighting = false; + bool bBlendSpecular = false; + + // Draw base texture(s) + if( doBaseTexture2 && params[baseTexture2Var]->IsTexture() && params[baseTextureVar]->IsTexture() ) + { + DrawBaseTextureBlend( baseTextureVar, baseTextureTransformVar, frameVar, + baseTexture2Var, baseTextureTransform2Var, baseTextureFrame2Var, colorVar, alphaVar ); + bMultiplyDiffuseLighting = true; + bBlendSpecular = true; + } + else if( params[baseTextureVar]->IsTexture() ) + { + DrawWorldBaseTexture( baseTextureVar, baseTextureTransformVar, frameVar, colorVar, alphaVar ); + bMultiplyDiffuseLighting = true; + bBlendSpecular = true; + } + else + { + // Just use color here + } + + // Draw diffuse lighting + if( params[baseTextureVar]->IsTexture() || !params[envmapVar]->IsTexture() ) + { + DrawWorldBumpedDiffuseLighting( bumpmapVar, bumpFrameVar, bumpTransformVar, + bMultiplyDiffuseLighting, bSSBump ); + bBlendSpecular = true; + } + + // Add specular lighting + if( params[envmapVar]->IsTexture() ) + { + DrawWorldBumpedSpecularLighting( + bumpmapVar, envmapVar, + bumpFrameVar, envmapFrameVar, + envmapTintVar, alphaVar, + envmapContrastVar, envmapSaturationVar, + bumpTransformVar, fresnelReflectionVar, + bBlendSpecular ); + } +} +#endif // GAME_SHADER_DLL + + +//----------------------------------------------------------------------------- +// GR - translucency query +//----------------------------------------------------------------------------- +BlendType_t CBaseVSShader::EvaluateBlendRequirements( int textureVar, bool isBaseTexture, + int detailTextureVar ) +{ + // Either we've got a constant modulation + bool isTranslucent = IsAlphaModulating(); + + // Or we've got a vertex alpha + isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA); + + // Or we've got a texture alpha (for blending or alpha test) + isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) && + !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) ); + + if ( ( detailTextureVar != -1 ) && ( ! isTranslucent ) ) + { + isTranslucent = TextureIsTranslucent( detailTextureVar, isBaseTexture ); + } + + if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE ) + { + return isTranslucent ? BT_BLENDADD : BT_ADD; // Additive + } + else + { + return isTranslucent ? BT_BLEND : BT_NONE; // Normal blending + } +} + +#ifndef GAME_SHADER_DLL + +void CBaseVSShader::SetFlashlightVertexShaderConstants( bool bBump, int bumpTransformVar, bool bDetail, int detailScaleVar, bool bSetTextureTransforms ) +{ + Assert( !IsSnapshotting() ); + + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = s_pShaderAPI->GetFlashlightState( worldToTexture ); + + // Set the flashlight origin + float pos[4]; + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = 1.0f / ( ( 0.6f * flashlightState.m_FarZ ) - flashlightState.m_FarZ ); // DX8 needs this + + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, pos, 1 ); + + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, worldToTexture.Base(), 4 ); + + // Set the flashlight attenuation factors + float atten[4]; + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, atten, 1 ); + + if ( bDetail ) + { + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, BASETEXTURETRANSFORM, detailScaleVar ); + } + + if( bSetTextureTransforms ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, BASETEXTURETRANSFORM ); + if( !bDetail && bBump && bumpTransformVar != -1 ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, bumpTransformVar ); // aliased on top of detail transform + } + } +} + +#if SUPPORT_DX8 +void CBaseVSShader::DrawFlashlight_dx80( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBump, + int bumpmapVar, int bumpmapFrame, int bumpTransform, int flashlightTextureVar, int flashlightTextureFrameVar, + bool bLightmappedGeneric, bool bWorldVertexTransition, int nWorldVertexTransitionPassID, int baseTexture2Var, + int baseTexture2FrameVar, bool bTeeth, int nTeethForwardVar, int nTeethIllumFactorVar ) +{ + // FLASHLIGHTFIXME: hack . . need to fix the vertex shader so that it can deal with and without bumps for vertexlitgeneric + if( !bLightmappedGeneric ) + { + bBump = false; + } + if( pShaderShadow ) + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + // Never alpha test the flashlight pass + pShaderShadow->EnableAlphaTest( false ); + + if ( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) ) + { + // use zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + + // Alpha blend + if( bWorldVertexTransition ) + { + // use separate alpha blend to make sure that we aren't adding alpha from source + if( nWorldVertexTransitionPassID == 0 ) + { + EnableAlphaBlending( SHADER_BLEND_DST_ALPHA, SHADER_BLEND_ONE ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_DST_ALPHA, SHADER_BLEND_ONE ); + } + } + else + { + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + if( bLightmappedGeneric ) + { + bool bUsingVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + lightmappedgeneric_flashlight_vs11_Static_Index vshIndex; + vshIndex.SetNORMALMAP( bBump ); + vshIndex.SetWORLDVERTEXTRANSITION( bWorldVertexTransition ); + vshIndex.SetVERTEXCOLOR( bUsingVertexColor ); + pShaderShadow->SetVertexShader( "lightmappedgeneric_flashlight_vs11", vshIndex.GetIndex() ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + if( bBump ) + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + if ( bWorldVertexTransition || bUsingVertexColor ) + { + flags |= VERTEX_COLOR; + } + pShaderShadow->VertexShaderVertexFormat( flags, 1, 0, 0 ); + } + else + { + vertexlitgeneric_flashlight_vs11_Static_Index vshIndex; + vshIndex.SetTEETH( bTeeth ); + pShaderShadow->SetVertexShader( "vertexlitgeneric_flashlight_vs11", vshIndex.GetIndex() ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( flags, 1, 0, bBump ? 4 : 0 ); + } + + bool bNoCull = IS_FLAG_SET( MATERIAL_VAR_NOCULL ); + + flashlight_ps11_Static_Index pshIndex; + pshIndex.SetNORMALMAP( bBump ); + pshIndex.SetNOCULL( bNoCull ); + pShaderShadow->SetPixelShader( "flashlight_ps11", pshIndex.GetIndex() ); + + FogToBlack(); + } + else + { + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 0, true ); + BindTexture( SHADER_SAMPLER0, flashlightTextureVar, flashlightTextureFrameVar ); + + if( bWorldVertexTransition && ( nWorldVertexTransitionPassID == 1 ) ) + { + BindTexture( SHADER_SAMPLER1, baseTexture2Var, baseTexture2FrameVar ); + } + else + { + if( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP ); + if( bBump ) + { + BindTexture( SHADER_SAMPLER3, bumpmapVar, bumpmapFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + } + + if( bLightmappedGeneric ) + { + lightmappedgeneric_flashlight_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + vertexlitgeneric_flashlight_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + + if( bTeeth ) + { + Assert( nTeethForwardVar >= 0 ); + Assert( nTeethIllumFactorVar >= 0 ); + Vector4D lighting; + params[nTeethForwardVar]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[nTeethIllumFactorVar]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, lighting.Base() ); + } + + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + flashlight_ps11_Dynamic_Index pshIndex; + pShaderAPI->SetPixelShaderIndex( pshIndex.GetIndex() ); + + SetFlashlightVertexShaderConstants( bBump, bumpTransform, false, -1, true ); + } + Draw(); +} +#endif // support_dx8 + +#ifdef STDSHADER_DX9_DLL_EXPORT +void CBaseVSShader::DrawFlashlight_dx90( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, DrawFlashlight_dx90_Vars_t &vars ) +{ + // FLASHLIGHTFIXME: hack . . need to fix the vertex shader so that it can deal with and without bumps for vertexlitgeneric + if( !vars.m_bLightmappedGeneric ) + { + vars.m_bBump = false; + } + bool bBump2 = vars.m_bWorldVertexTransition && vars.m_bBump && vars.m_nBumpmap2Var != -1 && params[vars.m_nBumpmap2Var]->IsTexture(); + bool bSeamless = vars.m_fSeamlessScale != 0.0; + bool bDetail = vars.m_bLightmappedGeneric && (vars.m_nDetailVar != -1) && params[vars.m_nDetailVar]->IsDefined() && (vars.m_nDetailScale != -1); + + int nDetailBlendMode = 0; + if ( bDetail ) + { + nDetailBlendMode = GetIntParam( vars.m_nDetailTextureCombineMode, params ); + nDetailBlendMode = nDetailBlendMode > 1 ? 1 : nDetailBlendMode; + } + + if( pShaderShadow ) + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + // Alpha blend + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) ); + if ( vars.m_nAlphaTestReference != -1 && params[vars.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[vars.m_nAlphaTestReference]->GetFloatValue() ); + } + + // Spot sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + // Base sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + + // Normalizing cubemap sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // Normalizing cubemap sampler2 or normal map sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + // RandomRotation sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + + // Flashlight depth sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 ); + + if( vars.m_bWorldVertexTransition ) + { + // $basetexture2 + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + } + if( bBump2 ) + { + // Normalmap2 sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + } + if( bDetail ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // detail sampler + if ( nDetailBlendMode != 0 ) //Not Mod2X + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + if( vars.m_bLightmappedGeneric ) + { + lightmappedgeneric_flashlight_vs20_Static_Index vshIndex; + vshIndex.SetWORLDVERTEXTRANSITION( vars.m_bWorldVertexTransition ); + vshIndex.SetNORMALMAP( vars.m_bBump ); + vshIndex.SetSEAMLESS( bSeamless ); + vshIndex.SetDETAIL( bDetail ); + pShaderShadow->SetVertexShader( "lightmappedgeneric_flashlight_vs20", vshIndex.GetIndex() ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + if( vars.m_bBump ) + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + int numTexCoords = 1; + if( vars.m_bWorldVertexTransition ) + { + flags |= VERTEX_COLOR; + numTexCoords = 2; // need lightmap texcoords to get alpha. + } + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + } + else + { + vertexlitgeneric_flashlight_vs11_Static_Index vshIndex; + vshIndex.SetTEETH( vars.m_bTeeth ); + pShaderShadow->SetVertexShader( "vertexlitgeneric_flashlight_vs11", vshIndex.GetIndex() ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int numTexCoords = 1; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, vars.m_bBump ? 4 : 0 ); + } + + int nBumpMapVariant = 0; + if ( vars.m_bBump ) + { + nBumpMapVariant = ( vars.m_bSSBump ) ? 2 : 1; + } + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); + + flashlight_ps20b_Static_Index pshIndex; + pshIndex.SetNORMALMAP( nBumpMapVariant ); + pshIndex.SetNORMALMAP2( bBump2 ); + pshIndex.SetWORLDVERTEXTRANSITION( vars.m_bWorldVertexTransition ); + pshIndex.SetSEAMLESS( bSeamless ); + pshIndex.SetDETAILTEXTURE( bDetail ); + pshIndex.SetDETAIL_BLEND_MODE( nDetailBlendMode ); + pshIndex.SetFLASHLIGHTDEPTHFILTERMODE( nShadowFilterMode ); + pShaderShadow->SetPixelShader( "flashlight_ps20b", pshIndex.GetIndex() ); + } + else + { + flashlight_ps20_Static_Index pshIndex; + pshIndex.SetNORMALMAP( nBumpMapVariant ); + pshIndex.SetNORMALMAP2( bBump2 ); + pshIndex.SetWORLDVERTEXTRANSITION( vars.m_bWorldVertexTransition ); + pshIndex.SetSEAMLESS( bSeamless ); + pshIndex.SetDETAILTEXTURE( bDetail ); + pshIndex.SetDETAIL_BLEND_MODE( nDetailBlendMode ); + pShaderShadow->SetPixelShader( "flashlight_ps20", pshIndex.GetIndex() ); + } + FogToBlack(); + } + else + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + SetFlashLightColorFromState( flashlightState, pShaderAPI ); + + BindTexture( SHADER_SAMPLER0, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + BindTexture( SHADER_SAMPLER7, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + + // Tweaks associated with a given flashlight + float tweaks[4]; + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + } + + if( params[BASETEXTURE]->IsTexture() && mat_fullbright.GetInt() != 2 ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + if( vars.m_bWorldVertexTransition ) + { + Assert( vars.m_nBaseTexture2Var >= 0 && vars.m_nBaseTexture2FrameVar >= 0 ); + BindTexture( SHADER_SAMPLER4, vars.m_nBaseTexture2Var, vars.m_nBaseTexture2FrameVar ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP ); + if( vars.m_bBump ) + { + BindTexture( SHADER_SAMPLER3, vars.m_nBumpmapVar, vars.m_nBumpmapFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + } + + if( bDetail ) + { + BindTexture( SHADER_SAMPLER8, vars.m_nDetailVar ); + } + + if( vars.m_bWorldVertexTransition ) + { + if( bBump2 ) + { + BindTexture( SHADER_SAMPLER6, vars.m_nBumpmap2Var, vars.m_nBumpmap2Frame ); + } + } + + if( vars.m_bLightmappedGeneric ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 ); + if ( bSeamless ) + { + float const0[4]={ vars.m_fSeamlessScale,0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, const0 ); + } + + if ( bDetail ) + { + float vDetailConstants[4] = {1,1,1,1}; + + if ( vars.m_nDetailTint != -1 ) + { + params[vars.m_nDetailTint]->GetVecValue( vDetailConstants, 3 ); + } + + if ( vars.m_nDetailTextureBlendFactor != -1 ) + { + vDetailConstants[3] = params[vars.m_nDetailTextureBlendFactor]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vDetailConstants, 1 ); + } + } + else + { + vertexlitgeneric_flashlight_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( vars.m_bTeeth ) + { + Assert( vars.m_nTeethForwardVar >= 0 ); + Assert( vars.m_nTeethIllumFactorVar >= 0 ); + Vector4D lighting; + params[vars.m_nTeethForwardVar]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[vars.m_nTeethIllumFactorVar]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() ); + } + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ) ); + SET_DYNAMIC_PIXEL_SHADER( flashlight_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( flashlight_ps20 ); + } + + float atten[4]; // Set the flashlight attenuation factors + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + s_pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + SetFlashlightVertexShaderConstants( vars.m_bBump, vars.m_nBumpTransform, bDetail, vars.m_nDetailScale, bSeamless ? false : true ); + } + Draw(); +} + +#endif + +void CBaseVSShader::InitParamsUnlitGeneric_DX8( + int baseTextureVar, + int detailScaleVar, + int envmapOptionalVar, + int envmapVar, + int envmapTintVar, + int envmapMaskScaleVar, + int nDetailBlendMode ) +{ + IMaterialVar** params = s_ppParams; + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( envmapTintVar >= 0 && !params[envmapTintVar]->IsDefined() ) + { + params[envmapTintVar]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( envmapMaskScaleVar >= 0 && !params[envmapMaskScaleVar]->IsDefined() ) + { + params[envmapMaskScaleVar]->SetFloatValue( 1.0f ); + } + + if( detailScaleVar >= 0 && !params[detailScaleVar]->IsDefined() ) + { + params[detailScaleVar]->SetFloatValue( 4.0f ); + } + + // No texture means no self-illum or env mask in base alpha + if ( baseTextureVar >= 0 && !params[baseTextureVar]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + // Get rid of the envmap if it's optional for this dx level. + if( envmapOptionalVar >= 0 && params[envmapOptionalVar]->IsDefined() && params[envmapOptionalVar]->GetIntValue() ) + { + if (envmapVar >= 0) + { + params[envmapVar]->SetUndefined(); + } + } + + // If mat_specular 0, then get rid of envmap + if( envmapVar >= 0 && baseTextureVar >= 0 && !g_pConfig->UseSpecular() && params[envmapVar]->IsDefined() && params[baseTextureVar]->IsDefined() ) + { + params[envmapVar]->SetUndefined(); + } +} + +void CBaseVSShader::InitUnlitGeneric_DX8( + int baseTextureVar, + int detailVar, + int envmapVar, + int envmapMaskVar ) +{ + IMaterialVar** params = s_ppParams; + + if (baseTextureVar >= 0 && params[baseTextureVar]->IsDefined()) + { + LoadTexture( baseTextureVar ); + + if (!params[baseTextureVar]->GetTextureValue()->IsTranslucent()) + { + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if ( IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + // the second texture (if there is one) + if (detailVar >= 0 && params[detailVar]->IsDefined()) + { + LoadTexture( detailVar ); + } + + if (envmapVar >= 0 && params[envmapVar]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( envmapVar ); + else + LoadTexture( envmapVar ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + SET_FLAGS(MATERIAL_VAR_ENVMAPSPHERE); + + if (envmapMaskVar >= 0 && params[envmapMaskVar]->IsDefined()) + LoadTexture( envmapMaskVar ); + } +} +#endif // GAME_SHADER_DLL + +#endif // !_STATIC_LINKED || STDSHADER_DX8_DLL_EXPORT + + +// Take 0..1 seed and map to (u, v) coordinate to be used in shadow filter jittering... +void CBaseVSShader::HashShadow2DJitter( const float fJitterSeed, float *fU, float* fV ) +{ + const int nTexRes = 32; + int nSeed = fmod (fJitterSeed, 1.0f) * nTexRes * nTexRes; + + int nRow = nSeed / nTexRes; + int nCol = nSeed % nTexRes; + + // Div and mod to get an individual texel in the fTexRes x fTexRes grid + *fU = nRow / (float) nTexRes; // Row + *fV = nCol / (float) nTexRes; // Column +} + + +void CBaseVSShader::DrawEqualDepthToDestAlpha( void ) +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + bool bMakeActualDrawCall = false; + if( s_pShaderShadow ) + { + s_pShaderShadow->EnableColorWrites( false ); + s_pShaderShadow->EnableAlphaWrites( true ); + s_pShaderShadow->EnableDepthWrites( false ); + s_pShaderShadow->EnableAlphaTest( false ); + s_pShaderShadow->EnableBlending( false ); + + s_pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + + s_pShaderShadow->SetVertexShader( "depthtodestalpha_vs20", 0 ); + s_pShaderShadow->SetPixelShader( "depthtodestalpha_ps20b", 0 ); + } + if( s_pShaderAPI ) + { + s_pShaderAPI->SetVertexShaderIndex( 0 ); + s_pShaderAPI->SetPixelShaderIndex( 0 ); + + bMakeActualDrawCall = s_pShaderAPI->ShouldWriteDepthToDestAlpha(); + } + Draw( bMakeActualDrawCall ); + } +#else + Assert( 0 ); //probably just needs a shader update to the latest +#endif +} diff --git a/sp/src/materialsystem/stdshaders/BaseVSShader.h b/sp/src/materialsystem/stdshaders/BaseVSShader.h new file mode 100644 index 00000000..2a38afb1 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BaseVSShader.h @@ -0,0 +1,439 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// This is what all vs/ps (dx8+) shaders inherit from. +//===========================================================================// + +#ifndef BASEVSSHADER_H +#define BASEVSSHADER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "shaderlib/cshader.h" +#include "shaderlib/BaseShader.h" +#include "convar.h" +#include + +#ifdef _X360 +#define SUPPORT_DX8 0 +#define SUPPORT_DX7 0 +#else +#define SUPPORT_DX8 1 +#define SUPPORT_DX7 1 +#endif +//----------------------------------------------------------------------------- +// Helper macro for vertex shaders +//----------------------------------------------------------------------------- +#define BEGIN_VS_SHADER_FLAGS(_name, _help, _flags) __BEGIN_SHADER_INTERNAL( CBaseVSShader, _name, _help, _flags ) +#define BEGIN_VS_SHADER(_name,_help) __BEGIN_SHADER_INTERNAL( CBaseVSShader, _name, _help, 0 ) + + +// useful parameter initialization macro +#define INIT_FLOAT_PARM( parm, value ) \ + if ( !params[(parm)]->IsDefined() ) \ + { \ + params[(parm)]->SetFloatValue( (value) ); \ + } + +// useful pixel shader declaration macro for ps20/20b c++ code +#define SET_STATIC_PS2X_PIXEL_SHADER_NO_COMBOS( basename ) \ + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) \ + { \ + DECLARE_STATIC_PIXEL_SHADER( basename##_ps20b ); \ + SET_STATIC_PIXEL_SHADER( basename##_ps20b ); \ + } \ + else \ + { \ + DECLARE_STATIC_PIXEL_SHADER( basename##_ps20 ); \ + SET_STATIC_PIXEL_SHADER( basename##_ps20 ); \ + } + +#define SET_DYNAMIC_PS2X_PIXEL_SHADER_NO_COMBOS( basename ) \ + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) \ + { \ + DECLARE_DYNAMIC_PIXEL_SHADER( basename##_ps20b ); \ + SET_DYNAMIC_PIXEL_SHADER( basename##_ps20b ); \ + } \ + else \ + { \ + DECLARE_DYNAMIC_PIXEL_SHADER( basename##_ps20 ); \ + SET_DYNAMIC_PIXEL_SHADER( basename##_ps20 ); \ + } + + +//----------------------------------------------------------------------------- +// Base class for shaders, contains helper methods. +//----------------------------------------------------------------------------- +class CBaseVSShader : public CBaseShader +{ +public: + + // Loads bump lightmap coordinates into the pixel shader + void LoadBumpLightmapCoordinateAxes_PixelShader( int pixelReg ); + + // Loads bump lightmap coordinates into the vertex shader + void LoadBumpLightmapCoordinateAxes_VertexShader( int vertexReg ); + + // Pixel and vertex shader constants.... + void SetPixelShaderConstant( int pixelReg, int constantVar ); + + // Pixel and vertex shader constants.... + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ); + + // This version will put constantVar into x,y,z, and constantVar2 into the w + void SetPixelShaderConstant( int pixelReg, int constantVar, int constantVar2 ); + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar, int constantVar2 ); + + // Helpers for setting constants that need to be converted to linear space (from gamma space). + void SetVertexShaderConstantGammaToLinear( int var, float const* pVec, int numConst = 1, bool bForce = false ); + void SetPixelShaderConstantGammaToLinear( int var, float const* pVec, int numConst = 1, bool bForce = false ); + + void SetVertexShaderConstant( int vertexReg, int constantVar ); + + // set rgb components of constant from a color parm and give an explicit w value + void SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ); + + // GR - fix for const/lerp issues + void SetPixelShaderConstantFudge( int pixelReg, int constantVar ); + + // Sets light direction for pixel shaders. + void SetPixelShaderLightColors( int pixelReg ); + + // Sets vertex shader texture transforms + void SetVertexShaderTextureTranslation( int vertexReg, int translationVar ); + void SetVertexShaderTextureScale( int vertexReg, int scaleVar ); + void SetVertexShaderTextureTransform( int vertexReg, int transformVar ); + void SetVertexShaderTextureScaledTransform( int vertexReg, + int transformVar, int scaleVar ); + + // Set pixel shader texture transforms + void SetPixelShaderTextureTranslation( int pixelReg, int translationVar ); + void SetPixelShaderTextureScale( int pixelReg, int scaleVar ); + void SetPixelShaderTextureTransform( int pixelReg, int transformVar ); + void SetPixelShaderTextureScaledTransform( int pixelReg, + int transformVar, int scaleVar ); + + // Moves a matrix into vertex shader constants + void SetVertexShaderMatrix3x4( int vertexReg, int matrixVar ); + void SetVertexShaderMatrix4x4( int vertexReg, int matrixVar ); + + // Loads the view matrix into vertex shader constants + void LoadViewMatrixIntoVertexShaderConstant( int vertexReg ); + + // Loads the projection matrix into vertex shader constants + void LoadProjectionMatrixIntoVertexShaderConstant( int vertexReg ); + + // Loads the model->view matrix into vertex shader constants + void LoadModelViewMatrixIntoVertexShaderConstant( int vertexReg ); + + // Loads a scale/offset version of the viewport transform into the specified constant. + void LoadViewportTransformScaledIntoVertexShaderConstant( int vertexReg ); + + // Sets up ambient light cube... + void SetAmbientCubeDynamicStateVertexShader( ); + float GetAmbientLightCubeLuminance( ); + + // Helpers for dealing with envmaptint + void SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar, int alphaVar, bool bConvertFromGammaToLinear = false ); + + // Helper methods for pixel shader overbrighting + void EnablePixelShaderOverbright( int reg, bool bEnable, bool bDivideByTwo ); + + // Helper for dealing with modulation + void SetModulationVertexShaderDynamicState(); + void SetModulationPixelShaderDynamicState( int modulationVar ); + void SetModulationPixelShaderDynamicState_LinearColorSpace( int modulationVar ); + void SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int modulationVar, float flScale ); + + // Sets a color + alpha into shader constants + void SetColorVertexShaderConstant( int nVertexReg, int colorVar, int alphaVar ); + void SetColorPixelShaderConstant( int nPixelReg, int colorVar, int alphaVar ); + + +#ifndef GAME_SHADER_DLL + // + // Standard shader passes! + // + + void InitParamsUnlitGeneric_DX8( + int baseTextureVar, + int detailScaleVar, + int envmapOptionalVar, + int envmapVar, + int envmapTintVar, + int envmapMaskScaleVar, + int nDetailBlendMode ); + + void InitUnlitGeneric_DX8( + int baseTextureVar, + int detailVar, + int envmapVar, + int envmapMaskVar ); + + // Dx8 Unlit Generic pass + void VertexShaderUnlitGenericPass( int baseTextureVar, int frameVar, + int baseTextureTransformVar, + int detailVar, int detailTransform, bool bDetailTransformIsScale, + int envmapVar, int envMapFrameVar, int envmapMaskVar, + int envmapMaskFrameVar, int envmapMaskScaleVar, int envmapTintVar, + int alphaTestReferenceVar, + int nDetailBlendModeVar, + int nOutlineVar, + int nOutlineColorVar, + int nOutlineStartVar, + int nOutlineEndVar, + int nSeparateDetailUVsVar + ); + + // Helpers for drawing world bump mapped stuff. + void DrawModelBumpedSpecularLighting( int bumpMapVar, int bumpMapFrameVar, + int envMapVar, int envMapVarFrame, + int envMapTintVar, int alphaVar, + int envMapContrastVar, int envMapSaturationVar, + int bumpTransformVar, + bool bBlendSpecular, bool bNoWriteZ = false ); + void DrawWorldBumpedSpecularLighting( int bumpmapVar, int envmapVar, + int bumpFrameVar, int envmapFrameVar, + int envmapTintVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, + int bumpTransformVar, int fresnelReflectionVar, + bool bBlend, bool bNoWriteZ = false ); + + const char *UnlitGeneric_ComputeVertexShaderName( bool bMask, + bool bEnvmap, + bool bBaseTexture, + bool bBaseAlphaEnvmapMask, + bool bDetail, + bool bVertexColor, + bool bEnvmapCameraSpace, + bool bEnvmapSphere ); + + const char *UnlitGeneric_ComputePixelShaderName( bool bMask, + bool bEnvmap, + bool bBaseTexture, + bool bBaseAlphaEnvmapMask, + bool bDetail, + bool bMultiplyDetail, + bool bMaskBaseByDetailAlpha ); + + void DrawWorldBaseTexture( int baseTextureVar, int baseTextureTransformVar, int frameVar, int colorVar, int alphaVar ); + void DrawWorldBumpedDiffuseLighting( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, bool bMultiply, bool bSSBump ); + void DrawWorldBumpedSpecularLighting( int envmapMaskVar, int envmapMaskFrame, + int bumpmapVar, int envmapVar, + int bumpFrameVar, int envmapFrameVar, + int envmapTintVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, + int bumpTransformVar, int fresnelReflectionVar, + bool bBlend ); + void DrawBaseTextureBlend( int baseTextureVar, int baseTextureTransformVar, + int baseTextureFrameVar, + int baseTexture2Var, int baseTextureTransform2Var, + int baseTextureFrame2Var, int colorVar, int alphaVar ); + void DrawWorldBumpedDiffuseLighting_Base_ps14( int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, int baseTextureVar, int baseTextureTransformVar, int frameVar ); + void DrawWorldBumpedDiffuseLighting_Blend_ps14( int bumpmapVar, int bumpFrameVar, int bumpTransformVar, + int baseTextureVar, int baseTextureTransformVar, int baseTextureFrameVar, + int baseTexture2Var, int baseTextureTransform2Var, int baseTextureFrame2Var); + void DrawWorldBumpedUsingVertexShader( int baseTextureVar, int baseTextureTransformVar, + int bumpmapVar, int bumpFrameVar, + int bumpTransformVar, + int envmapMaskVar, int envmapMaskFrame, + int envmapVar, + int envmapFrameVar, + int envmapTintVar, int colorVar, int alphaVar, + int envmapContrastVar, int envmapSaturationVar, int frameVar, int fresnelReflectionVar, + bool doBaseTexture2, + int baseTexture2Var, + int baseTextureTransform2Var, + int baseTextureFrame2Var, + bool bSSBump + ); + + // Sets up hw morphing state for the vertex shader + void SetHWMorphVertexShaderState( int nDimConst, int nSubrectConst, VertexTextureSampler_t morphSampler ); + + // Computes the shader index for vertex lit materials + int ComputeVertexLitShaderIndex( bool bVertexLitGeneric, bool hasBump, bool hasEnvmap, bool hasVertexColor, bool bHasNormal ) const; + + // Helper for setting up flashlight constants + void SetFlashlightVertexShaderConstants( bool bBump, int bumpTransformVar, bool bDetail, int detailScaleVar, bool bSetTextureTransforms ); + +#if SUPPORT_DX8 + void DrawFlashlight_dx80( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bBump, int bumpmapVar, int bumpmapFrame, int bumpTransform, int flashlightTextureVar, + int flashlightTextureFrameVar, bool bLightmappedGeneric, bool bWorldVertexTransition, + int nWorldVertexTransitionPassID, int baseTexture2Var, int baseTexture2FrameVar, + bool bTeeth=false, int nTeethForwardVar=0, int nTeethIllumFactorVar=0 ); +#endif + + struct DrawFlashlight_dx90_Vars_t + { + DrawFlashlight_dx90_Vars_t() + { + // set all ints to -1 + memset( this, 0xFF, sizeof(DrawFlashlight_dx90_Vars_t) ); + // set all bools to a default value. + m_bBump = false; + m_bLightmappedGeneric = false; + m_bWorldVertexTransition = false; + m_bTeeth = false; + m_bSSBump = false; + m_fSeamlessScale = 0.0; + } + bool m_bBump; + bool m_bLightmappedGeneric; + bool m_bWorldVertexTransition; + bool m_bTeeth; + int m_nBumpmapVar; + int m_nBumpmapFrame; + int m_nBumpTransform; + int m_nFlashlightTextureVar; + int m_nFlashlightTextureFrameVar; + int m_nBaseTexture2Var; + int m_nBaseTexture2FrameVar; + int m_nBumpmap2Var; + int m_nBumpmap2Frame; + int m_nBump2Transform; + int m_nDetailVar; + int m_nDetailScale; + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + int m_nDetailTint; + int m_nTeethForwardVar; + int m_nTeethIllumFactorVar; + int m_nAlphaTestReference; + bool m_bSSBump; + float m_fSeamlessScale; // 0.0 = not seamless + }; + void DrawFlashlight_dx90( IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, DrawFlashlight_dx90_Vars_t &vars ); +#endif // GAME_SHADER_DLL + + BlendType_t EvaluateBlendRequirements( int textureVar, bool isBaseTexture, int detailTextureVar = -1 ); + + void HashShadow2DJitter( const float fJitterSeed, float *fU, float* fV ); + + //Alpha tested materials can end up leaving garbage in the dest alpha buffer if they write depth. + //This pass fills in the areas that passed the alpha test with depth in dest alpha + //by writing only equal depth pixels and only if we should be writing depth to dest alpha + void DrawEqualDepthToDestAlpha( void ); + +private: + // Helper methods for VertexLitGenericPass +// void UnlitGenericShadowState( int baseTextureVar, int detailVar, int envmapVar, int envmapMaskVar, bool doSkin ); + void UnlitGenericDynamicState( int baseTextureVar, int frameVar, int baseTextureTransformVar, + int detailVar, int detailTransform, bool bDetailTransformIsScale, int envmapVar, + int envMapFrameVar, int envmapMaskVar, int envmapMaskFrameVar, + int envmapMaskScaleVar, int envmapTintVar ); + + // Converts a color + alpha into a vector4 + void ColorVarsToVector( int colorVar, int alphaVar, Vector4D &color ); + +}; + +FORCEINLINE void SetFlashLightColorFromState( FlashlightState_t const &state, IShaderDynamicAPI *pShaderAPI, int nPSRegister=28, bool bFlashlightNoLambert=false ) +{ + // Old code + //float flToneMapScale = ( pShaderAPI->GetToneMappingScaleLinear() ).x; + //float flFlashlightScale = 1.0f / flToneMapScale; + + // Fix to old code to keep flashlight from ever getting brighter than 1.0 + //float flToneMapScale = ( pShaderAPI->GetToneMappingScaleLinear() ).x; + //if ( flToneMapScale < 1.0f ) + // flToneMapScale = 1.0f; + //float flFlashlightScale = 1.0f / flToneMapScale; + + // Force flashlight to 25% bright always + float flFlashlightScale = 0.25f; + + if ( !g_pHardwareConfig->GetHDREnabled() ) + { + // Non-HDR path requires 2.0 flashlight + flFlashlightScale = 2.0f; + } + + // DX10 requires some hackery due to sRGB/blend ordering change from DX9 + if ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) + { + flFlashlightScale *= 2.5f; // Magic number that works well on the NVIDIA 8800 + } + + // Generate pixel shader constant + float const *pFlashlightColor = state.m_Color; + float vPsConst[4] = { flFlashlightScale * pFlashlightColor[0], flFlashlightScale * pFlashlightColor[1], flFlashlightScale * pFlashlightColor[2], pFlashlightColor[3] }; + vPsConst[3] = bFlashlightNoLambert ? 2.0f : 0.0f; // This will be added to N.L before saturate to force a 1.0 N.L term + + // Red flashlight for testing + //vPsConst[0] = 0.5f; vPsConst[1] = 0.0f; vPsConst[2] = 0.0f; + + pShaderAPI->SetPixelShaderConstant( nPSRegister, ( float * )vPsConst ); +} + +FORCEINLINE float ShadowAttenFromState( FlashlightState_t const &state ) +{ + // DX10 requires some hackery due to sRGB/blend ordering change from DX9, which makes the shadows too light + if ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) + return state.m_flShadowAtten * 0.1f; // magic number + + return state.m_flShadowAtten; +} + +FORCEINLINE float ShadowFilterFromState( FlashlightState_t const &state ) +{ + // We developed shadow maps at 1024, so we expect the penumbra size to have been tuned relative to that + return state.m_flShadowFilterSize / 1024.0f; +} + + +// convenient material variable access functions for helpers to use. +FORCEINLINE bool IsTextureSet( int nVar, IMaterialVar **params ) +{ + return ( nVar != -1 ) && ( params[nVar]->IsTexture() ); +} + +FORCEINLINE bool IsBoolSet( int nVar, IMaterialVar **params ) +{ + return ( nVar != -1 ) && ( params[nVar]->GetIntValue() ); +} + +FORCEINLINE int GetIntParam( int nVar, IMaterialVar **params, int nDefaultValue = 0 ) +{ + return ( nVar != -1 ) ? ( params[nVar]->GetIntValue() ) : nDefaultValue; +} + +FORCEINLINE float GetFloatParam( int nVar, IMaterialVar **params, float flDefaultValue = 0.0 ) +{ + return ( nVar != -1 ) ? ( params[nVar]->GetFloatValue() ) : flDefaultValue; +} + +FORCEINLINE void InitFloatParam( int nIndex, IMaterialVar **params, float flValue ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetFloatValue( flValue ); + } +} + +FORCEINLINE void InitIntParam( int nIndex, IMaterialVar **params, int nValue ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetIntValue( nValue ); + } +} + + +class ConVar; + +#ifdef _DEBUG +extern ConVar mat_envmaptintoverride; +extern ConVar mat_envmaptintscale; +#endif + + +#endif // BASEVSSHADER_H diff --git a/sp/src/materialsystem/stdshaders/buildepisodicshaders.bat b/sp/src/materialsystem/stdshaders/buildepisodicshaders.bat new file mode 100644 index 00000000..beeeb93b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/buildepisodicshaders.bat @@ -0,0 +1,21 @@ +@echo off +setlocal + +rem ================================ +rem ==== MOD PATH CONFIGURATIONS === + +rem == Set the absolute path to your mod's game directory here == +set GAMEDIR=%cd%\..\..\..\game\mod_episodic + +rem == Set the relative or absolute path to Source SDK Base 2013 Singleplayer\bin == +set SDKBINDIR=D:\SteamBeta\SteamApps\common\Source SDK Base 2013 Singleplayer\bin + +rem == Set the Path to your mod's root source code == +rem This should already be correct, accepts relative paths only! +set SOURCEDIR=..\.. + +rem ==== MOD PATH CONFIGURATIONS END === +rem ==================================== + + +call buildsdkshaders.bat diff --git a/sp/src/materialsystem/stdshaders/buildhl2shaders.bat b/sp/src/materialsystem/stdshaders/buildhl2shaders.bat new file mode 100644 index 00000000..3324e8cd --- /dev/null +++ b/sp/src/materialsystem/stdshaders/buildhl2shaders.bat @@ -0,0 +1,21 @@ +@echo off +setlocal + +rem ================================ +rem ==== MOD PATH CONFIGURATIONS === + +rem == Set the absolute path to your mod's game directory here == +set GAMEDIR=%cd%\..\..\..\game\mod_hl2 + +rem == Set the relative or absolute path to Source SDK Base 2013 Singleplayer\bin == +set SDKBINDIR=D:\SteamBeta\SteamApps\common\Source SDK Base 2013 Singleplayer\bin + +rem == Set the Path to your mod's root source code == +rem This should already be correct, accepts relative paths only! +set SOURCEDIR=..\.. + +rem ==== MOD PATH CONFIGURATIONS END === +rem ==================================== + + +call buildsdkshaders.bat diff --git a/sp/src/materialsystem/stdshaders/buildsdkshaders.bat b/sp/src/materialsystem/stdshaders/buildsdkshaders.bat new file mode 100644 index 00000000..eeaa5b8c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/buildsdkshaders.bat @@ -0,0 +1,40 @@ +@echo off +setlocal + +rem Use dynamic shaders to build .inc files only +rem set dynamic_shaders=1 +rem == Setup path to nmake.exe, from vc 2005 common tools directory == +call "%VS100COMNTOOLS%vsvars32.bat" + + +set TTEXE=..\..\devtools\bin\timeprecise.exe +if not exist %TTEXE% goto no_ttexe +goto no_ttexe_end + +:no_ttexe +set TTEXE=time /t +:no_ttexe_end + + +rem echo. +rem echo ~~~~~~ buildsdkshaders %* ~~~~~~ +%TTEXE% -cur-Q +set tt_all_start=%ERRORLEVEL% +set tt_all_chkpt=%tt_start% + +set BUILD_SHADER=call buildshaders.bat +set ARG_EXTRA= + +%BUILD_SHADER% stdshader_dx9_20b -game %GAMEDIR% -source %SOURCEDIR% +%BUILD_SHADER% stdshader_dx9_30 -game %GAMEDIR% -source %SOURCEDIR% -dx9_30 -force30 + + +rem echo. +if not "%dynamic_shaders%" == "1" ( + rem echo Finished full buildallshaders %* +) else ( + rem echo Finished dynamic buildallshaders %* +) + +rem %TTEXE% -diff %tt_all_start% -cur +rem echo. diff --git a/sp/src/materialsystem/stdshaders/buildshaders.bat b/sp/src/materialsystem/stdshaders/buildshaders.bat new file mode 100644 index 00000000..64859912 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/buildshaders.bat @@ -0,0 +1,209 @@ +@echo off + +set TTEXE=..\..\devtools\bin\timeprecise.exe +if not exist %TTEXE% goto no_ttexe +goto no_ttexe_end + +:no_ttexe +set TTEXE=time /t +:no_ttexe_end + +echo. +echo ==================== buildshaders %* ================== +%TTEXE% -cur-Q +set tt_start=%ERRORLEVEL% +set tt_chkpt=%tt_start% + + +REM **************** +REM usage: buildshaders +REM **************** + +setlocal +set arg_filename=%1 +set shadercompilecommand=shadercompile.exe +set targetdir=shaders +set SrcDirBase=..\.. +set shaderDir=shaders +set SDKArgs= +set SHADERINCPATH=vshtmp9/... fxctmp9/... + + +if "%1" == "" goto usage +set inputbase=%1 + +set DIRECTX_SDK_VER=pc09.00 +set DIRECTX_SDK_BIN_DIR=dx9sdk\utilities + +if /i "%6" == "-dx9_30" goto dx_sdk_dx9_30 +goto dx_sdk_end +:dx_sdk_dx9_30 + set DIRECTX_SDK_VER=pc09.30 + set DIRECTX_SDK_BIN_DIR=dx10sdk\utilities\dx9_30 + goto dx_sdk_end +:dx_sdk_end + +if /i "%7" == "-force30" goto set_force30_arg +goto set_force_end +:set_force30_arg + set DIRECTX_FORCE_MODEL=30 + goto set_force_end +:set_force_end + +if /i "%2" == "-game" goto set_mod_args +goto build_shaders + +REM **************** +REM USAGE +REM **************** +:usage +echo. +echo "usage: buildshaders [-game] [gameDir if -game was specified] [-source sourceDir]" +echo " gameDir is where gameinfo.txt is (where it will store the compiled shaders)." +echo " sourceDir is where the source code is (where it will find scripts and compilers)." +echo "ex : buildshaders myshaders" +echo "ex : buildshaders myshaders -game c:\steam\steamapps\sourcemods\mymod -source c:\mymod\src" +goto :end + +REM **************** +REM MOD ARGS - look for -game or the vproject environment variable +REM **************** +:set_mod_args + +if not exist "%SDKBINDIR%\shadercompile.exe" goto NoShaderCompile +set ChangeToDir=%SDKBINDIR% + +if /i "%4" NEQ "-source" goto NoSourceDirSpecified +set SrcDirBase=%~5 + +REM ** use the -game parameter to tell us where to put the files +set targetdir=%~3\shaders +set SDKArgs=-nompi -nop4 -game "%~3" + +if not exist "%~3\gameinfo.txt" goto InvalidGameDirectory +goto build_shaders + +REM **************** +REM ERRORS +REM **************** +:InvalidGameDirectory +echo - +echo Error: "%~3" is not a valid game directory. +echo (The -game directory must have a gameinfo.txt file) +echo - +goto end + +:NoSourceDirSpecified +echo ERROR: If you specify -game on the command line, you must specify -source. +goto usage +goto end + +:NoShaderCompile +echo - +echo - ERROR: shadercompile.exe doesn't exist in %SDKBINDIR% +echo - +goto end + +REM **************** +REM BUILD SHADERS +REM **************** +:build_shaders + +rem echo -------------------------------- +rem echo %inputbase% +rem echo -------------------------------- +REM make sure that target dirs exist +REM files will be built in these targets and copied to their final destination +if not exist %shaderDir% mkdir %shaderDir% +if not exist %shaderDir%\fxc mkdir %shaderDir%\fxc +if not exist %shaderDir%\vsh mkdir %shaderDir%\vsh +if not exist %shaderDir%\psh mkdir %shaderDir%\psh +REM Nuke some files that we will add to later. +if exist filelist.txt del /f /q filelist.txt +if exist filestocopy.txt del /f /q filestocopy.txt +if exist filelistgen.txt del /f /q filelistgen.txt +if exist inclist.txt del /f /q inclist.txt +if exist vcslist.txt del /f /q vcslist.txt + +REM **************** +REM Generate a makefile for the shader project +REM **************** +perl "%SrcDirBase%\devtools\bin\updateshaders.pl" -source "%SrcDirBase%" %inputbase% + + +REM **************** +REM Run the makefile, generating minimal work/build list for fxc files, go ahead and compile vsh and psh files. +REM **************** +rem nmake /S /C -f makefile.%inputbase% clean > clean.txt 2>&1 +echo Building inc files, asm vcs files, and VMPI worklist for %inputbase%... +nmake /S /C -f makefile.%inputbase% + +REM **************** +REM Copy the inc files to their target +REM **************** +if exist "inclist.txt" ( + echo Publishing shader inc files to target... + perl %SrcDirBase%\devtools\bin\copyshaderincfiles.pl inclist.txt +) + +REM **************** +REM Add the executables to the worklist. +REM **************** +if /i "%DIRECTX_SDK_VER%" == "pc09.00" ( + rem echo "Copy extra files for dx 9 std +) +if /i "%DIRECTX_SDK_VER%" == "pc09.30" ( + echo %SrcDirBase%\devtools\bin\d3dx9_33.dll >> filestocopy.txt +) + +echo %SrcDirBase%\%DIRECTX_SDK_BIN_DIR%\dx_proxy.dll >> filestocopy.txt + +echo %SDKBINDIR%\shadercompile.exe >> filestocopy.txt +echo %SDKBINDIR%\shadercompile_dll.dll >> filestocopy.txt +echo %SDKBINDIR%\vstdlib.dll >> filestocopy.txt +echo %SDKBINDIR%\tier0.dll >> filestocopy.txt + +REM **************** +REM Cull duplicate entries in work/build list +REM **************** +if exist filestocopy.txt type filestocopy.txt | perl "%SrcDirBase%\devtools\bin\uniqifylist.pl" > uniquefilestocopy.txt +if exist filelistgen.txt if not "%dynamic_shaders%" == "1" ( + echo Generating action list... + copy filelistgen.txt filelist.txt >nul +) + +REM **************** +REM Execute distributed process on work/build list +REM **************** + +set shader_path_cd=%cd% +if exist "filelist.txt" if exist "uniquefilestocopy.txt" if not "%dynamic_shaders%" == "1" ( + echo Running distributed shader compilation... + + cd /D %ChangeToDir% + echo %shadercompilecommand% %SDKArgs% -shaderpath "%shader_path_cd:/=\%" -allowdebug + %shadercompilecommand% %SDKArgs% -shaderpath "%shader_path_cd:/=\%" -allowdebug + cd /D %shader_path_cd% +) + +REM **************** +REM PC Shader copy +REM Publish the generated files to the output dir using XCOPY +REM This batch file may have been invoked standalone or slaved (master does final smart mirror copy) +REM **************** +:DoXCopy +if not "%dynamic_shaders%" == "1" ( +if not exist "%targetdir%" md "%targetdir%" +if not "%targetdir%"=="%shaderDir%" xcopy %shaderDir%\*.* "%targetdir%" /e /y +) +goto end + +REM **************** +REM END +REM **************** +:end + + +%TTEXE% -diff %tt_start% +echo. + diff --git a/sp/src/materialsystem/stdshaders/clean.bat b/sp/src/materialsystem/stdshaders/clean.bat new file mode 100644 index 00000000..eec63804 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/clean.bat @@ -0,0 +1,33 @@ +@echo off +setlocal + +if /i "%1" == "-game" goto CleanGameDir + +rem Clean out hl2 +if exist ..\..\..\game\hl2\shaders rd /s /q ..\..\..\game\hl2\shaders +goto CleanOtherStuff + +:CleanGameDir +set __GameDir=%~2 +if not exist "%__GameDir%\gameinfo.txt" goto MissingGameInfo +if exist "%__GameDir%\shaders" rd /s /q "%2\shaders" +goto CleanOtherStuff + +:CleanOtherStuff +if exist debug_dx9 rd /s /q debug_dx9 + +if exist fxctmp9 rd /s /q fxctmp9 +if exist vshtmp9 rd /s /q vshtmp9 +if exist pshtmp9 rd /s /q pshtmp9 +if exist fxctmp9_tmp rd /s /q fxctmp9_tmp +if exist vshtmp9_tmp rd /s /q vshtmp9_tmp +if exist pshtmp9_tmp rd /s /q pshtmp9_tmp +if exist shaders rd /s /q shaders +goto end + +:MissingGameInfo +echo Invalid -game parameter specified (no "%__GameDir%\gameinfo.txt" exists). +goto end + + +:end \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/cleantemps.bat b/sp/src/materialsystem/stdshaders/cleantemps.bat new file mode 100644 index 00000000..51478ee4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cleantemps.bat @@ -0,0 +1,12 @@ +@echo off +setlocal + +if exist fxctmp9_tmp rd /s /q fxctmp9_tmp +if exist vshtmp9_tmp rd /s /q vshtmp9_tmp +if exist pshtmp9_tmp rd /s /q pshtmp9_tmp + +if exist fxctmp9_360_tmp rd /s /q fxctmp9_360_tmp +if exist vshtmp9_360_tmp rd /s /q vshtmp9_360_tmp +if exist pshtmp9_360_tmp rd /s /q pshtmp9_360_tmp + +if exist shaders rd /s /q shaders diff --git a/sp/src/materialsystem/stdshaders/commandbuilder.h b/sp/src/materialsystem/stdshaders/commandbuilder.h new file mode 100644 index 00000000..13a68ede --- /dev/null +++ b/sp/src/materialsystem/stdshaders/commandbuilder.h @@ -0,0 +1,407 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// Utility class for building command buffers into memory +//===========================================================================// + +#ifndef COMMANDBUILDER_H +#define COMMANDBUILDER_H + +#ifndef COMMANDBUFFER_H +#include "shaderapi/commandbuffer.h" +#endif + +#include "BaseVSShader.h" +#include "shaderapi/ishaderapi.h" + +#ifdef _WIN32 +#pragma once +#endif + +extern ConVar my_mat_fullbright; + +template class CFixedCommandStorageBuffer +{ +public: + uint8 m_Data[N]; + + uint8 *m_pDataOut; +#ifdef DBGFLAG_ASSERT + size_t m_nNumBytesRemaining; +#endif + + FORCEINLINE CFixedCommandStorageBuffer( void ) + { + m_pDataOut = m_Data; +#ifdef DBGFLAG_ASSERT + m_nNumBytesRemaining = N; +#endif + + } + + FORCEINLINE void EnsureCapacity( size_t sz ) + { + Assert( m_nNumBytesRemaining >= sz ); + } + + template FORCEINLINE void Put( T const &nValue ) + { + EnsureCapacity( sizeof( T ) ); + *( reinterpret_cast( m_pDataOut ) ) = nValue; + m_pDataOut += sizeof( nValue ); +#ifdef DBGFLAG_ASSERT + m_nNumBytesRemaining -= sizeof( nValue ); +#endif + } + + FORCEINLINE void PutInt( int nValue ) + { + Put( nValue ); + } + + FORCEINLINE void PutFloat( float nValue ) + { + Put( nValue ); + } + + FORCEINLINE void PutPtr( void * pPtr ) + { + Put( pPtr ); + } + + FORCEINLINE void PutMemory( const void *pMemory, size_t nBytes ) + { + EnsureCapacity( nBytes ); + memcpy( m_pDataOut, pMemory, nBytes ); + m_pDataOut += nBytes; + } + + FORCEINLINE uint8 *Base( void ) + { + return m_Data; + } + + FORCEINLINE void Reset( void ) + { + m_pDataOut = m_Data; +#ifdef DBGFLAG_ASSERT + m_nNumBytesRemaining = N; +#endif + } + + FORCEINLINE size_t Size( void ) const + { + return m_pDataOut - m_Data; + } + +}; + +template class CCommandBufferBuilder +{ +public: + S m_Storage; + + FORCEINLINE void End( void ) + { + m_Storage.PutInt( CBCMD_END ); + } + + + FORCEINLINE IMaterialVar *Param( int nVar ) const + { + return CBaseShader::s_ppParams[nVar]; + } + + FORCEINLINE void SetPixelShaderConstants( int nFirstConstant, int nConstants ) + { + m_Storage.PutInt( CBCMD_SET_PIXEL_SHADER_FLOAT_CONST ); + m_Storage.PutInt( nFirstConstant ); + m_Storage.PutInt( nConstants ); + } + + FORCEINLINE void OutputConstantData( float const *pSrcData ) + { + m_Storage.PutFloat( pSrcData[0] ); + m_Storage.PutFloat( pSrcData[1] ); + m_Storage.PutFloat( pSrcData[2] ); + m_Storage.PutFloat( pSrcData[3] ); + } + + FORCEINLINE void OutputConstantData4( float flVal0, float flVal1, float flVal2, float flVal3 ) + { + m_Storage.PutFloat( flVal0 ); + m_Storage.PutFloat( flVal1 ); + m_Storage.PutFloat( flVal2 ); + m_Storage.PutFloat( flVal3 ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, float const *pSrcData, int nNumConstantsToSet ) + { + SetPixelShaderConstants( nFirstConstant, nNumConstantsToSet ); + m_Storage.PutMemory( pSrcData, 4 * sizeof( float ) * nNumConstantsToSet ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, int nVar ) + { + SetPixelShaderConstant( nFirstConstant, Param( nVar )->GetVecValue() ); + } + + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ) + { + float val[4]; + Param(constantVar)->GetVecValue( val, 3 ); + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + val[3] = 1.0; + SetPixelShaderConstant( pixelReg, val ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, float const *pSrcData ) + { + SetPixelShaderConstants( nFirstConstant, 1 ); + OutputConstantData( pSrcData ); + } + + FORCEINLINE void SetPixelShaderConstant4( int nFirstConstant, float flVal0, float flVal1, float flVal2, float flVal3 ) + { + SetPixelShaderConstants( nFirstConstant, 1 ); + OutputConstantData4( flVal0, flVal1, flVal2, flVal3 ); + } + + FORCEINLINE void SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ) + { + if ( constantVar != -1 ) + { + float val[3]; + Param(constantVar)->GetVecValue( val, 3); + SetPixelShaderConstant4( pixelReg, val[0], val[1], val[2], fWValue ); + } + } + + FORCEINLINE void SetVertexShaderConstant( int nFirstConstant, float const *pSrcData ) + { + m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + m_Storage.PutInt( nFirstConstant ); + m_Storage.PutInt( 1 ); + OutputConstantData( pSrcData ); + } + + FORCEINLINE void SetVertexShaderConstant( int nFirstConstant, float const *pSrcData, int nConsts ) + { + m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + m_Storage.PutInt( nFirstConstant ); + m_Storage.PutInt( nConsts ); + m_Storage.PutMemory( pSrcData, 4 * nConsts * sizeof( float ) ); + } + + + FORCEINLINE void SetVertexShaderConstant4( int nFirstConstant, float flVal0, float flVal1, float flVal2, float flVal3 ) + { + m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + m_Storage.PutInt( nFirstConstant ); + m_Storage.PutInt( 1 ); + m_Storage.PutFloat( flVal0 ); + m_Storage.PutFloat( flVal1 ); + m_Storage.PutFloat( flVal2 ); + m_Storage.PutFloat( flVal3 ); + } + + void SetVertexShaderTextureTransform( int vertexReg, int transformVar ) + { + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = Param( transformVar ); + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); + } + + + void SetVertexShaderTextureScaledTransform( int vertexReg, int transformVar, int scaleVar ) + { + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = Param( transformVar ); + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = Param( scaleVar ); + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); + } + + FORCEINLINE void SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar ) + { + if( g_pConfig->bShowSpecular && my_mat_fullbright.GetInt() != 2 ) + { + SetPixelShaderConstant( pixelReg, Param( tintVar)->GetVecValue() ); + } + else + { + SetPixelShaderConstant4( pixelReg, 0.0, 0.0, 0.0, 0.0 ); + } + } + + FORCEINLINE void SetEnvMapTintPixelShaderDynamicStateGammaToLinear( int pixelReg, int tintVar, float flAlphaValue = 1.0 ) + { + if( ( tintVar != -1 ) && g_pConfig->bShowSpecular && my_mat_fullbright.GetInt() != 2 ) + { + float color[4]; + color[3] = flAlphaValue; + Param( tintVar)->GetLinearVecValue( color, 3 ); + SetPixelShaderConstant( pixelReg, color ); + } + else + { + SetPixelShaderConstant4( pixelReg, 0.0, 0.0, 0.0, flAlphaValue ); + } + } + + FORCEINLINE void StoreEyePosInPixelShaderConstant( int nConst ) + { + m_Storage.PutInt( CBCMD_STORE_EYE_POS_IN_PSCONST ); + m_Storage.PutInt( nConst ); + } + + FORCEINLINE void CommitPixelShaderLighting( int nConst ) + { + m_Storage.PutInt( CBCMD_COMMITPIXELSHADERLIGHTING ); + m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetPixelShaderStateAmbientLightCube( int nConst ) + { + m_Storage.PutInt( CBCMD_SETPIXELSHADERSTATEAMBIENTLIGHTCUBE ); + m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetAmbientCubeDynamicStateVertexShader( void ) + { + m_Storage.PutInt( CBCMD_SETAMBIENTCUBEDYNAMICSTATEVERTEXSHADER ); + } + + FORCEINLINE void SetPixelShaderFogParams( int nReg ) + { + m_Storage.PutInt( CBCMD_SETPIXELSHADERFOGPARAMS ); + m_Storage.PutInt( nReg ); + } + + FORCEINLINE void BindStandardTexture( Sampler_t nSampler, StandardTextureId_t nTextureId ) + { + m_Storage.PutInt( CBCMD_BIND_STANDARD_TEXTURE ); + m_Storage.PutInt( nSampler ); + m_Storage.PutInt( nTextureId ); + } + + + FORCEINLINE void BindTexture( Sampler_t nSampler, ShaderAPITextureHandle_t hTexture ) + { + Assert( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE ); + if ( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE ) + { + m_Storage.PutInt( CBCMD_BIND_SHADERAPI_TEXTURE_HANDLE ); + m_Storage.PutInt( nSampler ); + m_Storage.PutInt( hTexture ); + } + } + + FORCEINLINE void BindTexture( CBaseVSShader *pShader, Sampler_t nSampler, int nTextureVar, int nFrameVar ) + { + ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar ); + BindTexture( nSampler, hTexture ); + } + + FORCEINLINE void BindMultiTexture( CBaseVSShader *pShader, Sampler_t nSampler1, Sampler_t nSampler2, int nTextureVar, int nFrameVar ) + { + ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar, 0 ); + BindTexture( nSampler1, hTexture ); + hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar, 1 ); + BindTexture( nSampler2, hTexture ); + } + + FORCEINLINE void SetPixelShaderIndex( int nIndex ) + { + m_Storage.PutInt( CBCMD_SET_PSHINDEX ); + m_Storage.PutInt( nIndex ); + } + + FORCEINLINE void SetVertexShaderIndex( int nIndex ) + { + m_Storage.PutInt( CBCMD_SET_VSHINDEX ); + m_Storage.PutInt( nIndex ); + } + + FORCEINLINE void SetDepthFeatheringPixelShaderConstant( int iConstant, float fDepthBlendScale ) + { + m_Storage.PutInt( CBCMD_SET_DEPTH_FEATHERING_CONST ); + m_Storage.PutInt( iConstant ); + m_Storage.PutFloat( fDepthBlendScale ); + } + + FORCEINLINE void Goto( uint8 *pCmdBuf ) + { + m_Storage.PutInt( CBCMD_JUMP ); + m_Storage.PutPtr( pCmdBuf ); + } + + FORCEINLINE void Call( uint8 *pCmdBuf ) + { + m_Storage.PutInt( CBCMD_JSR ); + m_Storage.PutPtr( pCmdBuf ); + } + + FORCEINLINE void Reset( void ) + { + m_Storage.Reset(); + } + + FORCEINLINE size_t Size( void ) const + { + return m_Storage.Size(); + } + + FORCEINLINE uint8 *Base( void ) + { + return m_Storage.Base(); + } + + + +}; + + +#endif // commandbuilder_h diff --git a/sp/src/materialsystem/stdshaders/common_flashlight_fxc.h b/sp/src/materialsystem/stdshaders/common_flashlight_fxc.h new file mode 100644 index 00000000..f9256a59 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_flashlight_fxc.h @@ -0,0 +1,821 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Common pixel shader code specific to flashlights +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_FLASHLIGHT_FXC_H_ +#define COMMON_FLASHLIGHT_FXC_H_ + +#include "common_ps_fxc.h" + + +// JasonM - TODO: remove this simpleton version +float DoShadow( sampler DepthSampler, float4 texCoord ) +{ + const float g_flShadowBias = 0.0005f; + float2 uoffset = float2( 0.5f/512.f, 0.0f ); + float2 voffset = float2( 0.0f, 0.5f/512.f ); + float3 projTexCoord = texCoord.xyz / texCoord.w; + float4 flashlightDepth = float4( tex2D( DepthSampler, projTexCoord + uoffset + voffset ).x, + tex2D( DepthSampler, projTexCoord + uoffset - voffset ).x, + tex2D( DepthSampler, projTexCoord - uoffset + voffset ).x, + tex2D( DepthSampler, projTexCoord - uoffset - voffset ).x ); + +# if ( defined( REVERSE_DEPTH_ON_X360 ) ) + { + flashlightDepth = 1.0f - flashlightDepth; + } +# endif + + float shadowed = 0.0f; + float z = texCoord.z/texCoord.w; + float4 dz = float4(z,z,z,z) - (flashlightDepth + float4( g_flShadowBias, g_flShadowBias, g_flShadowBias, g_flShadowBias)); + float4 shadow = float4(0.25f,0.25f,0.25f,0.25f); + + if( dz.x <= 0.0f ) + shadowed += shadow.x; + if( dz.y <= 0.0f ) + shadowed += shadow.y; + if( dz.z <= 0.0f ) + shadowed += shadow.z; + if( dz.w <= 0.0f ) + shadowed += shadow.w; + + return shadowed; +} + + +float DoShadowNvidiaRAWZOneTap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float fDepth = dot(tex2D(DepthSampler, shadowMapCenter).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + + return fDepth > objDepth; +} + + +float DoShadowNvidiaRAWZ( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fE = 1.0f / 512.0f; // Epsilon + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vDepths; + vDepths.x = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.y = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.z = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.w = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + + return dot(vDepths > objDepth.xxxx, float4(0.25, 0.25, 0.25, 0.25)); +} + + +float DoShadowNvidiaCheap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fTexelEpsilon = 1.0f / 1024.0f; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vTaps; + vTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x; + + return dot(vTaps, float4(0.25, 0.25, 0.25, 0.25)); +} + +float DoShadowNvidiaPCF3x3Box( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fTexelEpsilon = 1.0f / 1024.0f; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vOneTaps; + vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x; + float flOneTaps = dot( vOneTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f)); + + float4 vTwoTaps; + vTwoTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, 0 ), objDepth, 1 ) ).x; + vTwoTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, 0 ), objDepth, 1 ) ).x; + vTwoTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x; + vTwoTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x; + float flTwoTaps = dot( vTwoTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f)); + + float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (1.0f / 9.0f); + + // Sum all 9 Taps + return flOneTaps + flTwoTaps + flCenterTap; +} + + +// +// 1 4 7 4 1 +// 4 20 33 20 4 +// 7 33 55 33 7 +// 4 20 33 20 4 +// 1 4 7 4 1 +// +float DoShadowNvidiaPCF5x5Gaussian( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fEpsilon = 1.0f / 512.0f; + float fTwoEpsilon = 2.0f * fEpsilon; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vOneTaps; + vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + float flOneTaps = dot( vOneTaps, float4(1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f)); + + float4 vSevenTaps; + vSevenTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, 0 ), objDepth, 1 ) ).x; + vSevenTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, 0 ), objDepth, 1 ) ).x; + vSevenTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x; + vSevenTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x; + float flSevenTaps = dot( vSevenTaps, float4( 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f ) ); + + float4 vFourTapsA, vFourTapsB; + vFourTapsA.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + float flFourTapsA = dot( vFourTapsA, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) ); + float flFourTapsB = dot( vFourTapsB, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) ); + + float4 v20Taps; + v20Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fEpsilon ), objDepth, 1 ) ).x; + v20Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fEpsilon ), objDepth, 1 ) ).x; + v20Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + v20Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + float fl20Taps = dot( v20Taps, float4(20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f)); + + float4 v33Taps; + v33Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, 0 ), objDepth, 1 ) ).x; + v33Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, 0 ), objDepth, 1 ) ).x; + v33Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x; + v33Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x; + float fl33Taps = dot( v33Taps, float4(33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f)); + + float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (55.0f / 331.0f); + + // Sum all 25 Taps + return flOneTaps + flSevenTaps + +flFourTapsA + flFourTapsB + fl20Taps + fl33Taps + flCenterTap; +} + + +float DoShadowATICheap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float2 shadowMapCenter = shadowMapPos.xy/shadowMapPos.w; + float objDepth = shadowMapPos.z / shadowMapPos.w; + float fSampleDepth = tex2D( DepthSampler, shadowMapCenter ).x; + + objDepth = min( objDepth, 0.99999 ); //HACKHACK: On 360, surfaces at or past the far flashlight plane have an abrupt cutoff. This is temp until a smooth falloff is implemented + + return fSampleDepth > objDepth; +} + + +// Poisson disc, randomly rotated at different UVs +float DoShadowPoisson16Sample( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks, bool bNvidiaHardwarePCF, bool bFetch4 ) +{ + float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), + float2( 0.8806f, 0.3430f ), + float2( -0.0041f, -0.6197f ), + float2( 0.0472f, 0.4964f ), + float2( -0.3730f, 0.0874f ), + float2( -0.9217f, -0.3177f ), + float2( -0.6289f, 0.7388f ), + float2( 0.5744f, -0.7741f ) }; + + float flScaleOverMapSize = vShadowTweaks.x * 2; // Tweak parameters to shader + float2 vNoiseOffset = vShadowTweaks.zw; + float4 vLightDepths = 0, accum = 0.0f; + float2 rotOffset = 0; + + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + + // 2D Rotation Matrix setup + float3 RMatTop = 0, RMatBottom = 0; +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5) + vNoiseOffset) * 2.0 - 1.0; + RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple +#endif + + RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution + RMatBottom *= flScaleOverMapSize; + + RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below + RMatBottom.z = shadowMapCenter.y; + + float fResult = 0.0f; + + if ( bNvidiaHardwarePCF ) + { + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z; + vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z; + vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z; + vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z; + vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z; + vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z; + vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z; + vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z; + vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + fResult = dot( vLightDepths, float4( 0.25, 0.25, 0.25, 0.25) ); + } + else if ( bFetch4 ) + { +/* + +TODO: Fix this contact hardening stuff + + float flNumCloserSamples = 1; + float flAccumulatedCloserSamples = objDepth; + float4 vBlockerDepths; + + // First, search for blockers + for( int j=0; j<8; j++ ) + { + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[j].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[j].xy) + RMatBottom.z; + vBlockerDepths = tex2D( DepthSampler, rotOffset.xy ); + + // Which samples are closer than the pixel we're rendering? + float4 vCloserSamples = (vBlockerDepths < objDepth.xxxx ); // Binary comparison results + flNumCloserSamples += dot( vCloserSamples, float4(1, 1, 1, 1) ); // How many samples are closer than receiver? + flAccumulatedCloserSamples += dot (vCloserSamples, vBlockerDepths ); // Total depths from samples closer than receiver + } + + float flBlockerDepth = flAccumulatedCloserSamples / flNumCloserSamples; + float flContactHardeningScale = (objDepth - flBlockerDepth) / flBlockerDepth; + + // Scale the kernel + RMatTop.xy *= flContactHardeningScale; + RMatBottom.xy *= flContactHardeningScale; +*/ + + for( int i=0; i<8; i++ ) + { + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[i].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[i].xy) + RMatBottom.z; + vLightDepths = tex2D( DepthSampler, rotOffset.xy ); + accum += (vLightDepths > objDepth.xxxx); + } + + fResult = dot( accum, float4( 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f) ); + } + else // ATI vanilla hardware shadow mapping + { + for( int i=0; i<2; i++ ) + { + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+0].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+0].xy) + RMatBottom.z; + vLightDepths.x = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+1].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+1].xy) + RMatBottom.z; + vLightDepths.y = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+2].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+2].xy) + RMatBottom.z; + vLightDepths.z = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+3].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+3].xy) + RMatBottom.z; + vLightDepths.w = tex2D( DepthSampler, rotOffset.xy ).x; + + accum += (vLightDepths > objDepth.xxxx); + } + + fResult = dot( accum, float4( 0.125, 0.125, 0.125, 0.125) ); + } + + return fResult; +} + +#if defined( _X360 ) + +// Poisson disc, randomly rotated at different UVs +float DoShadow360Simple( sampler DepthSampler, const float3 vProjCoords ) +{ + float fLOD; + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + +#if defined( REVERSE_DEPTH_ON_X360 ) + objDepth = 1.0f - objDepth; +#endif + + float4 vSampledDepths, vWeights; + + asm { + getCompTexLOD2D fLOD.x, shadowMapCenter.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + getWeights2D vWeights, shadowMapCenter.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true + }; + + vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y ); + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, vWeights ); +} + + +float Do360PCFFetch( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepths, vWeights; + + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + getWeights2D vWeights, tc.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true + }; + + vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y ); + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, vWeights ); +} + + + +float Do360NearestFetch( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepth; + + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepth.x___, tc, DepthSampler, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + return (vSampledDepth.x < objDepth.x); +#else + return (vSampledDepth.x > objDepth.x); +#endif + +} + + +float AmountShadowed_8Tap_360( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepthsA, vSampledDepthsB; + + // Optimal 8 rooks pattern to get an idea about whether we're at a penumbra or not + // From [Kallio07] "Scanline Edge-Flag Algorithm for Antialiasing" + // + // +---+---+---+---+---+---+---+---+ + // | | | | | | o | | | + // +---+---+---+---+---+---+---+---+ + // | o | | | | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | o | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | | | o | | + // +---+---+---+---+---+---+---+---+ + // | | o | | | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | o | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | | | | o | + // +---+---+---+---+---+---+---+---+ + // | | | o | | | | | | + // +---+---+---+---+---+---+---+---+ + // + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepthsA.x___, tc, DepthSampler, OffsetX = -2.0, OffsetY = -1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA._x__, tc, DepthSampler, OffsetX = -1.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA.__x_, tc, DepthSampler, OffsetX = -1.0, OffsetY = 2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA.___x, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + tfetch2D vSampledDepthsB.x___, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB._x__, tc, DepthSampler, OffsetX = 1.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB.__x_, tc, DepthSampler, OffsetX = 1.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB.___x, tc, DepthSampler, OffsetX = 2.0, OffsetY = 1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompareA = (vSampledDepthsA < objDepth.xxxx); + float4 vCompareB = (vSampledDepthsB < objDepth.xxxx); +#else + float4 vCompareA = (vSampledDepthsA > objDepth.xxxx); + float4 vCompareB = (vSampledDepthsB > objDepth.xxxx); +#endif + + return dot( vCompareA, float4(0.125,0.125,0.125,0.125) ) + dot( vCompareB, float4(0.125,0.125,0.125,0.125) ); +} + + +float AmountShadowed_4Tap_360( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepths; + + // Rotated grid pattern to get an idea about whether we're at a penumbra or not + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -1.0, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 1.0, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, float4(0.25,0.25,0.25,0.25) ); +} + +// Poisson disc, randomly rotated at different UVs +float DoShadowPoisson360( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks ) +{ + float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ), + float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ), + float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ), + float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) }; + + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + +#if defined( REVERSE_DEPTH_ON_X360 ) + objDepth = 1.0f - objDepth; +#endif + + float fAmountShadowed = AmountShadowed_4Tap_360( DepthSampler, shadowMapCenter, objDepth ); + + if ( fAmountShadowed >= 1.0f ) // Fully in light + { + return 1.0f; + } + else // Do the expensive filtering since we're at least partially shadowed + { + float flScaleOverMapSize = 1.7f / 512.0f; // Tweak parameters to shader + + // 2D Rotation Matrix setup + float3 RMatTop = 0, RMatBottom = 0; +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5)) * 2.0 - 1.0; + RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple +#endif + + RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution + RMatBottom *= flScaleOverMapSize; + RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below + RMatBottom.z = shadowMapCenter.y; + float2 rotOffset = float2(0,0); + float4 vAccum = 0; + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z; + vAccum.x = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z; + vAccum.y = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z; + vAccum.z = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z; + vAccum.w = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z; + vAccum.x += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z; + vAccum.y += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z; + vAccum.z += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z; + rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z; + vAccum.w += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + return dot( vAccum, float4( 0.25, 0.25, 0.25, 0.25) ); + } +} + +#endif // _X360 + + +float DoFlashlightShadow( sampler DepthSampler, sampler RandomRotationSampler, float3 vProjCoords, float2 vScreenPos, int nShadowLevel, float4 vShadowTweaks, bool bAllowHighQuality ) +{ + float flShadow = 1.0f; + +#if !defined( _X360 ) //PC + if( nShadowLevel == NVIDIA_PCF_POISSON ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, true, false ); + else if( nShadowLevel == ATI_NOPCF ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, false ); + else if( nShadowLevel == ATI_NO_PCF_FETCH4 ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, true ); + + return flShadow; +#else + + // Compile-time switch for shaders which allow high quality modes on 360 + if ( bAllowHighQuality ) + { + // Static control flow switch for shadow quality. Some non-interactive sequences use the high quality path + if ( g_bHighQualityShadows ) + { + flShadow = DoShadowPoisson360( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks ); + } + else + { + flShadow = DoShadow360Simple( DepthSampler, vProjCoords ); + } + } + else + { + flShadow = DoShadow360Simple( DepthSampler, vProjCoords ); + } + + return flShadow; + +#endif +} + +float3 SpecularLight( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent, + const float3 vEyeDir, const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel ) +{ + float3 result = float3(0.0f, 0.0f, 0.0f); + + //float3 vReflect = reflect( -vEyeDir, vWorldNormal ); + float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal + float3 vSpecular = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?) + vSpecular = pow( vSpecular.x, fSpecularExponent ); // Raise to specular power + + // Optionally warp as function of scalar specular and fresnel + if ( bDoSpecularWarp ) + vSpecular *= tex2D( specularWarpSampler, float2(vSpecular.x, fFresnel) ); // Sample at { (L.R)^k, fresnel } + + return vSpecular; +} + +void DoSpecularFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, + float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, sampler RandomRotationSampler, + int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, const float2 vScreenPos, const float fSpecularExponent, const float3 vEyeDir, + const bool bDoSpecularWarp, sampler specularWarpSampler, float fFresnel, float4 vShadowTweaks, + + // Outputs of this shader...separate shadowed diffuse and specular from the flashlight + out float3 diffuseLighting, out float3 specularLighting ) +{ + float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w; + float3 flashlightColor = float3(1,1,1); + +#if ( defined( _X360 ) ) + + float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f ); + float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f ); + + [branch] + if ( dot(ltz + gto, float3(1,1,1)) > 0 ) + { + clip(-1); + diffuseLighting = specularLighting = float3(0,0,0); + return; + } + else + { + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); + + [branch] + if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 ) + { + clip(-1); + diffuseLighting = specularLighting = float3(0,0,0); + return; + } + } +#else + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); +#endif + + +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + flashlightColor *= cFlashlightColor.xyz; // Flashlight color +#endif + + float3 delta = flashlightPos - worldPos; + float3 L = normalize( delta ); + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + + float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + + // Attenuation for light and to fade out shadow over distance + float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + + // Shadowing and coloring terms +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + if ( bDoShadows ) + { + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality ); + float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation + flashlightColor *= flShadow; // Shadow term + } +#endif + + diffuseLighting = fAtten; +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) + flFlashlightNoLambertValue ); // Lambertian term +#else + diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) ); // Lambertian (not Half-Lambert) term +#endif + diffuseLighting *= flashlightColor; + diffuseLighting *= endFalloffFactor; + + // Specular term (masked by diffuse) + specularLighting = diffuseLighting * SpecularLight ( worldNormal, L, fSpecularExponent, vEyeDir, bDoSpecularWarp, specularWarpSampler, fFresnel ); +} + +// Diffuse only version +float3 DoFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, + float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, + sampler RandomRotationSampler, int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, + const float2 vScreenPos, bool bClip, float4 vShadowTweaks = float4(3/1024.0f, 0.0005f, 0.0f, 0.0f), bool bHasNormal = true ) +{ + float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w; + float3 flashlightColor = float3(1,1,1); + +#if ( defined( _X360 ) ) + + float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f ); + float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f ); + + [branch] + if ( dot(ltz + gto, float3(1,1,1)) > 0 ) + { + if ( bClip ) + { + clip(-1); + } + return float3(0,0,0); + } + else + { + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); + + [branch] + if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 ) + { + if ( bClip ) + { + clip(-1); + } + return float3(0,0,0); + } + } +#else + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); +#endif + +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + flashlightColor *= cFlashlightColor.xyz; // Flashlight color +#endif + + float3 delta = flashlightPos - worldPos; + float3 L = normalize( delta ); + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + + float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + + // Attenuation for light and to fade out shadow over distance + float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + + // Shadowing and coloring terms +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + if ( bDoShadows ) + { + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality ); + float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation + flashlightColor *= flShadow; // Shadow term + } +#endif + + float3 diffuseLighting = fAtten; + + float flLDotWorldNormal; + if ( bHasNormal ) + { + flLDotWorldNormal = dot( L.xyz, worldNormal.xyz ); + } + else + { + flLDotWorldNormal = 1.0f; + } + +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + diffuseLighting *= saturate( flLDotWorldNormal + flFlashlightNoLambertValue ); // Lambertian term +#else + diffuseLighting *= saturate( flLDotWorldNormal ); // Lambertian (not Half-Lambert) term +#endif + + diffuseLighting *= flashlightColor; + diffuseLighting *= endFalloffFactor; + + return diffuseLighting; +} + +#endif //#ifndef COMMON_FLASHLIGHT_FXC_H_ diff --git a/sp/src/materialsystem/stdshaders/common_fxc.h b/sp/src/materialsystem/stdshaders/common_fxc.h new file mode 100644 index 00000000..b81c9a46 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_fxc.h @@ -0,0 +1,326 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_FXC_H_ +#define COMMON_FXC_H_ + +#include "common_pragmas.h" +#include "common_hlsl_cpp_consts.h" + +#ifdef NV3X +# define HALF half +# define HALF2 half2 +# define HALF3 half3 +# define HALF4 half4 +# define HALF3x3 half3x3 +# define HALF3x4 half3x4 +# define HALF4x3 half4x3 +# define HALF_CONSTANT( _constant ) ((HALF)_constant) +#else +# define HALF float +# define HALF2 float2 +# define HALF3 float3 +# define HALF4 float4 +# define HALF3x3 float3x3 +# define HALF3x4 float3x4 +# define HALF4x3 float4x3 +# define HALF_CONSTANT( _constant ) _constant +#endif + +// This is where all common code for both vertex and pixel shaders. +#define OO_SQRT_3 0.57735025882720947f +static const HALF3 bumpBasis[3] = { + HALF3( 0.81649661064147949f, 0.0f, OO_SQRT_3 ), + HALF3( -0.40824833512306213f, 0.70710676908493042f, OO_SQRT_3 ), + HALF3( -0.40824821591377258f, -0.7071068286895752f, OO_SQRT_3 ) +}; +static const HALF3 bumpBasisTranspose[3] = { + HALF3( 0.81649661064147949f, -0.40824833512306213f, -0.40824833512306213f ), + HALF3( 0.0f, 0.70710676908493042f, -0.7071068286895752f ), + HALF3( OO_SQRT_3, OO_SQRT_3, OO_SQRT_3 ) +}; + +#if defined( _X360 ) +#define REVERSE_DEPTH_ON_X360 //uncomment to use D3DFMT_D24FS8 with an inverted depth viewport for better performance. Keep this in sync with the same named #define in public/shaderapi/shareddefs.h +//Note that the reversal happens in the viewport. So ONLY reading back from a depth texture should be affected. Projected math is unaffected. +#endif + +HALF3 CalcReflectionVectorNormalized( HALF3 normal, HALF3 eyeVector ) +{ + // FIXME: might be better of normalizing with a normalizing cube map and + // get rid of the dot( normal, normal ) + // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v + return 2.0 * ( dot( normal, eyeVector ) / dot( normal, normal ) ) * normal - eyeVector; +} + +HALF3 CalcReflectionVectorUnnormalized( HALF3 normal, HALF3 eyeVector ) +{ + // FIXME: might be better of normalizing with a normalizing cube map and + // get rid of the dot( normal, normal ) + // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v + // multiply all values through by N.N. uniformly scaling reflection vector won't affect result + // since it is used in a cubemap lookup + return (2.0*(dot( normal, eyeVector ))*normal) - (dot( normal, normal )*eyeVector); +} + +float3 HuePreservingColorClamp( float3 c ) +{ + // Get the max of all of the color components and a specified maximum amount + float maximum = max( max( c.x, c.y ), max( c.z, 1.0f ) ); + + return (c / maximum); +} + +HALF3 HuePreservingColorClamp( HALF3 c, HALF maxVal ) +{ + // Get the max of all of the color components and a specified maximum amount + float maximum = max( max( c.x, c.y ), max( c.z, maxVal ) ); + return (c * ( maxVal / maximum ) ); +} + +#if (AA_CLAMP==1) +HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) +{ + HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99; + result += Lightmap3Coord; + return result; +} + +void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord, + out HALF2 bumpCoord1, + out HALF2 bumpCoord2, + out HALF2 bumpCoord3 ) +{ + HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99; + result += Lightmap3Coord; + bumpCoord1 = result + HALF2(Lightmap1and2Coord.z, 0); + bumpCoord2 = result + 2*HALF2(Lightmap1and2Coord.z, 0); + bumpCoord3 = result + 3*HALF2(Lightmap1and2Coord.z, 0); +} +#else +HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) +{ + return Lightmap1and2Coord.xy; +} + +void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord, + out HALF2 bumpCoord1, + out HALF2 bumpCoord2, + out HALF2 bumpCoord3 ) +{ + bumpCoord1 = Lightmap1and2Coord.xy; + bumpCoord2 = Lightmap1and2Coord.wz; // reversed order!!! + bumpCoord3 = Lightmap3Coord.xy; +} +#endif + +// Versions of matrix multiply functions which force HLSL compiler to explictly use DOTs, +// not giving it the option of using MAD expansion. In a perfect world, the compiler would +// always pick the best strategy, and these shouldn't be needed.. but.. well.. umm.. +// +// lorenmcq + +float3 mul3x3(float3 v, float3x3 m) +{ +#if !defined( _X360 ) + return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2])); +#else + // xbox360 fxc.exe (new back end) borks with transposes, generates bad code + return mul( v, m ); +#endif +} + +float3 mul4x3(float4 v, float4x3 m) +{ +#if !defined( _X360 ) + return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2])); +#else + // xbox360 fxc.exe (new back end) borks with transposes, generates bad code + return mul( v, m ); +#endif +} + +float3 DecompressHDR( float4 input ) +{ + return input.rgb * input.a * MAX_HDR_OVERBRIGHT; +} + +float4 CompressHDR( float3 input ) +{ + // FIXME: want to use min so that we clamp to white, but what happens if we + // have an albedo component that's less than 1/MAX_HDR_OVERBRIGHT? + // float fMax = max( max( color.r, color.g ), color.b ); + float4 output; + float fMax = min( min( input.r, input.g ), input.b ); + if( fMax > 1.0f ) + { + float oofMax = 1.0f / fMax; + output.rgb = oofMax * input.rgb; + output.a = min( fMax / MAX_HDR_OVERBRIGHT, 1.0f ); + } + else + { + output.rgb = input.rgb; + output.a = 0.0f; + } + return output; +} + + +float3 LinearToGamma( const float3 f3linear ) +{ + return pow( f3linear, 1.0f / 2.2f ); +} + +float4 LinearToGamma( const float4 f4linear ) +{ + return float4( pow( f4linear.xyz, 1.0f / 2.2f ), f4linear.w ); +} + +float LinearToGamma( const float f1linear ) +{ + return pow( f1linear, 1.0f / 2.2f ); +} + +float3 GammaToLinear( const float3 gamma ) +{ + return pow( gamma, 2.2f ); +} + +float4 GammaToLinear( const float4 gamma ) +{ + return float4( pow( gamma.xyz, 2.2f ), gamma.w ); +} + +float GammaToLinear( const float gamma ) +{ + return pow( gamma, 2.2f ); +} + +// These two functions use the actual sRGB math +float SrgbGammaToLinear( float flSrgbGammaValue ) +{ + float x = saturate( flSrgbGammaValue ); + return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) ); +} + +float SrgbLinearToGamma( float flLinearValue ) +{ + float x = saturate( flLinearValue ); + return ( x <= 0.0031308f ) ? ( x * 12.92f ) : ( 1.055f * pow( x, ( 1.0f / 2.4f ) ) ) - 0.055f; +} + +// These twofunctions use the XBox 360's exact piecewise linear algorithm +float X360GammaToLinear( float fl360GammaValue ) +{ + float flLinearValue; + + fl360GammaValue = saturate( fl360GammaValue ); + if ( fl360GammaValue < ( 96.0f / 255.0f ) ) + { + if ( fl360GammaValue < ( 64.0f / 255.0f ) ) + { + flLinearValue = fl360GammaValue * 255.0f; + } + else + { + flLinearValue = fl360GammaValue * ( 255.0f * 2.0f ) - 64.0f; + flLinearValue += floor( flLinearValue * ( 1.0f / 512.0f ) ); + } + } + else + { + if( fl360GammaValue < ( 192.0f / 255.0f ) ) + { + flLinearValue = fl360GammaValue * ( 255.0f * 4.0f ) - 256.0f; + flLinearValue += floor( flLinearValue * ( 1.0f / 256.0f ) ); + } + else + { + flLinearValue = fl360GammaValue * ( 255.0f * 8.0f ) - 1024.0f; + flLinearValue += floor( flLinearValue * ( 1.0f / 128.0f ) ); + } + } + + flLinearValue *= 1.0f / 1023.0f; + + flLinearValue = saturate( flLinearValue ); + return flLinearValue; +} + +float X360LinearToGamma( float flLinearValue ) +{ + float fl360GammaValue; + + flLinearValue = saturate( flLinearValue ); + if ( flLinearValue < ( 128.0f / 1023.0f ) ) + { + if ( flLinearValue < ( 64.0f / 1023.0f ) ) + { + fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) ); + } + else + { + fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f ); + } + } + else + { + if ( flLinearValue < ( 512.0f / 1023.0f ) ) + { + fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f ); + } + else + { + fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016 + if ( fl360GammaValue > 1.0f ) + { + fl360GammaValue = 1.0f; + } + } + } + + fl360GammaValue = saturate( fl360GammaValue ); + return fl360GammaValue; +} + +float SrgbGammaTo360Gamma( float flSrgbGammaValue ) +{ + float flLinearValue = SrgbGammaToLinear( flSrgbGammaValue ); + float fl360GammaValue = X360LinearToGamma( flLinearValue ); + return fl360GammaValue; +} + +float3 Vec3WorldToTangent( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + float3 vTangentVector; + vTangentVector.x = dot( iWorldVector.xyz, iWorldTangent.xyz ); + vTangentVector.y = dot( iWorldVector.xyz, iWorldBinormal.xyz ); + vTangentVector.z = dot( iWorldVector.xyz, iWorldNormal.xyz ); + return vTangentVector.xyz; // Return without normalizing +} + +float3 Vec3WorldToTangentNormalized( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + return normalize( Vec3WorldToTangent( iWorldVector, iWorldNormal, iWorldTangent, iWorldBinormal ) ); +} + +float3 Vec3TangentToWorld( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + float3 vWorldVector; + vWorldVector.xyz = iTangentVector.x * iWorldTangent.xyz; + vWorldVector.xyz += iTangentVector.y * iWorldBinormal.xyz; + vWorldVector.xyz += iTangentVector.z * iWorldNormal.xyz; + return vWorldVector.xyz; // Return without normalizing +} + +float3 Vec3TangentToWorldNormalized( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + return normalize( Vec3TangentToWorld( iTangentVector, iWorldNormal, iWorldTangent, iWorldBinormal ) ); +} + +#endif //#ifndef COMMON_FXC_H_ diff --git a/sp/src/materialsystem/stdshaders/common_fxc2.h b/sp/src/materialsystem/stdshaders/common_fxc2.h new file mode 100644 index 00000000..7ee8b48c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_fxc2.h @@ -0,0 +1,19 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_FXC2_H_ +#define COMMON_FXC2_H_ + +// This file is here so you can add new utility functions without +// changing common_fxc.h and causing a recompile of the entire universe. + +float LinearToMonochrome ( float3 r ) +{ + return dot( r, float3( 0.299f, 0.587f, 0.114f ) ); +} + +#endif //#ifndef COMMON_FXC2_H_ diff --git a/sp/src/materialsystem/stdshaders/common_hlsl_cpp_consts.h b/sp/src/materialsystem/stdshaders/common_hlsl_cpp_consts.h new file mode 100644 index 00000000..523feee4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_hlsl_cpp_consts.h @@ -0,0 +1,27 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_HLSL_CONSTS_H_ +#define COMMON_HLSL_CONSTS_H_ + +#ifdef NV3X + #define PSHADER_VECT_SCALE 20.0 + #define VSHADER_VECT_SCALE (1.0 / (PSHADER_VECT_SCALE) ) +#else + #define PSHADER_VECT_SCALE 1.0 + #define VSHADER_VECT_SCALE 1.0 +#endif + +// GR - HDR luminance maps to 0..n range +// IMPORTANT: Keep the same value as in materialsystem_global.h +// HDRFIXME: Make this a pixel shader constant? +#define MAX_HDR_OVERBRIGHT 16.0f + +#define LINEAR_FOG_COLOR 29 +#define TONE_MAPPING_SCALE_PSH_CONSTANT 30 + +#endif //#ifndef COMMON_HLSL_CONSTS_H_ diff --git a/sp/src/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h b/sp/src/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h new file mode 100644 index 00000000..e82bdf65 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h @@ -0,0 +1,202 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + + +#if defined( _X360 ) + +void GetBaseTextureAndNormal( sampler base, sampler base2, sampler bump, bool bBase2, bool bBump, float3 coords, float3 vWeights, + out float4 vResultBase, out float4 vResultBase2, out float4 vResultBump ) +{ + vResultBase = 0; + vResultBase2 = 0; + vResultBump = 0; + + if ( !bBump ) + { + vResultBump = float4(0, 0, 1, 1); + } + +#if SEAMLESS + + vWeights = max( vWeights - 0.3, 0 ); + + vWeights *= 1.0f / dot( vWeights, float3(1,1,1) ); + + [branch] + if (vWeights.x > 0) + { + vResultBase += vWeights.x * tex2D( base, coords.zy ); + + if ( bBase2 ) + { + vResultBase2 += vWeights.x * tex2D( base2, coords.zy ); + } + + if ( bBump ) + { + vResultBump += vWeights.x * tex2D( bump, coords.zy ); + } + } + + [branch] + if (vWeights.y > 0) + { + vResultBase += vWeights.y * tex2D( base, coords.xz ); + + if ( bBase2 ) + { + vResultBase2 += vWeights.y * tex2D( base2, coords.xz ); + } + if ( bBump ) + { + vResultBump += vWeights.y * tex2D( bump, coords.xz ); + } + } + + [branch] + if (vWeights.z > 0) + { + vResultBase += vWeights.z * tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.z * tex2D( base2, coords.xy ); + } + + if ( bBump ) + { + vResultBump += vWeights.z * tex2D( bump, coords.xy ); + } + } + +#else // not seamless + + vResultBase = tex2D( base, coords.xy ); + + if ( bBase2 ) + { + vResultBase2 = tex2D( base2, coords.xy ); + } + + if ( bBump ) + { + vResultBump = tex2D( bump, coords.xy ); + } + +#endif + + +} + +#else // PC + +void GetBaseTextureAndNormal( sampler base, sampler base2, sampler bump, bool bBase2, bool bBump, float3 coords, float3 vWeights, + out float4 vResultBase, out float4 vResultBase2, out float4 vResultBump ) +{ + vResultBase = 0; + vResultBase2 = 0; + vResultBump = 0; + + if ( !bBump ) + { + vResultBump = float4(0, 0, 1, 1); + } + +#if SEAMLESS + + vResultBase += vWeights.x * tex2D( base, coords.zy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.x * tex2D( base2, coords.zy ); + } + if ( bBump ) + { + vResultBump += vWeights.x * tex2D( bump, coords.zy ); + } + + vResultBase += vWeights.y * tex2D( base, coords.xz ); + if ( bBase2 ) + { + vResultBase2 += vWeights.y * tex2D( base2, coords.xz ); + } + if ( bBump ) + { + vResultBump += vWeights.y * tex2D( bump, coords.xz ); + } + + vResultBase += vWeights.z * tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.z * tex2D( base2, coords.xy ); + } + if ( bBump ) + { + vResultBump += vWeights.z * tex2D( bump, coords.xy ); + } + +#else // not seamless + + vResultBase = tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 = tex2D( base2, coords.xy ); + } + if ( bBump ) + { + vResultBump = tex2D( bump, coords.xy ); + } +#endif + +} + +#endif + + + + +float3 LightMapSample( sampler LightmapSampler, float2 vTexCoord ) +{ +# if ( !defined( _X360 ) || !defined( USE_32BIT_LIGHTMAPS_ON_360 ) ) + { + float3 sample = tex2D( LightmapSampler, vTexCoord ); + + return sample; + } +# else + { +# if 0 //1 for cheap sampling, 0 for accurate scaling from the individual samples + { + float4 sample = tex2D( LightmapSampler, vTexCoord ); + + return sample.rgb * sample.a; + } +# else + { + float4 Weights; + float4 samples_0; //no arrays allowed in inline assembly + float4 samples_1; + float4 samples_2; + float4 samples_3; + + asm { + tfetch2D samples_0, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_1, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_2, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_3, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + + getWeights2D Weights, vTexCoord.xy, LightmapSampler + }; + + Weights = float4( (1-Weights.x)*(1-Weights.y), Weights.x*(1-Weights.y), (1-Weights.x)*Weights.y, Weights.x*Weights.y ); + + float3 result; + result.rgb = samples_0.rgb * (samples_0.a * Weights.x); + result.rgb += samples_1.rgb * (samples_1.a * Weights.y); + result.rgb += samples_2.rgb * (samples_2.a * Weights.z); + result.rgb += samples_3.rgb * (samples_3.a * Weights.w); + + return result; + } +# endif + } +# endif +} + diff --git a/sp/src/materialsystem/stdshaders/common_pragmas.h b/sp/src/materialsystem/stdshaders/common_pragmas.h new file mode 100644 index 00000000..50b61ff0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_pragmas.h @@ -0,0 +1,38 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Common shader compiler pragmas +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_PRAGMAS_H_ +#define COMMON_PRAGMAS_H_ + +// +// Validated shader models: +// +// SHADER_MODEL_VS_1_1 +// SHADER_MODEL_VS_2_0 +// SHADER_MODEL_VS_3_0 +// +// SHADER_MODEL_PS_1_1 +// SHADER_MODEL_PS_1_4 +// SHADER_MODEL_PS_2_0 +// SHADER_MODEL_PS_2_B +// SHADER_MODEL_PS_3_0 +// +// +// +// Platforms: +// +// PC +// _X360 +// + +// Special pragmas silencing common warnings +#pragma warning ( disable : 3557 ) // warning X3557: Loop only executes for N iteration(s), forcing loop to unroll +#pragma warning ( disable : 3595 ) // warning X3595: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused +#pragma warning ( disable : 3596 ) // warning X3596: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused +#pragma warning ( disable : 4702 ) // warning X4702: complement opportunity missed because input result WAS clamped from 0 to 1 + +#endif //#ifndef COMMON_PRAGMAS_H_ diff --git a/sp/src/materialsystem/stdshaders/common_ps_fxc.h b/sp/src/materialsystem/stdshaders/common_ps_fxc.h new file mode 100644 index 00000000..d4a47ea5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_ps_fxc.h @@ -0,0 +1,804 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Common pixel shader code +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_PS_FXC_H_ +#define COMMON_PS_FXC_H_ + +#include "common_fxc.h" + +// Put global skip commands here. . make sure and check that the appropriate vars are defined +// so these aren't used on the wrong shaders! + +// -------------------------------------------------------------------------------- +// HDR should never be enabled if we don't aren't running in float or integer HDR mode. +// SKIP: defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED +// -------------------------------------------------------------------------------- +// We don't ever write water fog to dest alpha if we aren't doing water fog. +// SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA +// -------------------------------------------------------------------------------- +// We don't need fog in the pixel shader if we aren't in float fog mode2 +// NOSKIP: defined $HDRTYPE && defined $HDRENABLED && defined $PIXELFOGTYPE && $HDRTYPE != HDR_TYPE_FLOAT && $FOGTYPE != 0 +// -------------------------------------------------------------------------------- +// We don't do HDR and LIGHTING_PREVIEW at the same time since it's running LDR in hammer. +// SKIP: defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0 +// -------------------------------------------------------------------------------- +// Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW. +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH +// -------------------------------------------------------------------------------- +// Ditch flashlight depth when flashlight is disabled +// SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW +// -------------------------------------------------------------------------------- + +// System defined pixel shader constants + +#if defined( _X360 ) +const bool g_bHighQualityShadows : register( b0 ); +#endif + +// NOTE: w == 1.0f / (Dest alpha compressed depth range). +const float4 g_LinearFogColor : register( c29 ); +#define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w) + +// Linear and gamma light scale values +const float4 cLightScale : register( c30 ); +#define LINEAR_LIGHT_SCALE (cLightScale.x) +#define LIGHT_MAP_SCALE (cLightScale.y) +#define ENV_MAP_SCALE (cLightScale.z) +#define GAMMA_LIGHT_SCALE (cLightScale.w) + +// Flashlight constants +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + const float4 cFlashlightColor : register( c28 ); + const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused + #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0 +#endif + +#define HDR_INPUT_MAP_SCALE 16.0f + +#define TONEMAP_SCALE_NONE 0 +#define TONEMAP_SCALE_LINEAR 1 +#define TONEMAP_SCALE_GAMMA 2 + +#define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader +#define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits) +#define PIXEL_FOG_TYPE_HEIGHT 1 + +// If you change these, make the corresponding change in hardwareconfig.cpp +#define NVIDIA_PCF_POISSON 0 +#define ATI_NOPCF 1 +#define ATI_NO_PCF_FETCH4 2 + +struct LPREVIEW_PS_OUT +{ + float4 color : COLOR0; + float4 normal : COLOR1; + float4 position : COLOR2; + float4 flags : COLOR3; +}; + +/* +// unused +HALF Luminance( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) ); +} +*/ + +/* +// unused +HALF LuminanceScaled( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) ); +} +*/ + +/* +// unused +HALF AvgColor( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) ); +} +*/ + +/* +// unused +HALF4 DiffuseBump( sampler lightmapSampler, + float2 lightmapTexCoord1, + float2 lightmapTexCoord2, + float2 lightmapTexCoord3, + HALF3 normal ) +{ + HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 ); + HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 ); + HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 ); + + HALF3 diffuseLighting; + diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 + + saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 + + saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3; + + return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) ); +} +*/ + + +/* +// unused +HALF Fresnel( HALF3 normal, + HALF3 eye, + HALF2 scaleBias ) +{ + HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye ); + fresnel = pow( fresnel, HALF_CONSTANT(5.0f) ); + + return fresnel * scaleBias.x + scaleBias.y; +} +*/ + +/* +// unused +HALF4 GetNormal( sampler normalSampler, + float2 normalTexCoord ) +{ + HALF4 normal = tex2D( normalSampler, normalTexCoord ); + normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f); + + return normal; +} +*/ + +// Needs to match NormalDecodeMode_t enum in imaterialsystem.h +#define NORM_DECODE_NONE 0 +#define NORM_DECODE_ATI2N 1 +#define NORM_DECODE_ATI2N_ALPHA 2 + +float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler ) +{ + float4 normalTexel = tex2D( NormalSampler, tc ); + float4 result; + + if ( nDecompressionMode == NORM_DECODE_NONE ) + { + result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a ); + } + else if ( nDecompressionMode == NORM_DECODE_ATI2N ) + { + result.xy = normalTexel.xy * 2.0f - 1.0f; + result.z = sqrt( 1.0f - dot(result.xy, result.xy) ); + result.a = 1.0f; + } + else // ATI2N plus ATI1N for alpha + { + result.xy = normalTexel.xy * 2.0f - 1.0f; + result.z = sqrt( 1.0f - dot(result.xy, result.xy) ); + result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel + } + + return result; +} + +float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode ) +{ + return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler ); +} + + +HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input ) +{ +// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f; + return texCUBE( normalizeSampler, input ); +} + +/* +HALF4 EnvReflect( sampler envmapSampler, + sampler normalizeSampler, + HALF3 normal, + float3 eye, + HALF2 fresnelScaleBias ) +{ + HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye ); + HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias ); + HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye ); + return texCUBE( envmapSampler, reflect ); +} +*/ + +float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange ) +{ +// float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp + float flDepthFromWater = flWaterZ - flWorldPosZ; + + // if flDepthFromWater < 0, then set it to 0 + // This is the equivalent of moving the vert to the water surface if it's above the water surface + // We'll do this with the saturate at the end instead. +// flDepthFromWater = max( 0.0f, flDepthFromWater ); + + // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer + // to the vert is actually underwater. + float flDepthFromEye = flEyePosZ - flWorldPosZ; + float f = saturate(flDepthFromWater * (1.0/flDepthFromEye)); + + // $tmp.w is now the distance that we see through water. + return saturate(f * flProjPosZ * flFogOORange); +} + +float CalcRangeFog( const float flProjPosZ, const float flFogStartOverRange, const float flFogMaxDensity, const float flFogOORange ) +{ +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + return saturate( min( flFogMaxDensity, (flProjPosZ * flFogOORange) - flFogStartOverRange ) ); +#else + return 0.0f; //ps20 shaders will never have range fog enabled because too many ran out of slots. +#endif +} + +float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float retVal; + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE ) + { + retVal = 0.0f; + } + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters + { + retVal = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w ); + } + else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog + { + retVal = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w ); + } + + return retVal; +} + +//g_FogParams not defined by default, but this is the same layout for every shader that does define it +#define g_FogEndOverRange g_FogParams.x +#define g_WaterZ g_FogParams.y +#define g_FogMaxDensity g_FogParams.z +#define g_FogOORange g_FogParams.w + +float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE ) +{ + if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b + { +# if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + pixelFogFactor = saturate( pixelFogFactor ); + return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog +# else + return vShaderColor; +# endif + } + else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) + { + return lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + } + else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE ) + { + return vShaderColor; + } +} + + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) && ( CONVERT_TO_SRGB != 0 ) ) +sampler1D GammaTableSampler : register( s15 ); + +float3 SRGBOutput( const float3 vShaderColor ) +{ + //On ps2b capable hardware we always have the linear->gamma conversion table texture in sampler s15. + float3 result; + result.r = tex1D( GammaTableSampler, vShaderColor.r ).r; + result.g = tex1D( GammaTableSampler, vShaderColor.g ).r; + result.b = tex1D( GammaTableSampler, vShaderColor.b ).r; + return result; +} + +#else + +float3 SRGBOutput( const float3 vShaderColor ) +{ + return vShaderColor; //ps 1.1, 1.4, and 2.0 never do srgb conversion in the pixel shader +} + +#endif + + +float SoftParticleDepth( float flDepth ) +{ + return flDepth * OO_DESTALPHA_DEPTH_RANGE; +} + + +float DepthToDestAlpha( const float flProjZ ) +{ +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + return SoftParticleDepth( flProjZ ); +#else + return 1.0f; +#endif +} + + +float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f ) +{ + float4 result; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE ) + { + result.rgb = vShaderColor.rgb; + } + + if( bWriteDepthToDestAlpha ) + result.a = DepthToDestAlpha( flProjZ ); + else + result.a = vShaderColor.a; + + result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE ); + +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion +#endif + + return result; +} + +LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE ) +{ + LPREVIEW_PS_OUT result; + result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE ); + result.normal.rgb = SRGBOutput( vShaderColor.normal.rgb ); + result.normal.a = vShaderColor.normal.a; + + result.position.rgb = SRGBOutput( vShaderColor.position.rgb ); + result.position.a = vShaderColor.position.a; + + result.flags.rgb = SRGBOutput( vShaderColor.flags.rgb ); + result.flags.a = vShaderColor.flags.a; + + return result; +} + + + + +float RemapValClamped( float val, float A, float B, float C, float D) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + + return C + (D - C) * cVal; +} + + +//===================================================================================// +// This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI) +//===================================================================================// +// INPUT: +// inTexCoord: +// the texcoord for the height/displacement map before parallaxing +// +// vParallax: +// Compute initial parallax displacement direction: +// float2 vParallaxDirection = normalize( vViewTS.xy ); +// float fLength = length( vViewTS ); +// float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z; +// Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight; +// +// vNormal: +// tangent space normal +// +// vViewW: +// float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition ); +// +// OUTPUT: +// the new texcoord after parallaxing +float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal, + float3 vViewW, sampler HeightMapSampler ) +{ + const int nMinSamples = 8; + const int nMaxSamples = 50; + + // Normalize the incoming view vector to avoid artifacts: +// vView = normalize( vView ); + vViewW = normalize( vViewW ); +// vLight = normalize( vLight ); + + // Change the number of samples per ray depending on the viewing angle + // for the surface. Oblique angles require smaller step sizes to achieve + // more accurate precision + int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) ); + + float4 cResultColor = float4( 0, 0, 0, 1 ); + + //===============================================// + // Parallax occlusion mapping offset computation // + //===============================================// + float fCurrHeight = 0.0; + float fStepSize = 1.0 / (float) nNumSteps; + float fPrevHeight = 1.0; + float fNextHeight = 0.0; + + int nStepIndex = 0; +// bool bCondition = true; + + float2 dx = ddx( inTexCoord ); + float2 dy = ddy( inTexCoord ); + + float2 vTexOffsetPerStep = fStepSize * vParallax; + + float2 vTexCurrentOffset = inTexCoord; + float fCurrentBound = 1.0; + + float x = 0; + float y = 0; + float xh = 0; + float yh = 0; + + float2 texOffset2 = 0; + + bool bCondition = true; + while ( bCondition == true && nStepIndex < nNumSteps ) + { + vTexCurrentOffset -= vTexOffsetPerStep; + + fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r; + + fCurrentBound -= fStepSize; + + if ( fCurrHeight > fCurrentBound ) + { + x = fCurrentBound; + y = fCurrentBound + fStepSize; + xh = fCurrHeight; + yh = fPrevHeight; + + texOffset2 = vTexCurrentOffset - vTexOffsetPerStep; + + bCondition = false; + } + else + { + nStepIndex++; + fPrevHeight = fCurrHeight; + } + + } // End of while ( bCondition == true && nStepIndex > -1 )#else + + fCurrentBound -= fStepSize; + + float fParallaxAmount; + float numerator = (x * (y - yh) - y * (x - xh)); + float denomenator = ((y - yh) - (x - xh)); + // avoid NaN generation + if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) ) + { + fParallaxAmount = 0.0f; + } + else + { + fParallaxAmount = numerator / denomenator; + } + + float2 vParallaxOffset = vParallax * (1 - fParallaxAmount ); + + // Sample the height at the next possible step: + fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r; + + // Original offset: + float2 texSampleBase = inTexCoord - vParallaxOffset; + + return texSampleBase; + +#if 0 + cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight ); + + float fBound = 1.0 - fStepSize * nStepIndex; + if ( fNextHeight < fCurrentBound ) +// if( 0 ) + { + //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor ) + //cResultColor.rgb = float3(1,0,0); + DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + + cResultColor.rgb /= 5; +// cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f ); + } // End of if ( fNextHeight < fCurrentBound ) + +#if DOSHADOWS + { + //============================================// + // Soft shadow and self-occlusion computation // + //============================================// + // Compute the blurry shadows (note that this computation takes into + // account self-occlusion for shadow computation): + float sh0 = tex2D( sNormalMap, texSampleBase).w; + float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening; + float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening; + float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening; + float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening; + float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening; + float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening; + float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening; + + // Compute the actual shadow strength: + float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 ); + + cResultColor.rgb *= fShadow * 0.6 + 0.4; + } +#endif + + return cResultColor; +#endif +} + + +//======================================// +// HSL Color space conversion routines // +//======================================// + +#define HUE 0 +#define SATURATION 1 +#define LIGHTNESS 2 + +// Convert from RGB to HSL color space +float4 RGBtoHSL( float4 inColor ) +{ + float h, s; + float flMax = max( inColor.r, max( inColor.g, inColor.b ) ); + float flMin = min( inColor.r, min( inColor.g, inColor.b ) ); + + float l = (flMax + flMin) / 2.0f; + + if (flMax == flMin) // achromatic case + { + s = h = 0; + } + else // chromatic case + { + // Next, calculate the hue + float delta = flMax - flMin; + + // First, calculate the saturation + if (l < 0.5f) // If we're in the lower hexcone + { + s = delta/(flMax + flMin); + } + else + { + s = delta/(2 - flMax - flMin); + } + + if ( inColor.r == flMax ) + { + h = (inColor.g - inColor.b)/delta; // color between yellow and magenta + } + else if ( inColor.g == flMax ) + { + h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow + } + else // blue must be max + { + h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan + } + + h *= 60.0f; + + if (h < 0.0f) + { + h += 360.0f; + } + + h /= 360.0f; + } + + return float4 (h, s, l, 1.0f); +} + +float HueToRGB( float v1, float v2, float vH ) +{ + float fResult = v1; + + vH = fmod (vH + 1.0f, 1.0f); + + if ( ( 6.0f * vH ) < 1.0f ) + { + fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH ); + } + else if ( ( 2.0f * vH ) < 1.0f ) + { + fResult = ( v2 ); + } + else if ( ( 3.0f * vH ) < 2.0f ) + { + fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f ); + } + + return fResult; +} + +// Convert from HSL to RGB color space +float4 HSLtoRGB( float4 hsl ) +{ + float r, g, b; + float h = hsl[HUE]; + float s = hsl[SATURATION]; + float l = hsl[LIGHTNESS]; + + if ( s == 0 ) + { + r = g = b = l; + } + else + { + float v1, v2; + + if ( l < 0.5f ) + v2 = l * ( 1.0f + s ); + else + v2 = ( l + s ) - ( s * l ); + + v1 = 2 * l - v2; + + r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) ); + g = HueToRGB( v1, v2, h ); + b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) ); + } + + return float4( r, g, b, 1.0f ); +} + + +// texture combining modes for combining base and detail/basetexture2 +#define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode +#define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend +#define TCOMBINE_DETAIL_OVER_BASE 2 +#define TCOMBINE_FADE 3 // straight fade between base and detail. +#define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail +#define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting +#define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6 +#define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail +#define TCOMBINE_MULTIPLY 8 +#define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base +#define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump +#define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11 + +float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode, + float fBlendFactor ) +{ + if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS) + { + float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a); + baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor); + } + if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2) + baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor); + if ( combine_mode == TCOMBINE_RGB_ADDITIVE ) + baseColor.rgb += fBlendFactor * detailColor.rgb; + if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE ) + { + float fblend=fBlendFactor * detailColor.a; + baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend); + } + if ( combine_mode == TCOMBINE_FADE ) + { + baseColor = lerp( baseColor, detailColor, fBlendFactor); + } + if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL ) + { + float fblend=fBlendFactor * (1-baseColor.a); + baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend ); + baseColor.a = detailColor.a; + } + if ( combine_mode == TCOMBINE_MULTIPLY ) + { + baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor); + } + + if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA ) + { + baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor ); + } + if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP ) + { + baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 ); + } + return baseColor; +} + +float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x) +{ + return f1+(f2-f1)*(x-i1)/(i2-i1); +} + +float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode, + float fBlendFactor ) +{ + if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM ) + lit_baseColor += fBlendFactor * detailColor.rgb; + if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE ) + { + // fade in an unusual way - instead of fading out color, remap an increasing band of it from + // 0..1 + //if (fBlendFactor > 0.5) + // lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) ); + //else + // lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5); + + float f = fBlendFactor - 0.5; + float fMult = (f >= 0) ? 1.0/fBlendFactor : 4*fBlendFactor; + float fAdd = (f >= 0) ? 1.0-fMult : -0.5*fMult; + lit_baseColor += saturate(fMult * detailColor.rgb + fAdd); + } + return lit_baseColor; +} + +//NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader +float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants ) +{ +# if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b + { + float flFeatheredAlpha; + float2 flDepths; +#define flSceneDepth flDepths.x +#define flSpriteDepth flDepths.y + +# if ( defined( _X360 ) ) + { + //Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors + asm { + tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point + }; + +# if( !defined( REVERSE_DEPTH_ON_X360 ) ) + flSceneDepth = 1.0f - flSceneDepth; +# endif + + //get the sprite depth into the same range as the texture depth + flSpriteDepth = fProjZ / fProjW; + + //unproject to get at the pre-projection z. This value is much more linear than depth + flDepths = vDepthBlendConstants.z / flDepths; + flDepths = vDepthBlendConstants.y - flDepths; + + flFeatheredAlpha = flSceneDepth - flSpriteDepth; + flFeatheredAlpha *= vDepthBlendConstants.x; + flFeatheredAlpha = saturate( flFeatheredAlpha ); + } +# else + { + flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer + flSpriteDepth = SoftParticleDepth( fProjZ ); + + flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x; + flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering. + flFeatheredAlpha = saturate( flFeatheredAlpha ); + } +# endif + +#undef flSceneDepth +#undef flSpriteDepth + + return flFeatheredAlpha; + } +# else + { + return 1.0f; + } +# endif +} + +#endif //#ifndef COMMON_PS_FXC_H_ diff --git a/sp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h b/sp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h new file mode 100644 index 00000000..66cc642a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h @@ -0,0 +1,423 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef COMMON_VERTEXLITGENERIC_DX9_H_ +#define COMMON_VERTEXLITGENERIC_DX9_H_ + +#include "common_ps_fxc.h" + +// We store four light colors and positions in an +// array of three of these structures like so: +// +// x y z w +// +------+------+------+------+ +// | L0.rgb | | +// +------+------+------+ | +// | L0.pos | L3 | +// +------+------+------+ rgb | +// | L1.rgb | | +// +------+------+------+------+ +// | L1.pos | | +// +------+------+------+ | +// | L2.rgb | L3 | +// +------+------+------+ pos | +// | L2.pos | | +// +------+------+------+------+ +// +struct PixelShaderLightInfo +{ + float4 color; + float4 pos; +}; + +#define cOverbright 2.0f +#define cOOOverbright 0.5f + +#define LIGHTTYPE_NONE 0 +#define LIGHTTYPE_SPOT 1 +#define LIGHTTYPE_POINT 2 +#define LIGHTTYPE_DIRECTIONAL 3 + +// Better suited to Pixel shader models, 11 instructions in pixel shader +// ... actually, now only 9: mul, cmp, cmp, mul, mad, mad, mad, mad, mad +float3 PixelShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + float3 linearColor, nSquared = worldNormal * worldNormal; + float3 isNegative = ( worldNormal >= 0.0 ) ? 0 : nSquared; + float3 isPositive = ( worldNormal >= 0.0 ) ? nSquared : 0; + linearColor = isPositive.x * cAmbientCube[0] + isNegative.x * cAmbientCube[1] + + isPositive.y * cAmbientCube[2] + isNegative.y * cAmbientCube[3] + + isPositive.z * cAmbientCube[4] + isNegative.z * cAmbientCube[5]; + return linearColor; +} + +// Better suited to Vertex shader models +// Six VS instructions due to use of constant indexing (slt, mova, mul, mul, mad, mad) +float3 VertexShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + float3 nSquared = worldNormal * worldNormal; + int3 isNegative = ( worldNormal < 0.0 ); + float3 linearColor; + linearColor = nSquared.x * cAmbientCube[isNegative.x] + + nSquared.y * cAmbientCube[isNegative.y+2] + + nSquared.z * cAmbientCube[isNegative.z+4]; + return linearColor; +} + +float3 AmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + // Vertex shader cases +#ifdef SHADER_MODEL_VS_1_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_1_1 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_2_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_3_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#else + // Pixel shader case + return PixelShaderAmbientLight( worldNormal, cAmbientCube ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Compute scalar diffuse term with various optional tweaks such as +// Half Lambert and ambient occlusion +//----------------------------------------------------------------------------- +float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const float3 lightDir, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float fResult; + + float NDotL = dot( worldNormal, lightDir ); // Unsaturated dot (-1 to 1 range) + + if ( bHalfLambert ) + { + fResult = saturate(NDotL * 0.5 + 0.5); // Scale and bias to 0 to 1 range + + if ( !bDoLightingWarp ) + { + fResult *= fResult; // Square + } + } + else + { + fResult = saturate( NDotL ); // Saturate pure Lambertian term + } + + if ( bDoAmbientOcclusion ) + { + // Raise to higher powers for darker AO values +// float fAOPower = lerp( 4.0f, 1.0f, fAmbientOcclusion ); +// result *= pow( NDotL * 0.5 + 0.5, fAOPower ); + fResult *= fAmbientOcclusion; + } + + float3 fOut = float3( fResult, fResult, fResult ); + if ( bDoLightingWarp ) + { + fOut = 2.0f * tex1D( lightWarpSampler, fResult ); + } + + return fOut; +} + +float3 PixelShaderDoGeneralDiffuseLight( const float fAtten, const float3 worldPos, const float3 worldNormal, + in sampler NormalizeSampler, + const float3 vPosition, const float3 vColor, const bool bHalfLambert, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + float3 lightDir = normalize( vPosition - worldPos ); +#else + float3 lightDir = NormalizeWithCubemap( NormalizeSampler, vPosition - worldPos ); +#endif + return vColor * fAtten * DiffuseTerm( bHalfLambert, worldNormal, lightDir, bDoAmbientOcclusion, fAmbientOcclusion, bDoLightingWarp, lightWarpSampler ); +} + +float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cLightInfo[3], int nLightIndex ) +{ + if ( nLightIndex == 3 ) + { + // Unpack light 3 from w components... + float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w ); + return normalize( vLight3Pos - worldPos ); + } + else + { + return normalize( cLightInfo[nLightIndex].pos - worldPos ); + } +} + +float3 PixelShaderGetLightColor( PixelShaderLightInfo cLightInfo[3], int nLightIndex ) +{ + if ( nLightIndex == 3 ) + { + // Unpack light 3 from w components... + return float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w ); + } + else + { + return cLightInfo[nLightIndex].color.rgb; + } +} + + +void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent, + const float3 vEyeDir, const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel, + const float3 color, const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + rimLighting = float3(0.0f, 0.0f, 0.0f); + + //float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal + float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal + float LdotR = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?) + specularLighting = pow( LdotR, fSpecularExponent ); // Raise to specular exponent + + // Optionally warp as function of scalar specular and fresnel + if ( bDoSpecularWarp ) + specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel } + + specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L + specularLighting *= color; // Modulate with light color + + if ( bDoAmbientOcclusion ) // Optionally modulate with ambient occlusion + specularLighting *= fAmbientOcclusion; + + if ( bDoRimLighting ) // Optionally do rim lighting + { + rimLighting = pow( LdotR, fRimExponent ); // Raise to rim exponent + rimLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L + rimLighting *= color; // Modulate with light color + } +} + +// Traditional fresnel term approximation +float Fresnel( const float3 vNormal, const float3 vEyeDir ) +{ + float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term + return fresnel * fresnel; // Square for a more subtle look +} + +// Traditional fresnel term approximation which uses 4th power (square twice) +float Fresnel4( const float3 vNormal, const float3 vEyeDir ) +{ + float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term + fresnel = fresnel * fresnel; // Square + return fresnel * fresnel; // Square again for a more subtle look +} + + +// +// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function +// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between +// low and mid while the 0.5 to 1 range blends between mid and high +// +// | +// | . M . . . H +// | . +// L +// | +// +---------------- +// 0 1 +// +float Fresnel( const float3 vNormal, const float3 vEyeDir, float3 vRanges ) +{ + //float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel + //if ( f > 0.5f ) + // result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values + //else + // result = lerp( vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values + + // note: vRanges is now encoded as ((mid-min)*2, mid, (max-mid)*2) to optimize math + float f = saturate( 1 - dot( vNormal, vEyeDir ) ); + f = f*f - 0.5; + return vRanges.y + (f >= 0.0 ? vRanges.z : vRanges.x) * f; +} + +void PixelShaderDoSpecularLight( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir, + const float fAtten, const float3 vLightColor, const float3 vLightDir, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel, + const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + // Compute Specular and rim terms + SpecularAndRimTerms( vWorldNormal, vLightDir, fSpecularExponent, + vEyeDir, bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten, + bDoRimLighting, fRimExponent, specularLighting, rimLighting ); +} + +float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6], + in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bHalfLambert, const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float3 linearColor = 0.0f; + + if ( bStaticLight ) + { + // The static lighting comes in in gamma space and has also been premultiplied by $cOOOverbright + // need to get it into + // linear space so that we can do adds. + linearColor += GammaToLinear( staticLightingColor * cOverbright ); + } + + if ( bAmbientLight ) + { + float3 ambient = AmbientLight( worldNormal, cAmbientCube ); + + if ( bDoAmbientOcclusion ) + ambient *= fAmbientOcclusion * fAmbientOcclusion; // Note squaring... + + linearColor += ambient; + } + + if ( nNumLights > 0 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler, + cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 1 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler, + cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 2 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler, + cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 3 ) + { + // Unpack the 4th light's data from tight constant packing + float3 vLight3Color = float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w ); + float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w ); + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler, + vLight3Pos, vLight3Color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + } + } + } + } + + return linearColor; +} + +void PixelShaderDoSpecularLighting( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir, + const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel, + const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 localSpecularTerm, localRimTerm; + + if( nNumLights > 0 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 0 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + if( nNumLights > 1 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 1 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + + if( nNumLights > 2 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 2 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + if( nNumLights > 3 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 3 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + +} + +float3 PixelShaderDoRimLighting( const float3 worldNormal, const float3 vEyeDir, const float3 cAmbientCube[6], float fFresnel ) +{ + float3 vReflect = reflect( -vEyeDir, worldNormal ); // Reflect view through normal + + return fFresnel * PixelShaderAmbientLight( vEyeDir, cAmbientCube ); +} + +// Called directly by newer shaders or through the following wrapper for older shaders +float3 PixelShaderDoLighting( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6], + in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bHalfLambert, + + // New optional/experimental parameters + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float3 linearColor = PixelShaderDoLightingLinear( worldPos, worldNormal, staticLightingColor, + bStaticLight, bAmbientLight, lightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + + // go ahead and clamp to the linear space equivalent of overbright 2 so that we match + // everything else. +// linearColor = HuePreservingColorClamp( linearColor, pow( 2.0f, 2.2 ) ); + + return linearColor; +} + +#endif //#ifndef COMMON_VERTEXLITGENERIC_DX9_H_ diff --git a/sp/src/materialsystem/stdshaders/common_vs_fxc.h b/sp/src/materialsystem/stdshaders/common_vs_fxc.h new file mode 100644 index 00000000..fe2e117a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/common_vs_fxc.h @@ -0,0 +1,955 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: This is where all common code for vertex shaders go. +// +// $NoKeywords: $ +// +//===========================================================================// + + + +#ifndef COMMON_VS_FXC_H_ +#define COMMON_VS_FXC_H_ + +#include "common_fxc.h" + +// Put global skip commands here. . make sure and check that the appropriate vars are defined +// so these aren't used on the wrong shaders! +// -------------------------------------------------------------------------------- +// Ditch all fastpath attemps if we are doing LIGHTING_PREVIEW. +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH +// -------------------------------------------------------------------------------- + + +#ifndef COMPRESSED_VERTS +// Default to no vertex compression +#define COMPRESSED_VERTS 0 +#endif + +#if ( !defined( SHADER_MODEL_VS_2_0 ) && !defined( SHADER_MODEL_VS_3_0 ) ) +#if COMPRESSED_VERTS == 1 +#error "Vertex compression is only for DX9 and up!" +#endif +#endif + +// We're testing 2 normal compression methods +// One compressed normals+tangents into a SHORT2 each (8 bytes total) +// The other compresses them together, into a single UBYTE4 (4 bytes total) +// FIXME: pick one or the other, compare lighting quality in important cases +#define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0 +#define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1 +//#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 +#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 + + +#define FOGTYPE_RANGE 0 +#define FOGTYPE_HEIGHT 1 + +#define COMPILE_ERROR ( 1/0; ) + +// ------------------------- +// CONSTANTS +// ------------------------- + +#pragma def ( vs, c0, 0.0f, 1.0f, 2.0f, 0.5f ) + +const float4 cConstants1 : register(c1); +#define cOOGamma cConstants1.x +#define cOverbright 2.0f +#define cOneThird cConstants1.z +#define cOOOverbright ( 1.0f / 2.0f ) + + +// The g_bLightEnabled registers and g_nLightCountRegister hold the same information regarding +// enabling lights, but callers internal to this file tend to use the loops, while external +// callers will end up using the booleans +const bool g_bLightEnabled[4] : register(b0); + // through b3 + +const int g_nLightCountRegister : register(i0); + + +#define g_nLightCount g_nLightCountRegister.x + +const float4 cEyePosWaterZ : register(c2); +#define cEyePos cEyePosWaterZ.xyz + +// Only cFlexScale.x is used +// It is a binary value used to switch on/off the addition of the flex delta stream +const float4 cFlexScale : register( c3 ); + +const float4x4 cModelViewProj : register(c4); +const float4x4 cViewProj : register(c8); + +// Used to compute projPosZ in shaders without skinning +// Using cModelViewProj with FastClip generates incorrect results +// This is just row two of the non-FastClip cModelViewProj matrix +const float4 cModelViewProjZ : register(c12); + +// More constants working back from the top... +const float4 cViewProjZ : register(c13); + +const float4 cFogParams : register(c16); +#define cFogEndOverFogRange cFogParams.x +#define cFogOne cFogParams.y +#define cFogMaxDensity cFogParams.z +#define cOOFogRange cFogParams.w + +const float4x4 cViewModel : register(c17); + +const float3 cAmbientCubeX [ 2 ] : register ( c21 ) ; +const float3 cAmbientCubeY [ 2 ] : register ( c23 ) ; +const float3 cAmbientCubeZ [ 2 ] : register ( c25 ) ; + +#if defined ( SHADER_MODEL_VS_3_0 ) +const float4 cFlexWeights [ 512 ] : register ( c1024 ) ; +#endif + +struct LightInfo +{ + float4 color; // {xyz} is color w is light type code (see comment below) + float4 dir; // {xyz} is dir w is light type code + float4 pos; + float4 spotParams; + float4 atten; +}; + +// w components of color and dir indicate light type: +// 1x - directional +// 01 - spot +// 00 - point + +// Four lights x 5 constants each = 20 constants +LightInfo cLightInfo[4] : register(c27); +#define LIGHT_0_POSITION_REG c29 + +#ifdef SHADER_MODEL_VS_1_1 + +const float4 cModulationColor : register(c37); + +#define SHADER_SPECIFIC_CONST_0 c38 +#define SHADER_SPECIFIC_CONST_1 c39 +#define SHADER_SPECIFIC_CONST_2 c40 +#define SHADER_SPECIFIC_CONST_3 c41 +#define SHADER_SPECIFIC_CONST_4 c42 +#define SHADER_SPECIFIC_CONST_5 c43 +#define SHADER_SPECIFIC_CONST_6 c44 +#define SHADER_SPECIFIC_CONST_7 c45 +#define SHADER_SPECIFIC_CONST_8 c46 +#define SHADER_SPECIFIC_CONST_9 c47 +#define SHADER_SPECIFIC_CONST_10 c14 +#define SHADER_SPECIFIC_CONST_11 c15 + +static const int cModel0Index = 48; +const float4x3 cModel[16] : register(c48); +// last cmodel is c105 for dx80, c214 for dx90 + +#else // DX9 shaders (vs20 and beyond) + +const float4 cModulationColor : register( c47 ); + +#define SHADER_SPECIFIC_CONST_0 c48 +#define SHADER_SPECIFIC_CONST_1 c49 +#define SHADER_SPECIFIC_CONST_2 c50 +#define SHADER_SPECIFIC_CONST_3 c51 +#define SHADER_SPECIFIC_CONST_4 c52 +#define SHADER_SPECIFIC_CONST_5 c53 +#define SHADER_SPECIFIC_CONST_6 c54 +#define SHADER_SPECIFIC_CONST_7 c55 +#define SHADER_SPECIFIC_CONST_8 c56 +#define SHADER_SPECIFIC_CONST_9 c57 +#define SHADER_SPECIFIC_CONST_10 c14 +#define SHADER_SPECIFIC_CONST_11 c15 + +static const int cModel0Index = 58; +const float4x3 cModel[53] : register( c58 ); +// last cmodel is c105 for dx80, c216 for dx90 + + +#define SHADER_SPECIFIC_BOOL_CONST_0 b4 +#define SHADER_SPECIFIC_BOOL_CONST_1 b5 +#define SHADER_SPECIFIC_BOOL_CONST_2 b6 +#define SHADER_SPECIFIC_BOOL_CONST_3 b7 +#define SHADER_SPECIFIC_BOOL_CONST_4 b8 +#define SHADER_SPECIFIC_BOOL_CONST_5 b9 +#define SHADER_SPECIFIC_BOOL_CONST_6 b10 +#define SHADER_SPECIFIC_BOOL_CONST_7 b11 +#endif // vertex shader model constant packing changes + + +//======================================================================================= +// Methods to decompress vertex normals +//======================================================================================= + +//----------------------------------------------------------------------------------- +// Decompress a normal from two-component compressed format +// We expect this data to come from a signed SHORT2 stream in the range of -32768..32767 +// +// -32678 and 0 are invalid encodings +// w contains the sign to use in the cross product when generating a binormal +void _DecompressShort2Tangent( float2 inputTangent, out float4 outputTangent ) +{ + float2 ztSigns = sign( inputTangent ); // sign bits for z and tangent (+1 or -1) + float2 xyAbs = abs( inputTangent ); // 1..32767 + outputTangent.xy = (xyAbs - 16384.0f) / 16384.0f; // x and y + outputTangent.z = ztSigns.x * sqrt( saturate( 1.0f - dot( outputTangent.xy, outputTangent.xy ) ) ); + outputTangent.w = ztSigns.y; +} + +//----------------------------------------------------------------------------------- +// Same code as _DecompressShort2Tangent, just one returns a float4, one a float3 +void _DecompressShort2Normal( float2 inputNormal, out float3 outputNormal ) +{ + float4 result; + _DecompressShort2Tangent( inputNormal, result ); + outputNormal = result.xyz; +} + +//----------------------------------------------------------------------------------- +// Decompress normal+tangent together +void _DecompressShort2NormalTangent( float2 inputNormal, float2 inputTangent, out float3 outputNormal, out float4 outputTangent ) +{ + // FIXME: if we end up sticking with the SHORT2 format, pack the normal and tangent into a single SHORT4 element + // (that would make unpacking normal+tangent here together much cheaper than the sum of their parts) + _DecompressShort2Normal( inputNormal, outputNormal ); + _DecompressShort2Tangent( inputTangent, outputTangent ); +} + +//======================================================================================= +// Decompress a normal and tangent from four-component compressed format +// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255 +// The final vTangent.w contains the sign to use in the cross product when generating a binormal +void _DecompressUByte4NormalTangent( float4 inputNormal, + out float3 outputNormal, // {nX, nY, nZ} + out float4 outputTangent ) // {tX, tY, tZ, sign of binormal} +{ + float fOne = 1.0f; + + float4 ztztSignBits = ( inputNormal - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction + float4 xyxyAbs = abs( inputNormal - 128.0f ) - ztztSignBits; // 0..127 + float4 xyxySignBits = ( xyxyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0) + float4 normTan = (abs( xyxyAbs - 64.0f ) - xyxySignBits) / 63.0f; // abs({nX, nY, tX, tY}) + outputNormal.xy = normTan.xy; // abs({nX, nY, __, __}) + outputTangent.xy = normTan.zw; // abs({tX, tY, __, __}) + + float4 xyxySigns = 1 - 2*xyxySignBits; // Convert sign bits to signs + float4 ztztSigns = 1 - 2*ztztSignBits; // ( [1,0] -> [-1,+1] ) + + outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1 + outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere + outputNormal.xy *= xyxySigns.xy; // Restore x and y signs + outputNormal.z *= ztztSigns.x; // Restore z sign + + outputTangent.z = 1.0f - outputTangent.x - outputTangent.y; // Project onto x+y+z=1 + outputTangent.xyz = normalize( outputTangent.xyz ); // Normalize onto unit sphere + outputTangent.xy *= xyxySigns.zw; // Restore x and y signs + outputTangent.z *= ztztSigns.z; // Restore z sign + outputTangent.w = ztztSigns.w; // Binormal sign +} + + +//----------------------------------------------------------------------------------- +// Decompress just a normal from four-component compressed format (same as above) +// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255 +// [ When compiled, this works out to approximately 17 asm instructions ] +void _DecompressUByte4Normal( float4 inputNormal, + out float3 outputNormal) // {nX, nY, nZ} +{ + float fOne = 1.0f; + + float2 ztSigns = ( inputNormal.xy - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction + float2 xyAbs = abs( inputNormal.xy - 128.0f ) - ztSigns; // 0..127 + float2 xySigns = ( xyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0) + outputNormal.xy = ( abs( xyAbs - 64.0f ) - xySigns ) / 63.0f; // abs({nX, nY}) + + outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1 + outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere + + outputNormal.xy *= lerp( fOne.xx, -fOne.xx, xySigns ); // Restore x and y signs + outputNormal.z *= lerp( fOne.x, -fOne.x, ztSigns.x ); // Restore z sign +} + + +void DecompressVertex_Normal( float4 inputNormal, out float3 outputNormal ) +{ + if ( COMPRESSED_VERTS == 1 ) + { + if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) + { + _DecompressShort2Normal( inputNormal.xy, outputNormal ); + } + else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) + { + _DecompressUByte4Normal( inputNormal, outputNormal ); + } + } + else + { + outputNormal = inputNormal.xyz; + } +} + +void DecompressVertex_NormalTangent( float4 inputNormal, float4 inputTangent, out float3 outputNormal, out float4 outputTangent ) +{ + if ( COMPRESSED_VERTS == 1 ) + { + if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) + { + _DecompressShort2NormalTangent( inputNormal.xy, inputTangent.xy, outputNormal, outputTangent ); + } + else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) + { + _DecompressUByte4NormalTangent( inputNormal, outputNormal, outputTangent ); + } + } + else + { + outputNormal = inputNormal.xyz; + outputTangent = inputTangent; + } +} + + +#ifdef SHADER_MODEL_VS_3_0 + +//----------------------------------------------------------------------------- +// Methods to sample morph data from a vertex texture +// NOTE: vMorphTargetTextureDim.x = width, cVertexTextureDim.y = height, cVertexTextureDim.z = # of float4 fields per vertex +// For position + normal morph for example, there will be 2 fields. +//----------------------------------------------------------------------------- +float4 SampleMorphDelta( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, const float flField ) +{ + float flColumn = floor( flVertexID / vMorphSubrect.w ); + + float4 t; + t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + flField + 0.5f; + t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f; + t.xy /= vMorphTargetTextureDim.xy; + t.z = t.w = 0.f; + + return tex2Dlod( vt, t ); +} + +// Optimized version which reads 2 deltas +void SampleMorphDelta2( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, out float4 delta1, out float4 delta2 ) +{ + float flColumn = floor( flVertexID / vMorphSubrect.w ); + + float4 t; + t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + 0.5f; + t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f; + t.xy /= vMorphTargetTextureDim.xy; + t.z = t.w = 0.f; + + delta1 = tex2Dlod( vt, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + delta2 = tex2Dlod( vt, t ); +} + +#endif // SHADER_MODEL_VS_3_0 + + +#if ( defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 ) ) + +//----------------------------------------------------------------------------- +// Method to apply morphs +//----------------------------------------------------------------------------- +bool ApplyMorph( float3 vPosFlex, inout float3 vPosition ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + return true; +} + +bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, inout float3 vPosition, inout float3 vNormal ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + return true; +} + +bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + vTangent.xyz += vNormalDelta; + return true; +} + +bool ApplyMorph( float4 vPosFlex, float3 vNormalFlex, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + flWrinkle = vPosFlex.w * cFlexScale.y; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + vTangent.xyz += vNormalDelta; + return true; +} + +#endif // defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 ) + + +#ifdef SHADER_MODEL_VS_3_0 + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition ) +{ +#if MORPHING + +#if !DECAL + // Flexes coming in from a separate stream + float4 vPosDelta = SampleMorphDelta( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, 0 ); + vPosition += vPosDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // !MORPHING + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // !MORPHING + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; + vTangent += vNormalDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; + vTangent += vNormalDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // MORPHING + + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; + vTangent += vNormalDelta.xyz; + flWrinkle = vPosDelta.w; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float4 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; + vTangent += vNormalDelta.xyz * vMorphTexCoord.z; + flWrinkle = vPosDelta.w * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // MORPHING + + flWrinkle = 0.0f; + return false; + +#endif +} + +#endif // SHADER_MODEL_VS_3_0 + + +float RangeFog( const float3 projPos ) +{ + return max( cFogMaxDensity, ( -projPos.z * cOOFogRange + cFogEndOverFogRange ) ); +} + +float WaterFog( const float3 worldPos, const float3 projPos ) +{ + float4 tmp; + + tmp.xy = cEyePosWaterZ.wz - worldPos.z; + + // tmp.x is the distance from the water surface to the vert + // tmp.y is the distance from the eye position to the vert + + // if $tmp.x < 0, then set it to 0 + // This is the equivalent of moving the vert to the water surface if it's above the water surface + + tmp.x = max( 0.0f, tmp.x ); + + // $tmp.w = $tmp.x / $tmp.y + tmp.w = tmp.x / tmp.y; + + tmp.w *= projPos.z; + + // $tmp.w is now the distance that we see through water. + + return max( cFogMaxDensity, ( -tmp.w * cOOFogRange + cFogOne ) ); +} + +float CalcFog( const float3 worldPos, const float3 projPos, const int fogType ) +{ +#if defined( _X360 ) + // 360 only does pixel fog + return 1.0f; +#endif + + if( fogType == FOGTYPE_RANGE ) + { + return RangeFog( projPos ); + } + else + { +#if SHADERMODEL_VS_2_0 == 1 + // We do this work in the pixel shader in dx9, so don't do any fog here. + return 1.0f; +#else + return WaterFog( worldPos, projPos ); +#endif + } +} + +float CalcFog( const float3 worldPos, const float3 projPos, const bool bWaterFog ) +{ +#if defined( _X360 ) + // 360 only does pixel fog + return 1.0f; +#endif + + float flFog; + if( !bWaterFog ) + { + flFog = RangeFog( projPos ); + } + else + { +#if SHADERMODEL_VS_2_0 == 1 + // We do this work in the pixel shader in dx9, so don't do any fog here. + flFog = 1.0f; +#else + flFog = WaterFog( worldPos, projPos ); +#endif + } + + return flFog; +} + +float4 DecompressBoneWeights( const float4 weights ) +{ + float4 result = weights; + + if ( COMPRESSED_VERTS ) + { + // Decompress from SHORT2 to float. In our case, [-1, +32767] -> [0, +1] + // NOTE: we add 1 here so we can divide by 32768 - which is exact (divide by 32767 is not). + // This avoids cracking between meshes with different numbers of bone weights. + // We use SHORT2 instead of SHORT2N for a similar reason - the GPU's conversion + // from [-32768,+32767] to [-1,+1] is imprecise in the same way. + result += 1; + result /= 32768; + } + + return result; +} + +void SkinPosition( bool bSkinning, const float4 modelPos, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos ) +{ +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + } + } +} + +void SkinPositionAndNormal( bool bSkinning, const float4 modelPos, const float3 modelNormal, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos, out float3 worldNormal ) +{ + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + worldNormal = mul3x3( modelNormal, ( float3x3 )blendMatrix ); + } + + } // end [isolate] +} + +// Is it worth keeping SkinPosition and SkinPositionAndNormal around since the optimizer +// gets rid of anything that isn't used? +void SkinPositionNormalAndTangentSpace( + bool bSkinning, + const float4 modelPos, const float3 modelNormal, + const float4 modelTangentS, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos, out float3 worldNormal, + out float3 worldTangentS, out float3 worldTangentT ) +{ +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] ); + worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )blendMatrix ); + worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )blendMatrix ); + } + worldTangentT = cross( worldNormal, worldTangentS ) * modelTangentS.w; + } +} + + +//----------------------------------------------------------------------------- +// Lighting helper functions +//----------------------------------------------------------------------------- + +float3 AmbientLight( const float3 worldNormal ) +{ + float3 nSquared = worldNormal * worldNormal; + int3 isNegative = ( worldNormal < 0.0 ); + float3 linearColor; + linearColor = nSquared.x * cAmbientCubeX[isNegative.x] + + nSquared.y * cAmbientCubeY[isNegative.y] + + nSquared.z * cAmbientCubeZ[isNegative.z]; + return linearColor; +} + +// The following "internal" routines are called "privately" by other routines in this file which +// handle the particular flavor of vs20 control flow appropriate to the original caller +float VertexAttenInternal( const float3 worldPos, int lightNum ) +{ + float result = 0.0f; + + // Get light direction + float3 lightDir = cLightInfo[lightNum].pos - worldPos; + + // Get light distance squared. + float lightDistSquared = dot( lightDir, lightDir ); + + // Get 1/lightDistance + float ooLightDist = rsqrt( lightDistSquared ); + + // Normalize light direction + lightDir *= ooLightDist; + + float3 vDist; +# if defined( _X360 ) + { + //X360 dynamic compile hits an internal compiler error using dst(), this is the breakdown of how dst() works from the 360 docs. + vDist.x = 1; + vDist.y = lightDistSquared * ooLightDist; + vDist.z = lightDistSquared; + //flDist.w = ooLightDist; + } +# else + { + vDist = dst( lightDistSquared, ooLightDist ); + } +# endif + + float flDistanceAtten = 1.0f / dot( cLightInfo[lightNum].atten.xyz, vDist ); + + // Spot attenuation + float flCosTheta = dot( cLightInfo[lightNum].dir.xyz, -lightDir ); + float flSpotAtten = (flCosTheta - cLightInfo[lightNum].spotParams.z) * cLightInfo[lightNum].spotParams.w; + flSpotAtten = max( 0.0001f, flSpotAtten ); + flSpotAtten = pow( flSpotAtten, cLightInfo[lightNum].spotParams.x ); + flSpotAtten = saturate( flSpotAtten ); + + // Select between point and spot + float flAtten = lerp( flDistanceAtten, flDistanceAtten * flSpotAtten, cLightInfo[lightNum].dir.w ); + + // Select between above and directional (no attenuation) + result = lerp( flAtten, 1.0f, cLightInfo[lightNum].color.w ); + + return result; +} + +float CosineTermInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert ) +{ + // Calculate light direction assuming this is a point or spot + float3 lightDir = normalize( cLightInfo[lightNum].pos - worldPos ); + + // Select the above direction or the one in the structure, based upon light type + lightDir = lerp( lightDir, -cLightInfo[lightNum].dir, cLightInfo[lightNum].color.w ); + + // compute N dot L + float NDotL = dot( worldNormal, lightDir ); + + if ( !bHalfLambert ) + { + NDotL = max( 0.0f, NDotL ); + } + else // Half-Lambert + { + NDotL = NDotL * 0.5 + 0.5; + NDotL = NDotL * NDotL; + } + return NDotL; +} + +// This routine uses booleans to do early-outs and is meant to be called by routines OUTSIDE of this file +float GetVertexAttenForLight( const float3 worldPos, int lightNum, bool bUseStaticControlFlow ) +{ + float result = 0.0f; + + // Direct3D uses static control flow but OpenGL currently does not + if ( bUseStaticControlFlow ) + { + if ( g_bLightEnabled[lightNum] ) + { + result = VertexAttenInternal( worldPos, lightNum ); + } + } + else // OpenGL non-static-control-flow path + { + result = VertexAttenInternal( worldPos, lightNum ); + } + + return result; +} + +float3 DoLightInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert ) +{ + return cLightInfo[lightNum].color * + CosineTermInternal( worldPos, worldNormal, lightNum, bHalfLambert ) * + VertexAttenInternal( worldPos, lightNum ); +} + +float3 DoLighting( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bDynamicLight, bool bHalfLambert ) +{ + float3 linearColor = float3( 0.0f, 0.0f, 0.0f ); + + if( bStaticLight ) // Static light + { + float3 col = staticLightingColor * cOverbright; +#if defined ( _X360 ) + linearColor += col * col; +#else + linearColor += GammaToLinear( col ); +#endif + } + + if( bDynamicLight ) // Dynamic light + { + for (int i = 0; i < g_nLightCount; i++) + { + linearColor += DoLightInternal( worldPos, worldNormal, i, bHalfLambert ); + } + } + + if( bDynamicLight ) + { + linearColor += AmbientLight( worldNormal ); //ambient light is already remapped + } + + return linearColor; +} + +float3 DoLightingUnrolled( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bDynamicLight, bool bHalfLambert, const int nNumLights ) +{ + float3 linearColor = float3( 0.0f, 0.0f, 0.0f ); + + if( bStaticLight ) // Static light + { + linearColor += GammaToLinear( staticLightingColor * cOverbright ); + } + + if( bDynamicLight ) // Ambient light + { + if ( nNumLights >= 1 ) + linearColor += DoLightInternal( worldPos, worldNormal, 0, bHalfLambert ); + if ( nNumLights >= 2 ) + linearColor += DoLightInternal( worldPos, worldNormal, 1, bHalfLambert ); + if ( nNumLights >= 3 ) + linearColor += DoLightInternal( worldPos, worldNormal, 2, bHalfLambert ); + if ( nNumLights >= 4 ) + linearColor += DoLightInternal( worldPos, worldNormal, 3, bHalfLambert ); + } + + if( bDynamicLight ) + { + linearColor += AmbientLight( worldNormal ); //ambient light is already remapped + } + + return linearColor; +} + +int4 FloatToInt( in float4 floats ) +{ + return D3DCOLORtoUBYTE4( floats.zyxw / 255.001953125 ); +} + +float2 ComputeSphereMapTexCoords( in float3 reflectionVector ) +{ + // transform reflection vector into view space + reflectionVector = mul( reflectionVector, ( float3x3 )cViewModel ); + + // generate + float3 tmp = float3( reflectionVector.x, reflectionVector.y, reflectionVector.z + 1.0f ); + + // find 1 / len + float ooLen = dot( tmp, tmp ); + ooLen = 1.0f / sqrt( ooLen ); + + // tmp = tmp/|tmp| + 1 + tmp.xy = ooLen * tmp.xy + 1.0f; + + return tmp.xy * 0.5f; +} + + +#define DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE 1 + // minxyz.minsoftness / maxxyz.maxsoftness +float3 ApplyDeformation( float3 worldpos, int deftype, float4 defparms0, float4 defparms1, + float4 defparms2, float4 defparms3 ) +{ + float3 ret = worldpos; + if ( deftype == DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE ) + { + ret=max( ret, defparms2.xyz ); + ret=min( ret, defparms3.xyz ); + } + + return ret; +} + + +#endif //#ifndef COMMON_VS_FXC_H_ diff --git a/sp/src/materialsystem/stdshaders/cpp_shader_constant_register_map.h b/sp/src/materialsystem/stdshaders/cpp_shader_constant_register_map.h new file mode 100644 index 00000000..b448b048 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cpp_shader_constant_register_map.h @@ -0,0 +1,45 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Provide convenient mapping for shader constants +// +// $NoKeywords: $ +//============================================================================= + +#define C_CODE_HACK +#include "shader_constant_register_map.h" +#undef C_CODE_HACK + +// For the C code, map the above file's defines back to integers... +#define PSREG_CONSTANT_00 0 +#define PSREG_CONSTANT_01 1 +#define PSREG_CONSTANT_02 2 +#define PSREG_CONSTANT_03 3 +#define PSREG_CONSTANT_04 4 +#define PSREG_CONSTANT_05 5 +#define PSREG_CONSTANT_06 6 +#define PSREG_CONSTANT_07 7 +#define PSREG_CONSTANT_08 8 +#define PSREG_CONSTANT_09 9 +#define PSREG_CONSTANT_10 10 +#define PSREG_CONSTANT_11 11 +#define PSREG_CONSTANT_12 12 +#define PSREG_CONSTANT_13 13 +#define PSREG_CONSTANT_14 14 +#define PSREG_CONSTANT_15 15 +#define PSREG_CONSTANT_16 16 +#define PSREG_CONSTANT_17 17 +#define PSREG_CONSTANT_18 18 +#define PSREG_CONSTANT_19 19 +#define PSREG_CONSTANT_20 20 +#define PSREG_CONSTANT_21 21 +#define PSREG_CONSTANT_22 22 +#define PSREG_CONSTANT_23 23 +#define PSREG_CONSTANT_24 24 +#define PSREG_CONSTANT_25 25 +#define PSREG_CONSTANT_26 26 +#define PSREG_CONSTANT_27 27 +#define PSREG_CONSTANT_28 28 +#define PSREG_CONSTANT_29 29 +#define PSREG_CONSTANT_30 30 +#define PSREG_CONSTANT_31 31 + diff --git a/sp/src/materialsystem/stdshaders/dx8fallbacks.cpp b/sp/src/materialsystem/stdshaders/dx8fallbacks.cpp new file mode 100644 index 00000000..9ee2659c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/dx8fallbacks.cpp @@ -0,0 +1,11 @@ +#include "BaseVSShader.h" + +// This one isn't supported on dx8 +DEFINE_FALLBACK_SHADER( SDK_DepthWrite, Wireframe ) + +DEFINE_FALLBACK_SHADER( SDK_EyeRefract, Eyes_dx8 ) +DEFINE_FALLBACK_SHADER( SDK_VolumeClouds, UnlitGeneric_DX8 ) + +// FIXME: These aren't supported on dx8, but need to be. +DEFINE_FALLBACK_SHADER( SDK_EyeGlint, EyeGlint ) +DEFINE_FALLBACK_SHADER( SDK_AfterShock, AfterShock ) diff --git a/sp/src/materialsystem/stdshaders/example_model_dx9.cpp b/sp/src/materialsystem/stdshaders/example_model_dx9.cpp new file mode 100644 index 00000000..87e012e3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/example_model_dx9.cpp @@ -0,0 +1,60 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Example shader that can be applied to models +// +//================================================================================================== + +#include "BaseVSShader.h" +#include "convar.h" +#include "example_model_dx9_helper.h" + +#ifdef GAME_SHADER_DLL +DEFINE_FALLBACK_SHADER( Mod_Example_Model, Mod_Example_Model_DX9 ) +BEGIN_VS_SHADER( Mod_Example_Model_DX9, "Help for Example Model Shader" ) +#else +DEFINE_FALLBACK_SHADER( Example_Model, Example_Model_DX9 ) +BEGIN_VS_SHADER( Example_Model_DX9, "Help for Example Model Shader" ) +#endif + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + END_SHADER_PARAMS + + void SetupVars( ExampleModel_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + } + + SHADER_INIT_PARAMS() + { + ExampleModel_DX9_Vars_t info; + SetupVars( info ); + InitParamsExampleModel_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + ExampleModel_DX9_Vars_t info; + SetupVars( info ); + InitExampleModel_DX9( this, params, info ); + } + + SHADER_DRAW + { + ExampleModel_DX9_Vars_t info; + SetupVars( info ); + DrawExampleModel_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression, pContextDataPtr ); + } + +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp new file mode 100644 index 00000000..471b9f80 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp @@ -0,0 +1,341 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "BaseVSShader.h" +#include "example_model_dx9_helper.h" +#include "convar.h" +#include "cpp_shader_constant_register_map.h" +#include "example_model_vs20.inc" +#include "example_model_ps20b.inc" +#include "commandbuilder.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT ); +static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT ); +static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT ); + +// Textures may be bound to the following samplers: +// SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha +// SHADER_SAMPLER4 Flashlight Shadow Depth Map +// SHADER_SAMPLER5 Normalization cube map +// SHADER_SAMPLER6 Flashlight Cookie + + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, ExampleModel_DX9_Vars_t &info ) +{ + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + Assert( info.m_nFlashlightTexture >= 0 ); + + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // This shader can be used with hw skinning + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); +} + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- +void InitExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, ExampleModel_DX9_Vars_t &info ) +{ + Assert( info.m_nFlashlightTexture >= 0 ); + pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB ); + + bool bIsBaseTextureTranslucent = false; + if ( params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + } +} + +class CExampleModel_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; + bool m_bFastPath; + +}; + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +void DrawExampleModel_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bHasFlashlight, ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) +{ + bool bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture(); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + + BlendType_t nBlendType= pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true ); + bool bFullyOpaque = ( nBlendType != BT_BLENDADD ) && ( nBlendType != BT_BLEND ) && !bIsAlphaTested && !bHasFlashlight; + + CExampleModel_DX9_Context *pContextData = reinterpret_cast< CExampleModel_DX9_Context *> ( *pContextDataPtr ); + if ( !pContextData ) + { + pContextData = new CExampleModel_DX9_Context; + *pContextDataPtr = pContextData; + } + + if( pShader->IsSnapshotting() ) + { + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + int nShadowFilterMode = 0; + if( bHasFlashlight ) + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + + if( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + else // not flashlight pass + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true ); + } + } + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int userDataSize = 0; + + // Always enable...will bind white if nothing specified... + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base (albedo) map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + if( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Noise map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Flashlight cookie + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true ); + userDataSize = 4; // tangent S + } + + // Always enable, since flat normal will be bound + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Normal map + userDataSize = 4; // tangent S + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Normalizing cube map + pShaderShadow->EnableSRGBWrite( true ); + + // texcoord0 : base texcoord, texcoord2 : decal hw morph delta + int pTexCoordDim[3] = { 2, 0, 3 }; + int nTexCoordCount = 1; + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( example_model_vs20 ); + SET_STATIC_VERTEX_SHADER( example_model_vs20 ); + + // Assume we're only going to get in here if we support 2b + DECLARE_STATIC_PIXEL_SHADER( example_model_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 ); + SET_STATIC_PIXEL_SHADER( example_model_ps20b ); + + if( bHasFlashlight ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + else // not snapshotting -- begin dynamic state + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + + if( bHasBaseTexture ) + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + + LightState_t lightState = { 0, false, false }; + bool bFlashlightShadows = false; + if( bHasFlashlight ) + { + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + pShader->BindTexture( SHADER_SAMPLER6, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame ); + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + + SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + } + } + else // no flashlight + { + pShaderAPI->GetDX9LightState( &lightState ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + int numBones = pShaderAPI->GetCurrentNumBones(); + + bool bWriteDepthToAlpha = false; + bool bWriteWaterFogToAlpha = false; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( example_model_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( example_model_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( example_model_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( example_model_ps20b ); + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + pShader->SetAmbientCubeDynamicStateVertexShader(); + + if( !bHasFlashlight ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + } + + pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight ); // Force to black if not bAmbientLight + pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY ); + + // handle mat_fullbright 2 (diffuse lighting only) + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + if( bHasFlashlight ) + { + VMatrix worldToTexture; + float atten[4], pos[4], tweaks[4]; + + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + pShader->BindTexture( SHADER_SAMPLER6, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + } + } + pShader->Draw(); +} + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +void DrawExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr ) + +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if ( bHasFlashlight ) + { + DrawExampleModel_DX9_Internal( pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression, pContextDataPtr++ ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + DrawExampleModel_DX9_Internal( pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression, pContextDataPtr ); +} diff --git a/sp/src/materialsystem/stdshaders/example_model_dx9_helper.h b/sp/src/materialsystem/stdshaders/example_model_dx9_helper.h new file mode 100644 index 00000000..3b82e71f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/example_model_dx9_helper.h @@ -0,0 +1,46 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Example shader that can be applied to models +// +//================================================================================================== + +#ifndef EXAMPLE_MODEL_DX9_HELPER_H +#define EXAMPLE_MODEL_DX9_HELPER_H + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct ExampleModel_DX9_Vars_t +{ + ExampleModel_DX9_Vars_t() { memset( this, 0xFF, sizeof(*this) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nAlphaTestReference; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; +}; + +void InitParamsExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, + const char *pMaterialName, ExampleModel_DX9_Vars_t &info ); + +void InitExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, + ExampleModel_DX9_Vars_t &info ); + +void DrawExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, + ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ); + +#endif // EXAMPLE_MODEL_DX9_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/example_model_ps20b.fxc b/sp/src/materialsystem/stdshaders/example_model_ps20b.fxc new file mode 100644 index 00000000..a7b35e44 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/example_model_ps20b.fxc @@ -0,0 +1,92 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Example pixel shader that can be applied to models +// +//================================================================================================== + +// STATIC: "CONVERT_TO_SRGB" "0..0" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] + +// SKIP: ($PIXELFOGTYPE == 0) && ($WRITEWATERFOGTODESTALPHA != 0) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b] + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +const float4 g_DiffuseModulation : register( PSREG_DIFFUSE_MODULATION ); +const float4 g_ShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_FlashlightAttenuationFactors : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass +const float4 g_FlashlightPos_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total (4th light spread across w's) + +#define g_FlashlightPos g_FlashlightPos_RimBoost.xyz + +sampler BaseTextureSampler : register( s0 ); // Base map, selfillum in alpha +sampler ShadowDepthSampler : register( s4 ); // Flashlight shadow depth map sampler +sampler NormalizeRandRotSampler : register( s5 ); // Normalization / RandomRotation samplers +sampler FlashlightSampler : register( s6 ); // Flashlight cookie + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float4 lightAtten : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 worldPos : TEXCOORD3; + float3 projPos : TEXCOORD4; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + + float3 diffuseLighting; + if ( FLASHLIGHT != 0 ) + { + float4 flashlightSpacePosition = mul( float4( i.worldPos, 1.0f ), g_FlashlightWorldToTexture ); + + diffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos, flashlightSpacePosition, + i.worldNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, i.projPos, false, g_ShadowTweaks ); + } + else // non-flashlight path + { + // Summation of diffuse illumination from all local lights + diffuseLighting = PixelShaderDoLighting( i.worldPos, i.worldNormal, + float3( 0.0f, 0.0f, 0.0f ), false, true, i.lightAtten, + cAmbientCube, NormalizeRandRotSampler, NUM_LIGHTS, cLightInfo, true, + + // These are dummy parameters: + false, 1.0f, + false, BaseTextureSampler ); + } + + float3 result = baseColor.rgb * g_DiffuseModulation.rgb * diffuseLighting; + float alpha = g_DiffuseModulation.a * baseColor.a; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos.z, i.projPos.z ); + +#if WRITEWATERFOGTODESTALPHA && ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) + alpha = fogFactor; +#endif + + bool bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 ); + + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.projPos.z ); +} diff --git a/sp/src/materialsystem/stdshaders/example_model_vs20.fxc b/sp/src/materialsystem/stdshaders/example_model_vs20.fxc new file mode 100644 index 00000000..877c84e2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/example_model_vs20.fxc @@ -0,0 +1,91 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Example vertex shader that can be applied to models +// +//================================================================================================== + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPosSetup : POSITION; + float fog : FOG; + // Stuff that is seen by the pixel shader + float2 baseTexCoord : TEXCOORD0; + float4 lightAtten : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 worldPos : TEXCOORD3; + float3 projPos : TEXCOORD4; +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + + float3 worldNormal, worldPos; + SkinPositionAndNormal( g_bSkinning, v.vPos, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPosSetup = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.projPos = vProjPos.xyz; + o.fog = CalcFog( worldPos, vProjPos.xyz, g_FogType ); + + // Needed for water fog alpha and diffuse lighting + o.worldPos = worldPos; + o.worldNormal = normalize( worldNormal ); + + // Scalar attenuations for four lights + o.lightAtten.xyz = float4(0,0,0,0); + #if ( NUM_LIGHTS > 0 ) + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, false ); + #endif + #if ( NUM_LIGHTS > 1 ) + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, false ); + #endif + #if ( NUM_LIGHTS > 2 ) + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, false ); + #endif + #if ( NUM_LIGHTS > 3 ) + o.lightAtten.w = GetVertexAttenForLight( worldPos, 3, false ); + #endif + + // Base texture coordinate transform + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/example_model_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9/example_model_ps20b.inc new file mode 100644 index 00000000..018f7b63 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/fxctmp9/example_model_ps20b.inc @@ -0,0 +1,237 @@ +#include "shaderlib/cshader.h" +class example_model_ps20b_Static_Index +{ +private: + int m_nCONVERT_TO_SRGB; +#ifdef _DEBUG + bool m_bCONVERT_TO_SRGB; +#endif +public: + void SetCONVERT_TO_SRGB( int i ) + { + Assert( i >= 0 && i <= 0 ); + m_nCONVERT_TO_SRGB = i; +#ifdef _DEBUG + m_bCONVERT_TO_SRGB = true; +#endif + } + void SetCONVERT_TO_SRGB( bool i ) + { + m_nCONVERT_TO_SRGB = i ? 1 : 0; +#ifdef _DEBUG + m_bCONVERT_TO_SRGB = true; +#endif + } +private: + int m_nFLASHLIGHT; +#ifdef _DEBUG + bool m_bFLASHLIGHT; +#endif +public: + void SetFLASHLIGHT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nFLASHLIGHT = i; +#ifdef _DEBUG + m_bFLASHLIGHT = true; +#endif + } + void SetFLASHLIGHT( bool i ) + { + m_nFLASHLIGHT = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHT = true; +#endif + } +private: + int m_nFLASHLIGHTDEPTHFILTERMODE; +#ifdef _DEBUG + bool m_bFLASHLIGHTDEPTHFILTERMODE; +#endif +public: + void SetFLASHLIGHTDEPTHFILTERMODE( int i ) + { + Assert( i >= 0 && i <= 2 ); + m_nFLASHLIGHTDEPTHFILTERMODE = i; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = true; +#endif + } + void SetFLASHLIGHTDEPTHFILTERMODE( bool i ) + { + m_nFLASHLIGHTDEPTHFILTERMODE = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = true; +#endif + } +public: + example_model_ps20b_Static_Index( ) + { +#ifdef _DEBUG + m_bCONVERT_TO_SRGB = false; +#endif // _DEBUG + m_nCONVERT_TO_SRGB = 0; +#ifdef _DEBUG + m_bFLASHLIGHT = false; +#endif // _DEBUG + m_nFLASHLIGHT = 0; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = false; +#endif // _DEBUG + m_nFLASHLIGHTDEPTHFILTERMODE = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bCONVERT_TO_SRGB && m_bFLASHLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nFLASHLIGHT ) + ( 160 * m_nFLASHLIGHTDEPTHFILTERMODE ) + 0; + } +}; +#define shaderStaticTest_example_model_ps20b psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + 0 +class example_model_ps20b_Dynamic_Index +{ +private: + int m_nWRITEWATERFOGTODESTALPHA; +#ifdef _DEBUG + bool m_bWRITEWATERFOGTODESTALPHA; +#endif +public: + void SetWRITEWATERFOGTODESTALPHA( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nWRITEWATERFOGTODESTALPHA = i; +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = true; +#endif + } + void SetWRITEWATERFOGTODESTALPHA( bool i ) + { + m_nWRITEWATERFOGTODESTALPHA = i ? 1 : 0; +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = true; +#endif + } +private: + int m_nPIXELFOGTYPE; +#ifdef _DEBUG + bool m_bPIXELFOGTYPE; +#endif +public: + void SetPIXELFOGTYPE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPIXELFOGTYPE = i; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } + void SetPIXELFOGTYPE( bool i ) + { + m_nPIXELFOGTYPE = i ? 1 : 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } +private: + int m_nNUM_LIGHTS; +#ifdef _DEBUG + bool m_bNUM_LIGHTS; +#endif +public: + void SetNUM_LIGHTS( int i ) + { + Assert( i >= 0 && i <= 4 ); + m_nNUM_LIGHTS = i; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } + void SetNUM_LIGHTS( bool i ) + { + m_nNUM_LIGHTS = i ? 1 : 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } +private: + int m_nWRITE_DEPTH_TO_DESTALPHA; +#ifdef _DEBUG + bool m_bWRITE_DEPTH_TO_DESTALPHA; +#endif +public: + void SetWRITE_DEPTH_TO_DESTALPHA( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nWRITE_DEPTH_TO_DESTALPHA = i; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = true; +#endif + } + void SetWRITE_DEPTH_TO_DESTALPHA( bool i ) + { + m_nWRITE_DEPTH_TO_DESTALPHA = i ? 1 : 0; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = true; +#endif + } +private: + int m_nFLASHLIGHTSHADOWS; +#ifdef _DEBUG + bool m_bFLASHLIGHTSHADOWS; +#endif +public: + void SetFLASHLIGHTSHADOWS( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nFLASHLIGHTSHADOWS = i; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = true; +#endif + } + void SetFLASHLIGHTSHADOWS( bool i ) + { + m_nFLASHLIGHTSHADOWS = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = true; +#endif + } +public: + example_model_ps20b_Dynamic_Index() + { +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = false; +#endif // _DEBUG + m_nWRITEWATERFOGTODESTALPHA = 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = false; +#endif // _DEBUG + m_nPIXELFOGTYPE = 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = false; +#endif // _DEBUG + m_nNUM_LIGHTS = 0; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = false; +#endif // _DEBUG + m_nWRITE_DEPTH_TO_DESTALPHA = 0; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = false; +#endif // _DEBUG + m_nFLASHLIGHTSHADOWS = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bWRITEWATERFOGTODESTALPHA && m_bPIXELFOGTYPE && m_bNUM_LIGHTS && m_bWRITE_DEPTH_TO_DESTALPHA && m_bFLASHLIGHTSHADOWS; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nWRITEWATERFOGTODESTALPHA ) + ( 2 * m_nPIXELFOGTYPE ) + ( 4 * m_nNUM_LIGHTS ) + ( 20 * m_nWRITE_DEPTH_TO_DESTALPHA ) + ( 40 * m_nFLASHLIGHTSHADOWS ) + 0; + } +}; +#define shaderDynamicTest_example_model_ps20b psh_forgot_to_set_dynamic_WRITEWATERFOGTODESTALPHA + psh_forgot_to_set_dynamic_PIXELFOGTYPE + psh_forgot_to_set_dynamic_NUM_LIGHTS + psh_forgot_to_set_dynamic_WRITE_DEPTH_TO_DESTALPHA + psh_forgot_to_set_dynamic_FLASHLIGHTSHADOWS + 0 diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/example_model_vs20.inc b/sp/src/materialsystem/stdshaders/fxctmp9/example_model_vs20.inc new file mode 100644 index 00000000..a8dbd23f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/fxctmp9/example_model_vs20.inc @@ -0,0 +1,160 @@ +#include "shaderlib/cshader.h" +class example_model_vs20_Static_Index +{ +public: + example_model_vs20_Static_Index( ) + { + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG +#endif // _DEBUG + return 0; + } +}; +#define shaderStaticTest_example_model_vs20 0 +class example_model_vs20_Dynamic_Index +{ +private: + int m_nCOMPRESSED_VERTS; +#ifdef _DEBUG + bool m_bCOMPRESSED_VERTS; +#endif +public: + void SetCOMPRESSED_VERTS( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nCOMPRESSED_VERTS = i; +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = true; +#endif + } + void SetCOMPRESSED_VERTS( bool i ) + { + m_nCOMPRESSED_VERTS = i ? 1 : 0; +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = true; +#endif + } +private: + int m_nDOWATERFOG; +#ifdef _DEBUG + bool m_bDOWATERFOG; +#endif +public: + void SetDOWATERFOG( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nDOWATERFOG = i; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } + void SetDOWATERFOG( bool i ) + { + m_nDOWATERFOG = i ? 1 : 0; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } +private: + int m_nSKINNING; +#ifdef _DEBUG + bool m_bSKINNING; +#endif +public: + void SetSKINNING( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nSKINNING = i; +#ifdef _DEBUG + m_bSKINNING = true; +#endif + } + void SetSKINNING( bool i ) + { + m_nSKINNING = i ? 1 : 0; +#ifdef _DEBUG + m_bSKINNING = true; +#endif + } +private: + int m_nLIGHTING_PREVIEW; +#ifdef _DEBUG + bool m_bLIGHTING_PREVIEW; +#endif +public: + void SetLIGHTING_PREVIEW( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nLIGHTING_PREVIEW = i; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = true; +#endif + } + void SetLIGHTING_PREVIEW( bool i ) + { + m_nLIGHTING_PREVIEW = i ? 1 : 0; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = true; +#endif + } +private: + int m_nNUM_LIGHTS; +#ifdef _DEBUG + bool m_bNUM_LIGHTS; +#endif +public: + void SetNUM_LIGHTS( int i ) + { + Assert( i >= 0 && i <= 4 ); + m_nNUM_LIGHTS = i; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } + void SetNUM_LIGHTS( bool i ) + { + m_nNUM_LIGHTS = i ? 1 : 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } +public: + example_model_vs20_Dynamic_Index() + { +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = false; +#endif // _DEBUG + m_nCOMPRESSED_VERTS = 0; +#ifdef _DEBUG + m_bDOWATERFOG = false; +#endif // _DEBUG + m_nDOWATERFOG = 0; +#ifdef _DEBUG + m_bSKINNING = false; +#endif // _DEBUG + m_nSKINNING = 0; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = false; +#endif // _DEBUG + m_nLIGHTING_PREVIEW = 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = false; +#endif // _DEBUG + m_nNUM_LIGHTS = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bCOMPRESSED_VERTS && m_bDOWATERFOG && m_bSKINNING && m_bLIGHTING_PREVIEW && m_bNUM_LIGHTS; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nCOMPRESSED_VERTS ) + ( 2 * m_nDOWATERFOG ) + ( 4 * m_nSKINNING ) + ( 8 * m_nLIGHTING_PREVIEW ) + ( 16 * m_nNUM_LIGHTS ) + 0; + } +}; +#define shaderDynamicTest_example_model_vs20 vsh_forgot_to_set_dynamic_COMPRESSED_VERTS + vsh_forgot_to_set_dynamic_DOWATERFOG + vsh_forgot_to_set_dynamic_SKINNING + vsh_forgot_to_set_dynamic_LIGHTING_PREVIEW + vsh_forgot_to_set_dynamic_NUM_LIGHTS + 0 diff --git a/sp/src/materialsystem/stdshaders/game_shader_dx9_base.vpc b/sp/src/materialsystem/stdshaders/game_shader_dx9_base.vpc new file mode 100644 index 00000000..2fb7fc9e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/game_shader_dx9_base.vpc @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// game_shader_dx9.vpc +// +// Project Script for mods to use an an example of how to override shaders +//----------------------------------------------------------------------------- + +$Macro OUTBINDIR "$SRCDIR\..\game\$GAMENAME\bin" + +$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc" + +$Configuration "Debug" +{ + $General + { + $OutputDirectory "Debug_dx9_$GAMENAME" [$WIN32] + $IntermediateDirectory "Debug_dx9_$GAMENAME" [$WIN32] + } +} + +$Configuration "Release" +{ + $General + { + $OutputDirectory "Release_dx9_$GAMENAME" [$WIN32] + $IntermediateDirectory "Release_dx9_$GAMENAME" [$WIN32] + } +} + +// Common Configuration +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE;fxctmp9;vshtmp9;" [$WIN32||$POSIX] +// $AdditionalIncludeDirectories "$BASE;..\..\dx9sdk\include" [$WIN32] + $AdditionalIncludeDirectories "$BASE;fxctmp9_360;vshtmp9_360" [$X360] + $PreprocessorDefinitions "$BASE;STDSHADER_DX9_DLL_EXPORT;FAST_MATERIALVAR_ACCESS;GAME_SHADER_DLL" + $PreprocessorDefinitions "$BASE;USE_ACTUAL_DX" [($WIN32||$X360) && !$GL] + } + + $Linker + { + $AdditionalDependencies "$BASE version.lib winmm.lib" [$WIN32] + $SystemLibraries "iconv" [$OSXALL] + } +} + +$Project +{ + $Folder "Source Files" + { + $File "BaseVSShader.cpp" + + $File "example_model_dx9.cpp" + $File "example_model_dx9_helper.cpp" + } + + $Folder "Header Files" + { + $File "BaseVSShader.h" + $File "common_fxc.h" + $File "common_hlsl_cpp_consts.h" + $File "common_ps_fxc.h" + $File "common_vertexlitgeneric_dx9.h" + $File "common_vs_fxc.h" + $File "shader_constant_register_map.h" + + $File "example_model_dx9_helper.h" + } + + $Folder "Link Libraries" [$WIN32] + { +// $File "$SRCDIR\dx9sdk\lib\d3dx9.lib" + $DynamicFile "$SRCDIR\lib\public\mathlib.lib" + $DynamicFile "$SRCDIR\lib\public\shaderlib.lib" + } + + $Folder "Link Libraries" [$X360] + { + $DynamicFile "$SRCDIR\lib\public\mathlib_360.lib" + $DynamicFile "$SRCDIR\lib\public\shaderlib_360.lib" + } + + $Folder "Link Libraries" [$POSIX&&!$LINUX] + { + $DynamicFile "$SRCDIR\lib\$PLATFORM\mathlib$_STATICLIB_EXT" + $DynamicFile "$SRCDIR\lib\$PLATFORM\shaderlib$_STATICLIB_EXT" + } + + $Folder "Link Libraries" [$LINUX] + { + $Lib mathlib + $Lib shaderlib + } + + $File "buildsdkshaders.bat" + $File "buildshaders.bat" + + $Shaders "stdshader_dx9_20b.txt" + $Shaders "stdshader_dx9_30.txt" +} diff --git a/sp/src/materialsystem/stdshaders/game_shader_dx9_episodic.vpc b/sp/src/materialsystem/stdshaders/game_shader_dx9_episodic.vpc new file mode 100644 index 00000000..670a5082 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/game_shader_dx9_episodic.vpc @@ -0,0 +1,13 @@ +//----------------------------------------------------------------------------- +// game_shader_dx9.vpc +// +// Project Script for mods to use an an example of how to override shaders +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro GAMENAME "mod_episodic" +$Include "$SRCDIR\materialsystem\stdshaders\game_shader_dx9_base.vpc" + +$Project "Shaders (Episodic)" +{ +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/game_shader_dx9_hl2.vpc b/sp/src/materialsystem/stdshaders/game_shader_dx9_hl2.vpc new file mode 100644 index 00000000..ad9068c3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/game_shader_dx9_hl2.vpc @@ -0,0 +1,13 @@ +//----------------------------------------------------------------------------- +// game_shader_dx9.vpc +// +// Project Script for mods to use an an example of how to override shaders +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro GAMENAME "mod_hl2" +$Include "$SRCDIR\materialsystem\stdshaders\game_shader_dx9_base.vpc" + +$Project "Shaders (HL2)" +{ +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/genwaterloop.pl b/sp/src/materialsystem/stdshaders/genwaterloop.pl new file mode 100644 index 00000000..0a4701ce --- /dev/null +++ b/sp/src/materialsystem/stdshaders/genwaterloop.pl @@ -0,0 +1,9 @@ +for($ix=-2;$ix<=2;$ix++) +{ + for($iy=-2;$iy<=2;$iy++) + { + print "vRefractColor += tex2D( RefractSampler, vRefractTexCoord + $ix * ddx1 + $iy * ddy1 );\n"; + $sumweights+=1; + } +} +print "float sumweights = $sumweights;\n"; diff --git a/sp/src/materialsystem/stdshaders/macros.vsh b/sp/src/materialsystem/stdshaders/macros.vsh new file mode 100644 index 00000000..9b19f777 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/macros.vsh @@ -0,0 +1,1393 @@ +;------------------------------------ +; RULES FOR AUTHORING VERTEX SHADERS: +;------------------------------------ +; - never use "def" . . .set constants in code instead. . our constant shadowing will break otherwise. +; (same goes for pixel shaders) +; - use cN notation instead of c[N] notation. .makes grepping for registers easier. +; The only exception is c[a0.x+blah] where you have no choice. +$g_NumRegisters = 12; + +; NOTE: These must match the same values in vsh_prep.pl! +$vPos = "v0"; +$vBoneWeights = "v1"; +$vBoneIndices = "v2"; +$vNormal = "v3"; +$vColor = "v5"; +$vSpecular = "v6"; +$vTexCoord0 = "v7"; +$vTexCoord1 = "v8"; +$vTexCoord2 = "v9"; +$vTexCoord3 = "v10"; +$vTangentS = "v11"; +$vTangentT = "v12"; +$vUserData = "v14"; + +if( $g_dx9 ) +{ + if( $g_usesPos ) + { + dcl_position $vPos; + } + + if( $g_usesBoneWeights ) + { + dcl_blendweight $vBoneWeights; + } + if( $g_usesBoneIndices ) + { + dcl_blendindices $vBoneIndices; + } + if( $g_usesNormal ) + { + dcl_normal $vNormal; + } + if( $g_usesColor ) + { + dcl_color0 $vColor; + } + if( $g_usesSpecular ) + { + dcl_color1 $vSpecular; + } + if( $g_usesTexCoord0 ) + { + dcl_texcoord0 $vTexCoord0; + } + if( $g_usesTexCoord1 ) + { + dcl_texcoord1 $vTexCoord1; + } + if( $g_usesTexCoord2 ) + { + dcl_texcoord2 $vTexCoord2; + } + if( $g_usesTexCoord3 ) + { + dcl_texcoord3 $vTexCoord3; + } + if( $g_usesTangentS ) + { + dcl_tangent $vTangentS; + } + if( $g_usesTangentT ) + { + dcl_binormal0 $vTangentT; + } + if( $g_usesUserData ) + { + dcl_tangent $vUserData; + } +} + +# NOTE: These should match g_LightCombinations in vertexshaderdx8.cpp! +# NOTE: Leave this on single lines or shit might blow up. +@g_staticLightTypeArray = ( "none", "static", "none", "none", "none", "none", "none", "none", "none", "none", "none", "none", "static", "static", "static", "static", "static", "static", "static", "static", "static", "static" ); +@g_ambientLightTypeArray = ( "none", "none", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient" ); +@g_localLightType1Array = ( "none", "none", "none", "spot", "point", "directional", "spot", "spot", "spot", "point", "point", "directional", "none", "spot", "point", "directional", "spot", "spot", "spot", "point", "point", "directional" ); +@g_localLightType2Array = ( "none", "none", "none", "none", "none", "none", "spot", "point", "directional", "point", "directional", "directional", "none", "none", "none", "none", "spot", "point", "directional", "point", "directional", "directional" ); + +$cConstants0 = "c0"; +$cZero = "c0.x"; +$cOne = "c0.y"; +$cTwo = "c0.z"; +$cHalf = "c0.w"; + +$cConstants1 = "c1"; +$cOOGamma = "c1.x"; # 1/2.2 +$cOtherOverbrightFactor = "c1.y"; # overbright +$cOneThird = "c1.z"; # 1/3 +$cOverbrightFactor = "c1.w"; # 1/overbright + +$cEyePos = "c2"; +$cWaterZ = "c2.w"; +$cEyePosWaterZ = "c2"; + +$cLightIndex = "c3"; +$cLight0Offset = "c3.x"; # 27 +$cLight1Offset = "c3.y"; # 32 +$cColorToIntScale = "c3.z"; # matrix array offset = 3.0f * 255.0f + 0.01 (epsilon ensures floor yields desired result) +$cModel0Index = "c3.w"; # base for start of skinning matrices + +; NOTE: These must match the same values in vsh_prep.pl! +$cModelViewProj0 = "c4"; +$cModelViewProj1 = "c5"; +$cModelViewProj2 = "c6"; +$cModelViewProj3 = "c7"; + +$cViewProj0 = "c8"; +$cViewProj1 = "c9"; +$cViewProj2 = "c10"; +$cViewProj3 = "c11"; + +; currently unused +; c12, c13 + +$SHADER_SPECIFIC_CONST_10 = "c14"; +$SHADER_SPECIFIC_CONST_11 = "c15"; + +$cFogParams = "c16"; +$cFogEndOverFogRange = "c16.x"; +$cFogOne = "c16.y"; +$cFogMaxDensity = "c16.z"; +$cOOFogRange = "c16.w"; # (1/(fogEnd-fogStart)) + +$cViewModel0 = "c17"; +$cViewModel1 = "c18"; +$cViewModel2 = "c19"; +$cViewModel3 = "c20"; + +$cAmbientColorPosX = "c21"; +$cAmbientColorNegX = "c22"; +$cAmbientColorPosY = "c23"; +$cAmbientColorNegY = "c24"; +$cAmbientColorPosZ = "c25"; +$cAmbientColorNegZ = "c26"; + +$cAmbientColorPosXOffset = "21"; +$cAmbientColorPosYOffset = "23"; +$cAmbientColorPosZOffset = "25"; + +$cLight0DiffColor = "c27"; +$cLight0Dir = "c28"; +$cLight0Pos = "c29"; +$cLight0SpotParams = "c30"; # [ exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2) +$cLight0Atten = "c31"; # [ constant, linear, quadratic, 0.0f ] + +$cLight1DiffColor = "c32"; +$cLight1Dir = "c33"; +$cLight1Pos = "c34"; +$cLight1SpotParams = "c35"; # [ exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2) +$cLight1Atten = "c36"; # [ constant, linear, quadratic, 0.0f ] + +$cModulationColor = "c37"; + +$SHADER_SPECIFIC_CONST_0 = "c38"; +$SHADER_SPECIFIC_CONST_1 = "c39"; +$SHADER_SPECIFIC_CONST_2 = "c40"; +$SHADER_SPECIFIC_CONST_3 = "c41"; +$SHADER_SPECIFIC_CONST_4 = "c42"; +$SHADER_SPECIFIC_CONST_5 = "c43"; +$SHADER_SPECIFIC_CONST_6 = "c44"; +$SHADER_SPECIFIC_CONST_7 = "c45"; +$SHADER_SPECIFIC_CONST_8 = "c46"; +$SHADER_SPECIFIC_CONST_9 = "c47"; +; $SHADER_SPECIFIC_CONST_10 is c14 +; $SHADER_SPECIFIC_CONST_11 is c15 + +; There are 16 model matrices for skinning +; NOTE: These must match the same values in vsh_prep.pl! +$cModel0 = "c48"; +$cModel1 = "c49"; +$cModel2 = "c50"; + +sub OutputUsedRegisters +{ + local( $i ); + ; USED REGISTERS + for( $i = 0; $i < $g_NumRegisters; $i++ ) + { + if( $g_allocated[$i] ) + { + ; $g_allocatedname[$i] = r$i + } + } + ; +} + +sub AllocateRegister +{ + local( *reg ) = shift; + local( $regname ) = shift; + local( $i ); + for( $i = 0; $i < $g_NumRegisters; $i++ ) + { + if( !$g_allocated[$i] ) + { + $g_allocated[$i] = 1; + $g_allocatedname[$i] = $regname; + ; AllocateRegister $regname = r$i + $reg = "r$i"; + &OutputUsedRegisters(); + return; + } + } + ; Out of registers allocating $regname! + $reg = "rERROR_OUT_OF_REGISTERS"; + &OutputUsedRegisters(); +} + +; pass in a reference to a var that contains a register. . ie \$var where var will constain "r1", etc +sub FreeRegister +{ + local( *reg ) = shift; + local( $regname ) = shift; + ; FreeRegister $regname = $reg + if( $reg =~ m/rERROR_DEALLOCATED/ ) + { + ; $regname already deallocated + ; $reg = "rALREADY_DEALLOCATED"; + &OutputUsedRegisters(); + return; + } +; if( $regname ne g_allocatedname[$reg] ) +; { +; ; Error freeing $reg +; mov compileerror, freed unallocated register $regname +; } + + if( ( $reg =~ m/r(.*)/ ) ) + { + $g_allocated[$1] = 0; + } + $reg = "rERROR_DEALLOCATED"; + &OutputUsedRegisters(); +} + +sub CheckUnfreedRegisters() +{ + local( $i ); + for( $i = 0; $i < $g_NumRegisters; $i++ ) + { + if( $g_allocated[$i] ) + { + print "ERROR: r$i allocated to $g_allocatedname[$i] at end of program\n"; + $g_allocated[$i] = 0; + } + } +} + +sub Normalize +{ + local( $r ) = shift; + dp3 $r.w, $r, $r + rsq $r.w, $r.w + mul $r, $r, $r.w +} + +sub Cross +{ + local( $result ) = shift; + local( $a ) = shift; + local( $b ) = shift; + + mul $result.xyz, $a.yzx, $b.zxy + mad $result.xyz, -$b.yzx, $a.zxy, $result +} + +sub RangeFog +{ + local( $projPos ) = shift; + + ;------------------------------ + ; Regular range fog + ;------------------------------ + + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + ; compute fog factor f = (fog_end - dist)*(1/(fog_end-fog_start)) + ; this is == to: (fog_end/(fog_end-fog_start) - dist/(fog_end-fog_start) + ; which can be expressed with a single mad instruction! + + ; Compute |projPos| + local( $tmp ); + &AllocateRegister( \$tmp ); + dp3 $tmp.x, $projPos.xyw, $projPos.xyw + rsq $tmp.x, $tmp.x + rcp $tmp.x, $tmp.x + + if( $g_dx9 ) + { + mad $tmp, -$tmp.x, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max oFog, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$tmp.x, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max oFog.x, $tmp.x, $cFogMaxDensity + } + &FreeRegister( \$tmp ); +} + +sub DepthFog +{ + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + ;------------------------------ + ; Regular range fog + ;------------------------------ + + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + ; compute fog factor f = (fog_end - dist)*(1/(fog_end-fog_start)) + ; this is == to: (fog_end/(fog_end-fog_start) - dist/(fog_end-fog_start) + ; which can be expressed with a single mad instruction! + + ; Compute |projPos| + local( $tmp ); + &AllocateRegister( \$tmp ); + + if( $g_dx9 ) + { + mad $tmp, -$projPos.w, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max $dest, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$projPos.w, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max $dest.x, $tmp.x, $cFogMaxDensity + } + + &FreeRegister( \$tmp ); +} + +sub WaterRangeFog +{ + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + + ; only $worldPos.z is used out of worldPos + local( $worldPos ) = shift; + local( $projPos ) = shift; + + local( $tmp ); + &AllocateRegister( \$tmp ); + + ; This is simple similar triangles. Imagine a line passing from the point directly vertically + ; and another line passing from the point to the eye position. + ; Let d = total distance from point to the eye + ; Let h = vertical distance from the point to the eye + ; Let hw = vertical distance from the point to the water surface + ; Let dw = distance from the point to a point on the water surface that lies along the ray from point to eye + ; Therefore d/h = dw/hw by similar triangles, or dw = d * hw / h. + ; d = |projPos|, h = eyepos.z - worldPos.z, hw = waterheight.z - worldPos.z, dw = what we solve for + + ; Now, tmp.x = hw, and tmp.y = h + add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z + + ; if $tmp.x < 0, then set it to 0 + ; This is the equivalent of moving the vert to the water surface if it's above the water surface + max $tmp.x, $tmp.x, $cZero + + ; Compute 1 / |projPos| = 1/d + dp3 $tmp.z, $projPos.xyw, $projPos.xyw + rsq $tmp.z, $tmp.z + + ; Now we have h/d + mul $tmp.z, $tmp.z, $tmp.y + + ; Now we have d/h + rcp $tmp.w, $tmp.z + + ; We finally have d * hw / h + ; $tmp.w is now the distance that we see through water. + mul $tmp.w, $tmp.x, $tmp.w + + if( $g_dx9 ) + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max oFog, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max oFog.x, $tmp.x, $cFogMaxDensity + } + + &FreeRegister( \$tmp ); +} + +sub WaterDepthFog +{ + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + + ; only $worldPos.z is used out of worldPos + local( $worldPos ) = shift; + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + local( $tmp ); + &AllocateRegister( \$tmp ); + + ; This is simple similar triangles. Imagine a line passing from the point directly vertically + ; and another line passing from the point to the eye position. + ; Let d = total distance from point to the eye + ; Let h = vertical distance from the point to the eye + ; Let hw = vertical distance from the point to the water surface + ; Let dw = distance from the point to a point on the water surface that lies along the ray from point to eye + ; Therefore d/h = dw/hw by similar triangles, or dw = d * hw / h. + ; d = projPos.w, h = eyepos.z - worldPos.z, hw = waterheight.z - worldPos.z, dw = what we solve for + + ; Now, tmp.x = hw, and tmp.y = h + add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z + + ; if $tmp.x < 0, then set it to 0 + ; This is the equivalent of moving the vert to the water surface if it's above the water surface + max $tmp.x, $tmp.x, $cZero + + ; Now we have 1/h + rcp $tmp.z, $tmp.y + + ; Now we have d/h + mul $tmp.w, $projPos.w, $tmp.z + + ; We finally have d * hw / h + ; $tmp.w is now the distance that we see through water. + mul $tmp.w, $tmp.x, $tmp.w + + if( $g_dx9 ) + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max $dest, $tmp.x, $cZero + } + else + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max $dest.x, $tmp.x, $cZero + } + + &FreeRegister( \$tmp ); +} + + +;------------------------------------------------------------------------------ +; Main fogging routine +;------------------------------------------------------------------------------ +sub CalcFog +{ + if( !defined $DOWATERFOG ) + { + die "CalcFog called without using \$DOWATERFOG\n"; + } + my $fogType; + if( $DOWATERFOG == 0 ) + { + $fogType = "rangefog"; + } + else + { + $fogType = "heightfog"; + } + +# print "\$fogType = $fogType\n"; + + ; CalcFog + local( $worldPos ) = shift; + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + if( $fogType eq "rangefog" ) + { + &DepthFog( $projPos, $dest ); + } + elsif( $fogType eq "heightfog" ) + { + &WaterDepthFog( $worldPos, $projPos, $dest ); + } + else + { + die; + } +} + +sub CalcRangeFog +{ + ; CalcFog + local( $worldPos ) = shift; + local( $projPos ) = shift; + + if( $DOWATERFOG == 0 ) + { + &RangeFog( $projPos ); + } + elsif( $DOWATERFOG == 1 ) + { + &WaterRangeFog( $worldPos, $projPos ); + } + else + { + die; + } +} + +sub GammaToLinear +{ + local( $gamma ) = shift; + local( $linear ) = shift; + + local( $tmp ); + &AllocateRegister( \$tmp ); + + ; Is rcp more expensive than just storing 2.2 somewhere and doing a mov? + rcp $gamma.w, $cOOGamma ; $gamma.w = 2.2 + lit $linear.z, $gamma.zzzw ; r0.z = linear blue + lit $tmp.z, $gamma.yyyw ; r2.z = linear green + mov $linear.y, $tmp.z ; r0.y = linear green + lit $tmp.z, $gamma.xxxw ; r2.z = linear red + mov $linear.x, $tmp.z ; r0.x = linear red + + &FreeRegister( \$tmp ); +} + +sub LinearToGamma +{ + local( $linear ) = shift; + local( $gamma ) = shift; + + local( $tmp ); + &AllocateRegister( \$tmp ); + + mov $linear.w, $cOOGamma ; $linear.w = 1.0/2.2 + lit $gamma.z, $linear.zzzw ; r0.z = gamma blue + lit $tmp.z, $linear.yyyw ; r2.z = gamma green + mov $gamma.y, $tmp.z ; r0.y = gamma green + lit $tmp.z, $linear.xxxw ; r2.z = gamma red + mov $gamma.x, $tmp.z ; r0.x = gamma red + + &FreeRegister( \$tmp ); +} + +sub ComputeReflectionVector +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $reflectionVector ) = shift; + + local( $vertToEye ); &AllocateRegister( \$vertToEye ); + local( $tmp ); &AllocateRegister( \$tmp ); + + ; compute reflection vector r = 2 * (n dot v) n - v + sub $vertToEye.xyz, $cEyePos.xyz, $worldPos ; $tmp1 = v = c - p + dp3 $tmp, $worldNormal, $vertToEye ; $tmp = n dot v + mul $tmp.xyz, $tmp.xyz, $worldNormal ; $tmp = (n dot v ) n + mad $reflectionVector.xyz, $tmp, $cTwo, -$vertToEye + + &FreeRegister( \$vertToEye ); + &FreeRegister( \$tmp ); +} + +sub ComputeSphereMapTexCoords +{ + local( $reflectionVector ) = shift; + local( $sphereMapTexCoords ) = shift; + + local( $tmp ); &AllocateRegister( \$tmp ); + + ; transform reflection vector into view space + dp3 $tmp.x, $reflectionVector, $cViewModel0 + dp3 $tmp.y, $reflectionVector, $cViewModel1 + dp3 $tmp.z, $reflectionVector, $cViewModel2 + + ; generate + add $tmp.z, $tmp.z, $cOne + + ; find 1 / the length of r2 + dp3 $tmp.w, $tmp, $tmp + rsq $tmp.w, $tmp.w + + ; r1 = r2/|r2| + 1 + mad $tmp.xy, $tmp.w, $tmp, $cOne + mul $sphereMapTexCoords.xy, $tmp.xy, $cHalf + + &FreeRegister( \$tmp ); +} + +sub SkinPosition +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (4 instructions) + ; + ; Transform position into world space + ; position + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + } + else + { + ; + ; 3 bone skinning (19 instructions) + ; + local( $boneIndices ); + local( $blendedMatrix0 ); + local( $blendedMatrix1 ); + local( $blendedMatrix2 ); + local( $localPos ); + &AllocateRegister( \$boneIndices ); + &AllocateRegister( \$blendedMatrix0 ); + &AllocateRegister( \$blendedMatrix1 ); + &AllocateRegister( \$blendedMatrix2 ); + + ; Transform position into world space using all bones + ; denormalize d3dcolor to matrix index + mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; r11 = boneindices at this point + ; first matrix + mov a0.x, $boneIndices.z + mul $blendedMatrix0, $vBoneWeights.x, c[a0.x] + mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1] + mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2] + ; second matrix + mov a0.x, $boneIndices.y + mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2 + + ; Calculate third weight + ; compute 1-(weight1+weight2) to calculate weight2 + ; Use $boneIndices.w as a temp since we aren't using it for anything. + add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y + sub $boneIndices.w, $cOne, $boneIndices.w + + ; third matrix + mov a0.x, $boneIndices.x + mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2 + + dp4 $worldPos.x, $vPos, $blendedMatrix0 + dp4 $worldPos.y, $vPos, $blendedMatrix1 + dp4 $worldPos.z, $vPos, $blendedMatrix2 + mov $worldPos.w, $cOne + + &FreeRegister( \$boneIndices ); + &FreeRegister( \$blendedMatrix0 ); + &FreeRegister( \$blendedMatrix1 ); + &FreeRegister( \$blendedMatrix2 ); + } +} + + +sub SkinPositionAndNormal +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (13 instructions) + ; + ; Transform position + normal + tangentS + tangentT into world space + ; position + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + } + else + { + local( $boneIndices ); + local( $blendedMatrix0 ); + local( $blendedMatrix1 ); + local( $blendedMatrix2 ); + local( $localPos ); + local( $localNormal ); + local( $normalLength ); + local( $ooNormalLength ); + &AllocateRegister( \$boneIndices ); + &AllocateRegister( \$blendedMatrix0 ); + &AllocateRegister( \$blendedMatrix1 ); + &AllocateRegister( \$blendedMatrix2 ); + + ; Transform position into world space using all bones + ; denormalize d3dcolor to matrix index + mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; r11 = boneindices at this point + ; first matrix + mov a0.x, $boneIndices.z + mul $blendedMatrix0, $vBoneWeights.x, c[a0.x] + mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1] + mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2] + ; second matrix + mov a0.x, $boneIndices.y + mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2 + + ; Calculate third weight + ; compute 1-(weight1+weight2) to calculate weight2 + ; Use $boneIndices.w as a temp since we aren't using it for anything. + add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y + sub $boneIndices.w, $cOne, $boneIndices.w + + ; third matrix + mov a0.x, $boneIndices.x + mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2 + + dp4 $worldPos.x, $vPos, $blendedMatrix0 + dp4 $worldPos.y, $vPos, $blendedMatrix1 + dp4 $worldPos.z, $vPos, $blendedMatrix2 + mov $worldPos.w, $cOne + + ; normal + dp3 $worldNormal.x, $vNormal, $blendedMatrix0 + dp3 $worldNormal.y, $vNormal, $blendedMatrix1 + dp3 $worldNormal.z, $vNormal, $blendedMatrix2 + + &FreeRegister( \$boneIndices ); + &FreeRegister( \$blendedMatrix0 ); + &FreeRegister( \$blendedMatrix1 ); + &FreeRegister( \$blendedMatrix2 ); + } +} + +sub SkinPositionNormalAndTangentSpace +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $worldTangentS ) = shift; + local( $worldTangentT ) = shift; + local( $userData ); + local( $localPos ); + local( $localNormal ); + local( $normalLength ); + local( $ooNormalLength ); + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# &AllocateRegister( \$userData ); +# ; remap compressed range [0..1] to [-1..1] +# mad $userData, $vUserData, $cTwo, -$cOne +# } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (13 instructions) + ; + ; Transform position + normal + tangentS + tangentT into world space + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# ; tangents +# dp3 $worldTangentS.x, $userData, $cModel0 +# dp3 $worldTangentS.y, $userData, $cModel1 +# dp3 $worldTangentS.z, $userData, $cModel2 +# +# ; calculate tangent t via cross( N, S ) * S[3] +# &Cross( $worldTangentT, $worldNormal, $worldTangentS ); +# mul $worldTangentT.xyz, $userData.w, $worldTangentT.xyz +# } +# else + { + ; tangents + dp3 $worldTangentS.x, $vUserData, $cModel0 + dp3 $worldTangentS.y, $vUserData, $cModel1 + dp3 $worldTangentS.z, $vUserData, $cModel2 + + ; calculate tangent t via cross( N, S ) * S[3] + &Cross( $worldTangentT, $worldNormal, $worldTangentS ); + mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz + } + } + else + { + local( $boneIndices ); + local( $blendedMatrix0 ); + local( $blendedMatrix1 ); + local( $blendedMatrix2 ); + &AllocateRegister( \$boneIndices ); + &AllocateRegister( \$blendedMatrix0 ); + &AllocateRegister( \$blendedMatrix1 ); + &AllocateRegister( \$blendedMatrix2 ); + + ; Transform position into world space using all bones + ; denormalize d3dcolor to matrix index + mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; r11 = boneindices at this point + ; first matrix + mov a0.x, $boneIndices.z + mul $blendedMatrix0, $vBoneWeights.x, c[a0.x] + mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1] + mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2] + ; second matrix + mov a0.x, $boneIndices.y + mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2 + + ; Calculate third weight + ; compute 1-(weight1+weight2) to calculate weight2 + ; Use $boneIndices.w as a temp since we aren't using it for anything. + add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y + sub $boneIndices.w, $cOne, $boneIndices.w + + ; third matrix + mov a0.x, $boneIndices.x + mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0 + mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1 + mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2 + + ; position + dp4 $worldPos.x, $vPos, $blendedMatrix0 + dp4 $worldPos.y, $vPos, $blendedMatrix1 + dp4 $worldPos.z, $vPos, $blendedMatrix2 + mov $worldPos.w, $cOne + + ; normal + dp3 $worldNormal.x, $vNormal, $blendedMatrix0 + dp3 $worldNormal.y, $vNormal, $blendedMatrix1 + dp3 $worldNormal.z, $vNormal, $blendedMatrix2 + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# ; tangents +# dp3 $worldTangentS.x, $userData, $blendedMatrix0 +# dp3 $worldTangentS.y, $userData, $blendedMatrix1 +# dp3 $worldTangentS.z, $userData, $blendedMatrix2 +# +# ; calculate tangent t via cross( N, S ) * S[3] +# &Cross( $worldTangentT, $worldNormal, $worldTangentS ); +# mul $worldTangentT.xyz, $userData.w, $worldTangentT.xyz +# } +# else + { + ; tangents + dp3 $worldTangentS.x, $vUserData, $blendedMatrix0 + dp3 $worldTangentS.y, $vUserData, $blendedMatrix1 + dp3 $worldTangentS.z, $vUserData, $blendedMatrix2 + + ; calculate tangent t via cross( N, S ) * S[3] + &Cross( $worldTangentT, $worldNormal, $worldTangentS ); + mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz + } + + &FreeRegister( \$boneIndices ); + &FreeRegister( \$blendedMatrix0 ); + &FreeRegister( \$blendedMatrix1 ); + &FreeRegister( \$blendedMatrix2 ); + } + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# &FreeRegister( \$userData ); +# } +} + +sub ColorClamp +{ + ; ColorClamp; stomps $color.w + local( $color ) = shift; + local( $dst ) = shift; + + ; Get the max of RGB and stick it in W + max $color.w, $color.x, $color.y + max $color.w, $color.w, $color.z + + ; get the greater of one and the max color. + max $color.w, $color.w, $cOne + + rcp $color.w, $color.w + mul $dst.xyz, $color.w, $color.xyz +} + +sub AmbientLight +{ + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + ; Ambient lighting + &AllocateRegister( \$nSquared ); + &AllocateRegister( \$isNegative ); + + mul $nSquared.xyz, $worldNormal.xyz, $worldNormal.xyz ; compute n times n + slt $isNegative.xyz, $worldNormal.xyz, $cZero ; Figure out whether each component is >0 + mov a0.x, $isNegative.x + if( $add ) + { + mad $linearColor.xyz, $nSquared.x, c[a0.x + $cAmbientColorPosXOffset], $linearColor ; $linearColor = normal[0]*normal[0] * box color of appropriate x side + } + else + { + mul $linearColor.xyz, $nSquared.x, c[a0.x + $cAmbientColorPosXOffset] ; $linearColor = normal[0]*normal[0] * box color of appropriate x side + } + mov a0.x, $isNegative.y + mad $linearColor.xyz, $nSquared.y, c[a0.x + $cAmbientColorPosYOffset], $linearColor + mov a0.x, $isNegative.z + mad $linearColor.xyz, $nSquared.z, c[a0.x + $cAmbientColorPosZOffset], $linearColor + + &FreeRegister( \$isNegative ); + &FreeRegister( \$nSquared ); +} + +sub DirectionalLight +{ + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + &AllocateRegister( \$nDotL ); # FIXME: This only needs to be a scalar + + ; NOTE: Gotta use -l here, since light direction = -l + ; DIRECTIONAL LIGHT + ; compute n dot l + dp3 $nDotL.x, -c[a0.x + 1], $worldNormal + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $nDotL.x, $nDotL.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $nDotL.x, $nDotL.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5)^2 + mul $nDotL.x, $nDotL.x, $nDotL.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + if( $add ) + { + mad $linearColor.xyz, c[a0.x], $nDotL.x, $linearColor + } + else + { + mul $linearColor.xyz, c[a0.x], $nDotL.x + } + + &FreeRegister( \$nDotL ); +} + +sub PointLight +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + local( $lightDir ); + &AllocateRegister( \$lightDir ); + + ; POINT LIGHT + ; compute light direction + sub $lightDir, c[a0.x+2], $worldPos + + local( $lightDistSquared ); + local( $ooLightDist ); + &AllocateRegister( \$lightDistSquared ); + &AllocateRegister( \$ooLightDist ); + + ; normalize light direction, maintain temporaries for attenuation + dp3 $lightDistSquared, $lightDir, $lightDir + rsq $ooLightDist, $lightDistSquared.x + mul $lightDir, $lightDir, $ooLightDist.x + + local( $attenuationFactors ); + &AllocateRegister( \$attenuationFactors ); + + ; compute attenuation amount (r2 = 'd*d d*d d*d d*d', r3 = '1/d 1/d 1/d 1/d') + dst $attenuationFactors, $lightDistSquared, $ooLightDist ; r4 = ( 1, d, d*d, 1/d ) + &FreeRegister( \$lightDistSquared ); + &FreeRegister( \$ooLightDist ); + local( $attenuation ); + &AllocateRegister( \$attenuation ); + dp3 $attenuation, $attenuationFactors, c[a0.x+4] ; r3 = atten0 + d * atten1 + d*d * atten2 + + rcp $lightDir.w, $attenuation ; $lightDir.w = 1 / (atten0 + d * atten1 + d*d * atten2) + + &FreeRegister( \$attenuationFactors ); + &FreeRegister( \$attenuation ); + + local( $tmp ); + &AllocateRegister( \$tmp ); # FIXME : really only needs to be a scalar + + ; compute n dot l, fold in distance attenutation + dp3 $tmp.x, $lightDir, $worldNormal + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $tmp.x, $tmp.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $tmp.x, $tmp.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5)^2 + mul $tmp.x, $tmp.x, $tmp.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + mul $tmp.x, $tmp.x, $lightDir.w + if( $add ) + { + mad $linearColor.xyz, c[a0.x], $tmp.x, $linearColor + } + else + { + mul $linearColor.xyz, c[a0.x], $tmp.x + } + + &FreeRegister( \$lightDir ); + &FreeRegister( \$tmp ); # FIXME : really only needs to be a scalar +} + +sub SpotLight +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + local( $lightDir ); + &AllocateRegister( \$lightDir ); + + ; SPOTLIGHT + ; compute light direction + sub $lightDir, c[a0.x+2], $worldPos + + local( $lightDistSquared ); + local( $ooLightDist ); + &AllocateRegister( \$lightDistSquared ); + &AllocateRegister( \$ooLightDist ); + + ; normalize light direction, maintain temporaries for attenuation + dp3 $lightDistSquared, $lightDir, $lightDir + rsq $ooLightDist, $lightDistSquared.x + mul $lightDir, $lightDir, $ooLightDist.x + + local( $attenuationFactors ); + &AllocateRegister( \$attenuationFactors ); + + ; compute attenuation amount (r2 = 'd*d d*d d*d d*d', r3 = '1/d 1/d 1/d 1/d') + dst $attenuationFactors, $lightDistSquared, $ooLightDist ; r4 = ( 1, d, d*d, 1/d ) + + &FreeRegister( \$lightDistSquared ); + &FreeRegister( \$ooLightDist ); + local( $attenuation ); &AllocateRegister( \$attenuation ); + + dp3 $attenuation, $attenuationFactors, c[a0.x+4] ; r3 = atten0 + d * atten1 + d*d * atten2 + rcp $lightDir.w, $attenuation ; r1.w = 1 / (atten0 + d * atten1 + d*d * atten2) + + &FreeRegister( \$attenuationFactors ); + &FreeRegister( \$attenuation ); + + local( $litSrc ); &AllocateRegister( \$litSrc ); + local( $tmp ); &AllocateRegister( \$tmp ); # FIXME - only needs to be scalar + + ; compute n dot l + dp3 $litSrc.x, $worldNormal, $lightDir + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $litSrc.x, $litSrc.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $litSrc.x, $litSrc.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5) ^ 2 + mul $litSrc.x, $litSrc.x, $litSrc.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + ; compute angular attenuation + dp3 $tmp.x, c[a0.x+1], -$lightDir ; dot = -delta * spot direction + sub $litSrc.y, $tmp.x, c[a0.x+3].z ; r2.y = dot - stopdot2 + &FreeRegister( \$tmp ); + mul $litSrc.y, $litSrc.y, c[a0.x+3].w ; r2.y = (dot - stopdot2) / (stopdot - stopdot2) + mov $litSrc.w, c[a0.x+3].x ; r2.w = exponent + local( $litDst ); &AllocateRegister( \$litDst ); + lit $litDst, $litSrc ; r3.y = N dot L or 0, whichever is bigger + &FreeRegister( \$litSrc ); + ; r3.z = pow((dot - stopdot2) / (stopdot - stopdot2), exponent) + min $litDst.z, $litDst.z, $cOne ; clamp pow() to 1 + + local( $tmp1 ); &AllocateRegister( \$tmp1 ); + local( $tmp2 ); &AllocateRegister( \$tmp2 ); # FIXME - could be scalar + + ; fold in distance attenutation with other factors + mul $tmp1, c[a0.x], $lightDir.w + mul $tmp2.x, $litDst.y, $litDst.z + if( $add ) + { + mad $linearColor.xyz, $tmp1, $tmp2.x, $linearColor + } + else + { + mul $linearColor.xyz, $tmp1, $tmp2.x + } + + &FreeRegister( \$lightDir ); + &FreeRegister( \$litDst ); + &FreeRegister( \$tmp1 ); + &FreeRegister( \$tmp2 ); +} + +sub DoLight +{ + local( $lightType ) = shift; + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + local( $add ) = shift; + + if( $lightType eq "spot" ) + { + &SpotLight( $worldPos, $worldNormal, $linearColor, $add ); + } + elsif( $lightType eq "point" ) + { + &PointLight( $worldPos, $worldNormal, $linearColor, $add ); + } + elsif( $lightType eq "directional" ) + { + &DirectionalLight( $worldNormal, $linearColor, $add ); + } + else + { + die "don't know about light type \"$lightType\"\n"; + } +} + +sub DoLighting +{ + if( !defined $LIGHT_COMBO ) + { + die "DoLighting called without using \$LIGHT_COMBO\n"; + } + if ( !defined $HALF_LAMBERT ) + { + die "DoLighting called without using \$HALF_LAMBERT\n"; + } + + my $staticLightType = $g_staticLightTypeArray[$LIGHT_COMBO]; + my $ambientLightType = $g_ambientLightTypeArray[$LIGHT_COMBO]; + my $localLightType1 = $g_localLightType1Array[$LIGHT_COMBO]; + my $localLightType2 = $g_localLightType2Array[$LIGHT_COMBO]; + +# print "\$staticLightType = $staticLightType\n"; +# print "\$ambientLightType = $ambientLightType\n"; +# print "\$localLightType1 = $localLightType1\n"; +# print "\$localLightType2 = $localLightType2\n"; + + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + + ; special case for no lighting + if( $staticLightType eq "none" && $ambientLightType eq "none" && + $localLightType1 eq "none" && $localLightType2 eq "none" ) + { + ; Have to write something here since debug d3d runtime will barf otherwise. + mov oD0, $cOne + return; + } + + ; special case for static lighting only + ; Don't need to bother converting to linear space in this case. + if( $staticLightType eq "static" && $ambientLightType eq "none" && + $localLightType1 eq "none" && $localLightType2 eq "none" ) + { + mov oD0, $vSpecular + return; + } + + alloc $linearColor + alloc $gammaColor + + local( $add ) = 0; + if( $staticLightType eq "static" ) + { + ; The static lighting comes in in gamma space and has also been premultiplied by $cOverbrightFactor + ; need to get it into + ; linear space so that we can do adds. + rcp $gammaColor.w, $cOverbrightFactor + mul $gammaColor.xyz, $vSpecular, $gammaColor.w + &GammaToLinear( $gammaColor, $linearColor ); + $add = 1; + } + + if( $ambientLightType eq "ambient" ) + { + &AmbientLight( $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType1 ne "none" ) + { + mov a0.x, $cLight0Offset + &DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType2 ne "none" ) + { + mov a0.x, $cLight1Offset + &DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } + + ;------------------------------------------------------------------------------ + ; Output color (gamma correction) + ;------------------------------------------------------------------------------ + + &LinearToGamma( $linearColor, $gammaColor ); + if( 0 ) + { + mul oD0.xyz, $gammaColor.xyz, $cOverbrightFactor + } + else + { + mul $gammaColor.xyz, $gammaColor.xyz, $cOverbrightFactor + &ColorClamp( $gammaColor, "oD0" ); + } + +; mov oD0.xyz, $linearColor + mov oD0.w, $cOne ; make sure all components are defined + + free $linearColor + free $gammaColor +} + +sub DoDynamicLightingToLinear +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + + if( !defined $LIGHT_COMBO ) + { + die "DoLighting called without using \$LIGHT_COMBO\n"; + } + if ( !defined $HALF_LAMBERT ) + { + die "DoLighting called without using \$HALF_LAMBERT\n"; + } + + my $staticLightType = $g_staticLightTypeArray[$LIGHT_COMBO]; + my $ambientLightType = $g_ambientLightTypeArray[$LIGHT_COMBO]; + my $localLightType1 = $g_localLightType1Array[$LIGHT_COMBO]; + my $localLightType2 = $g_localLightType2Array[$LIGHT_COMBO]; + + # No lights at all. . note that we don't even consider static lighting here. + if( $ambientLightType eq "none" && + $localLightType1 eq "none" && $localLightType2 eq "none" ) + { + mov $linearColor, $cZero + return; + } + + local( $add ) = 0; + if( $ambientLightType eq "ambient" ) + { + &AmbientLight( $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType1 ne "none" ) + { + mov a0.x, $cLight0Offset + &DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType2 ne "none" ) + { + mov a0.x, $cLight1Offset + &DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } +} + +sub NotImplementedYet +{ + &AllocateRegister( \$projPos ); + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 + mov oPos, $projPos + &FreeRegister( \$projPos ); + exit; +} diff --git a/sp/src/materialsystem/stdshaders/shader_constant_register_map.h b/sp/src/materialsystem/stdshaders/shader_constant_register_map.h new file mode 100644 index 00000000..485bb7c4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/shader_constant_register_map.h @@ -0,0 +1,81 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Provide convenient mapping for shader constants +// +// $NoKeywords: $ +//============================================================================= + +#ifndef C_CODE_HACK +#include "common_vertexlitgeneric_dx9.h" +#endif + +#define PSREG_SELFILLUMTINT PSREG_CONSTANT_00 +#define PSREG_DIFFUSE_MODULATION PSREG_CONSTANT_01 +#define PSREG_ENVMAP_TINT__SHADOW_TWEAKS PSREG_CONSTANT_02 +#define PSREG_SELFILLUM_SCALE_BIAS_EXP PSREG_CONSTANT_03 +#define PSREG_AMBIENT_CUBE PSREG_CONSTANT_04 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_05 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_06 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_07 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_08 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_09 +#define PSREG_ENVMAP_FRESNEL__SELFILLUMMASK PSREG_CONSTANT_10 +#define PSREG_EYEPOS_SPEC_EXPONENT PSREG_CONSTANT_11 +#define PSREG_FOG_PARAMS PSREG_CONSTANT_12 +#define PSREG_FLASHLIGHT_ATTENUATION PSREG_CONSTANT_13 +#define PSREG_FLASHLIGHT_POSITION_RIM_BOOST PSREG_CONSTANT_14 +#define PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_15 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_16 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_17 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_18 +#define PSREG_FRESNEL_SPEC_PARAMS PSREG_CONSTANT_19 +#define PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_20 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_21 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_22 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_23 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_24 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_25 +#define PSREG_SPEC_RIM_PARAMS PSREG_CONSTANT_26 +// #define **free** PSREG_CONSTANT_27 //actually using this often blows constant limits, since literals have to get stuffed somewhere... +#define PSREG_FLASHLIGHT_COLOR PSREG_CONSTANT_28 +#define PSREG_LINEAR_FOG_COLOR PSREG_CONSTANT_29 +#define PSREG_LIGHT_SCALE PSREG_CONSTANT_30 +#define PSREG_FLASHLIGHT_SCREEN_SCALE PSREG_CONSTANT_31 +// --- End of ps_2_0 and ps_2_b constants --- + + +#ifndef C_CODE_HACK +//for fxc code, map the constants to register names. +#define PSREG_CONSTANT_00 c0 +#define PSREG_CONSTANT_01 c1 +#define PSREG_CONSTANT_02 c2 +#define PSREG_CONSTANT_03 c3 +#define PSREG_CONSTANT_04 c4 +#define PSREG_CONSTANT_05 c5 +#define PSREG_CONSTANT_06 c6 +#define PSREG_CONSTANT_07 c7 +#define PSREG_CONSTANT_08 c8 +#define PSREG_CONSTANT_09 c9 +#define PSREG_CONSTANT_10 c10 +#define PSREG_CONSTANT_11 c11 +#define PSREG_CONSTANT_12 c12 +#define PSREG_CONSTANT_13 c13 +#define PSREG_CONSTANT_14 c14 +#define PSREG_CONSTANT_15 c15 +#define PSREG_CONSTANT_16 c16 +#define PSREG_CONSTANT_17 c17 +#define PSREG_CONSTANT_18 c18 +#define PSREG_CONSTANT_19 c19 +#define PSREG_CONSTANT_20 c20 +#define PSREG_CONSTANT_21 c21 +#define PSREG_CONSTANT_22 c22 +#define PSREG_CONSTANT_23 c23 +#define PSREG_CONSTANT_24 c24 +#define PSREG_CONSTANT_25 c25 +#define PSREG_CONSTANT_26 c26 +#define PSREG_CONSTANT_27 c27 +#define PSREG_CONSTANT_28 c28 +#define PSREG_CONSTANT_29 c29 +#define PSREG_CONSTANT_30 c30 +#define PSREG_CONSTANT_31 c31 +#endif diff --git a/sp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt b/sp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt new file mode 100644 index 00000000..f70ae0a2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt @@ -0,0 +1,11 @@ +// +// Standard shaders collection +// +// These shaders are compiled as the following shader models: +// _ps20.vcs +// _ps20b.vcs +// _vs20.vcs +// + +example_model_ps20b.fxc +example_model_vs20.fxc diff --git a/sp/src/materialsystem/stdshaders/stdshader_dx9_30.txt b/sp/src/materialsystem/stdshaders/stdshader_dx9_30.txt new file mode 100644 index 00000000..5a09a37b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/stdshader_dx9_30.txt @@ -0,0 +1,10 @@ +// +// vs 3.0 ps 3.0 shaders collection +// +// These shaders are forced to compile as shader model 3.0 +// using the new compiler. +// _ps30.vcs +// _vs30.vcs +// + +// There are no examples of such shaders in the SDK, but add yours here. diff --git a/sp/src/public/appframework/ilaunchermgr.h b/sp/src/public/appframework/ilaunchermgr.h index 5d38b15a..7fa5dc76 100644 --- a/sp/src/public/appframework/ilaunchermgr.h +++ b/sp/src/public/appframework/ilaunchermgr.h @@ -10,7 +10,7 @@ #pragma once #endif -#if defined( USE_SDL ) || defined( OSX ) +#if defined( USE_SDL ) #include "tier0/threadtools.h" #include "appframework/IAppSystem.h" @@ -29,18 +29,12 @@ class CShowPixelsParams; #endif // if you rev this version also update materialsystem/cmaterialsystem.cpp CMaterialSystem::Connect as it defines the string directly -#if defined( USE_SDL ) - #define SDLMGR_INTERFACE_VERSION "SDLMgrInterface001" -#elif defined( OSX ) - #define COCOAMGR_INTERFACE_VERSION "CocoaMgrInterface006" -#endif +#define SDLMGR_INTERFACE_VERSION "SDLMgrInterface001" class CCocoaEvent; class CStackCrawlParams; -#if defined( USE_SDL ) typedef struct SDL_Cursor SDL_Cursor; -#endif class ILauncherMgr : public IAppSystem { @@ -103,11 +97,9 @@ public: virtual void *GetWindowRef() = 0; virtual void SetMouseVisible( bool bState ) = 0; -#ifdef USE_SDL virtual void SetMouseCursor( SDL_Cursor *hCursor ) = 0; virtual void SetForbidMouseGrab( bool bForbidMouseGrab ) = 0; virtual void OnFrameRendered() = 0; -#endif virtual void SetGammaRamp( const uint16 *pRed, const uint16 *pGreen, const uint16 *pBlue ) = 0; @@ -163,6 +155,6 @@ public: int m_MouseButton; // which of the CocoaMouseButton_t buttons this is for from above }; -#endif // USE_SDL || OSX +#endif // defined( USE_SDL ) #endif // ILAUNCHERMGR_H diff --git a/sp/src/public/cdll_int.h b/sp/src/public/cdll_int.h index 1757d5d7..1801c383 100644 --- a/sp/src/public/cdll_int.h +++ b/sp/src/public/cdll_int.h @@ -525,7 +525,7 @@ public: virtual void SetGamestatsData( CGamestatsData *pGamestatsData ) = 0; virtual CGamestatsData *GetGamestatsData() = 0; -#if defined( USE_SDL ) || defined( OSX ) +#if defined( USE_SDL ) // we need to pull delta's from the cocoa mgr, the engine vectors this for us virtual void GetMouseDelta( int &x, int &y, bool bIgnoreNextMouseDelta = false ) = 0; #endif diff --git a/sp/src/public/dt_common.h b/sp/src/public/dt_common.h index e1d00ae4..d899ee80 100644 --- a/sp/src/public/dt_common.h +++ b/sp/src/public/dt_common.h @@ -143,7 +143,7 @@ public: switch ( m_Type ) { case DPT_Int : - Q_snprintf( text, sizeof(text), "%ld", m_Int ); + Q_snprintf( text, sizeof(text), "%i", m_Int ); break; case DPT_Float : Q_snprintf( text, sizeof(text), "%.3f", m_Float ); @@ -190,7 +190,7 @@ public: union { float m_Float; - long m_Int; + int m_Int; const char *m_pString; void *m_pData; // For DataTables. #if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! diff --git a/sp/src/public/eiface.h b/sp/src/public/eiface.h index ea0a4ab7..821df8d6 100644 --- a/sp/src/public/eiface.h +++ b/sp/src/public/eiface.h @@ -407,6 +407,9 @@ public: // Server version from the steam.inf, this will be compared to the GC version virtual int GetServerVersion() const = 0; + + // Get sv.GetTime() + virtual float GetServerTime() const = 0; }; diff --git a/sp/src/public/engine/ivdebugoverlay.h b/sp/src/public/engine/ivdebugoverlay.h index 51aeafd1..0b24c777 100644 --- a/sp/src/public/engine/ivdebugoverlay.h +++ b/sp/src/public/engine/ivdebugoverlay.h @@ -25,7 +25,7 @@ class Vector; // When used as a duration by a server-side NDebugOverlay:: call, // causes the overlay to persist until the next server update. -#define NDEBUG_PERSIST_TILL_NEXT_SERVER (0.01023f) +#define NDEBUG_PERSIST_TILL_NEXT_SERVER (0.0f) class OverlayText_t; diff --git a/sp/src/public/headtrack/iheadtrack.h b/sp/src/public/headtrack/iheadtrack.h deleted file mode 100644 index 4f5fcced..00000000 --- a/sp/src/public/headtrack/iheadtrack.h +++ /dev/null @@ -1,84 +0,0 @@ -//===== Copyright (c), Valve Corporation, All rights reserved. ======// -// -// Purpose: Contains the IHeadTrack interface, which is implemented in headtrack.dll -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef IHEADTRACK_H -#define IHEADTRACK_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include "tier1/refcount.h" -#include "appframework/IAppSystem.h" -#include "mathlib/vmatrix.h" -#include "view_shared.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// important enumeration -//----------------------------------------------------------------------------- - -// NOTE NOTE NOTE!!!! If you up this, grep for "NEW_INTERFACE" to see if there is anything -// waiting to be enabled during an interface revision. -#define HEAD_TRACK_INTERFACE_VERSION "VHeadTrack001" - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -abstract_class IHeadTrack : public IAppSystem -{ -public: - virtual ~IHeadTrack() {} - - // Placeholder for API revision - virtual bool Connect( CreateInterfaceFn factory ) = 0; - virtual void Disconnect() = 0; - virtual void *QueryInterface( const char *pInterfaceName ) = 0; - virtual InitReturnVal_t Init() = 0; - virtual void Shutdown() = 0; - - //----------------------------------------------------------------------------- - // Tracking section - //----------------------------------------------------------------------------- - // All methods return true on success, false on failure. - - // Also sets the zero pose - virtual bool ResetTracking() = 0; - - // Set the current pose as the "zero" - virtual bool SetCurrentCameraAsZero() = 0; - - // Raw interfaces - one one or other of these, not both (GetCameraPoseZeroFromCurrent calls GetCameraFromWorldPose ); - virtual bool GetCameraFromWorldPose ( VMatrix *pResultCameraFromWorldPose, VMatrix *pResultCameraFromWorldPoseUnpredicted = NULL, double *pflAcquireTime = NULL ) = 0; - virtual bool GetCameraPoseZeroFromCurrent ( VMatrix *pResultMatrix ) = 0; - - // All-in-one interfaces (they call GetCameraPoseZeroFromCurrent) - // Grabs the current tracking data and sets up state for the Override* calls. - virtual bool ProcessCurrentTrackingState ( float PlayerGameFov ) = 0; - - // Performs the distortion post-processing. - virtual bool DoDistortionProcessing ( const vrect_t *SrcRect ) = 0; - -}; - - - -//----------------------------------------------------------------------------- - -extern IHeadTrack *g_pHeadTrack; - -inline bool UseHeadTracking() -{ - return g_pHeadTrack != NULL; -} -#endif // IHEADTRACK_H diff --git a/sp/src/public/materialsystem/materialsystem_config.h b/sp/src/public/materialsystem/materialsystem_config.h index 1cdca782..1a8d1d1d 100644 --- a/sp/src/public/materialsystem/materialsystem_config.h +++ b/sp/src/public/materialsystem/materialsystem_config.h @@ -32,6 +32,7 @@ enum MaterialSystem_Config_Flags_t MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE = ( 1 << 13 ), MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION = ( 1 << 14 ), MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS = ( 1 << 15 ), + MATSYS_VIDCFG_FLAGS_DISABLE_PHONG = ( 1 << 16 ), }; struct MaterialSystemHardwareIdentifier_t @@ -62,6 +63,7 @@ struct MaterialSystem_Config_t bool LimitWindowedSize() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE ) != 0; } bool ScaleToOutputResolution() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION ) != 0; } bool UsingMultipleWindows() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS ) != 0; } + bool UsePhong() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_PHONG ) == 0; } bool ShadowDepthTexture() const { return m_bShadowDepthTexture; } bool MotionBlur() const { return m_bMotionBlur; } bool SupportFlashlight() const { return m_bSupportFlashlight; } @@ -157,6 +159,7 @@ struct MaterialSystem_Config_t SetFlag( MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE, false ); SetFlag( MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION, false ); SetFlag( MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS, false ); + SetFlag( MATSYS_VIDCFG_FLAGS_DISABLE_PHONG, false ); m_VideoMode.m_Width = 640; m_VideoMode.m_Height = 480; diff --git a/sp/src/public/mathlib/mathlib.h b/sp/src/public/mathlib/mathlib.h index 83fdb6a0..e1873cd0 100644 --- a/sp/src/public/mathlib/mathlib.h +++ b/sp/src/public/mathlib/mathlib.h @@ -97,7 +97,9 @@ private: #ifdef DEBUG // stop crashing edit-and-continue FORCEINLINE float clamp( float val, float minVal, float maxVal ) { - if( val < minVal ) + if ( maxVal < minVal ) + return maxVal; + else if( val < minVal ) return minVal; else if( val > maxVal ) return maxVal; @@ -115,8 +117,8 @@ FORCEINLINE float clamp( float val, float minVal, float maxVal ) _mm_load_ss(&minVal) ), _mm_load_ss(&maxVal) ) ); #else - val = fpmin(maxVal, val); val = fpmax(minVal, val); + val = fpmin(maxVal, val); #endif return val; } @@ -128,7 +130,9 @@ FORCEINLINE float clamp( float val, float minVal, float maxVal ) template< class T > inline T clamp( T const &val, T const &minVal, T const &maxVal ) { - if( val < minVal ) + if ( maxVal < minVal ) + return maxVal; + else if( val < minVal ) return minVal; else if( val > maxVal ) return maxVal; @@ -2172,9 +2176,9 @@ bool AlmostEqual(float a, float b, int maxUlps = 10); inline bool AlmostEqual( const Vector &a, const Vector &b, int maxUlps = 10) { - return AlmostEqual( a.x, a.x, maxUlps ) && - AlmostEqual( a.y, a.y, maxUlps ) && - AlmostEqual( a.z, a.z, maxUlps ); + return AlmostEqual( a.x, b.x, maxUlps ) && + AlmostEqual( a.y, b.y, maxUlps ) && + AlmostEqual( a.z, b.z, maxUlps ); } diff --git a/sp/src/public/optimize.h b/sp/src/public/optimize.h index b473a65d..b71dc895 100644 --- a/sp/src/public/optimize.h +++ b/sp/src/public/optimize.h @@ -226,7 +226,7 @@ struct FileHeader_t int maxBonesPerVert; // must match checkSum in the .mdl - long checkSum; + int checkSum; int numLODs; // garymcthack - this is also specified in ModelHeader_t and should match diff --git a/sp/src/public/renderparm.h b/sp/src/public/renderparm.h index 32c0fbc0..91c9cfd5 100644 --- a/sp/src/public/renderparm.h +++ b/sp/src/public/renderparm.h @@ -26,6 +26,7 @@ enum RenderParamVector_t VECTOR_RENDERPARM_HMDWARP_GROW_OUTIN, VECTOR_RENDERPARM_HMDWARP_GROW_ABOVEBELOW, VECTOR_RENDERPARM_HMDWARP_ASPECT, + INT_RENDERPARM_DISTORTION_TYPE, MAX_VECTOR_RENDER_PARMS = 20 }; diff --git a/sp/src/public/steam/steam_api.h b/sp/src/public/steam/steam_api.h index fe021f80..e16f226b 100644 --- a/sp/src/public/steam/steam_api.h +++ b/sp/src/public/steam/steam_api.h @@ -512,8 +512,8 @@ inline bool CSteamAPIContext::Init() #if defined(USE_BREAKPAD_HANDLER) || defined(STEAM_API_EXPORTS) // this should be called before the game initialized the steam APIs -// pchDate should be of the format "Mmm dd yyyy" (such as from the __DATE__ macro ) -// pchTime should be of the format "hh:mm:ss" (such as from the __TIME__ macro ) +// pchDate should be of the format "Mmm dd yyyy" (such as from the __DATE __ macro ) +// pchTime should be of the format "hh:mm:ss" (such as from the __TIME __ macro ) // bFullMemoryDumps (Win32 only) -- writes out a uuid-full.dmp in the client/dumps folder // pvContext-- can be NULL, will be the void * context passed into m_pfnPreMinidumpCallback // PFNPreMinidumpCallback m_pfnPreMinidumpCallback -- optional callback which occurs just before a .dmp file is written during a crash. Applications can hook this to allow adding additional information into the .dmp comment stream. diff --git a/sp/src/public/studio.h b/sp/src/public/studio.h index 7770c2af..9b58ab0c 100644 --- a/sp/src/public/studio.h +++ b/sp/src/public/studio.h @@ -1816,7 +1816,7 @@ struct vertexFileHeader_t DECLARE_BYTESWAP_DATADESC(); int id; // MODEL_VERTEX_FILE_ID int version; // MODEL_VERTEX_FILE_VERSION - long checksum; // same as studiohdr_t, ensures sync + int checksum; // same as studiohdr_t, ensures sync int numLODs; // num of valid lods int numLODVertexes[MAX_NUM_LODS]; // num verts for desired root lod int numFixups; // num of vertexFileFixup_t @@ -1991,7 +1991,7 @@ struct studiohdr_t int id; int version; - long checksum; // this has to be the same in the phy and vtx files to load! + int checksum; // this has to be the same in the phy and vtx files to load! inline const char * pszName( void ) const { if (studiohdr2index && pStudioHdr2()->pszName()) return pStudioHdr2()->pszName(); else return name; } char name[64]; diff --git a/sp/src/public/studio_virtualmodel.cpp b/sp/src/public/studio_virtualmodel.cpp index 748ed3b2..269e7cdf 100644 --- a/sp/src/public/studio_virtualmodel.cpp +++ b/sp/src/public/studio_virtualmodel.cpp @@ -572,4 +572,23 @@ void virtualmodel_t::AppendIKLocks( int group, const studiohdr_t *pStudioHdr ) } m_iklock = iklock; + + // copy knee directions for uninitialized knees + if ( group != 0 ) + { + studiohdr_t *pBaseHdr = (studiohdr_t *)m_group[ 0 ].GetStudioHdr(); + if ( pStudioHdr->numikchains == pBaseHdr->numikchains ) + { + for (j = 0; j < pStudioHdr->numikchains; j++) + { + if ( pBaseHdr->pIKChain( j )->pLink(0)->kneeDir.LengthSqr() == 0.0f ) + { + if ( pStudioHdr->pIKChain( j )->pLink(0)->kneeDir.LengthSqr() > 0.0f ) + { + pBaseHdr->pIKChain( j )->pLink(0)->kneeDir = pStudioHdr->pIKChain( j )->pLink(0)->kneeDir; + } + } + } + } + } } diff --git a/sp/src/public/tier0/memalloc.h b/sp/src/public/tier0/memalloc.h index 52578760..2840d095 100644 --- a/sp/src/public/tier0/memalloc.h +++ b/sp/src/public/tier0/memalloc.h @@ -535,7 +535,7 @@ inline void MemAlloc_GlobalMemoryStatus( size_t *pusedMemory, size_t *pfreeMemor *pusedMemory = 0; *pfreeMemory = 0; } -#define MemAlloc_MemoryAllocFailed() 1 +#define MemAlloc_MemoryAllocFailed() 0 #define MemAlloc_GetDebugInfoSize() 0 #define MemAlloc_SaveDebugInfo( pvDebugInfo ) ((void)0) diff --git a/sp/src/public/tier0/platform.h b/sp/src/public/tier0/platform.h index 914cd39a..38e6b563 100644 --- a/sp/src/public/tier0/platform.h +++ b/sp/src/public/tier0/platform.h @@ -1085,7 +1085,7 @@ PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode(); PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded. -PLATFORM_INTERFACE unsigned long Plat_MSTime(); // Time in milliseconds. +PLATFORM_INTERFACE unsigned int Plat_MSTime(); // Time in milliseconds. PLATFORM_INTERFACE char * Plat_asctime( const struct tm *tm, char *buf ); PLATFORM_INTERFACE char * Plat_ctime( const time_t *timep, char *buf, size_t bufsize ); PLATFORM_INTERFACE struct tm * Plat_gmtime( const time_t *timep, struct tm *result ); diff --git a/sp/src/public/tier1/checksum_crc.h b/sp/src/public/tier1/checksum_crc.h index a8ef71e5..130577ee 100644 --- a/sp/src/public/tier1/checksum_crc.h +++ b/sp/src/public/tier1/checksum_crc.h @@ -10,7 +10,7 @@ #pragma once #endif -typedef unsigned long CRC32_t; +typedef unsigned int CRC32_t; void CRC32_Init( CRC32_t *pulCRC ); void CRC32_ProcessBuffer( CRC32_t *pulCRC, const void *p, int len ); diff --git a/sp/src/public/tier1/ilocalize.h b/sp/src/public/tier1/ilocalize.h index 348986ad..a3dd6bb8 100644 --- a/sp/src/public/tier1/ilocalize.h +++ b/sp/src/public/tier1/ilocalize.h @@ -135,7 +135,7 @@ private: typedef char locchar_t; #define loc_snprintf Q_snprintf - #define loc_sprintf_safe V_snprintf_safe + #define loc_sprintf_safe V_sprintf_safe #define loc_sncat Q_strncat #define loc_scat_safe V_strcat_safe #define loc_sncpy Q_strncpy @@ -148,7 +148,7 @@ private: typedef wchar_t locchar_t; #define loc_snprintf V_snwprintf - #define loc_sprintf_safe V_snwprintf_safe + #define loc_sprintf_safe V_swprintf_safe #define loc_sncat V_wcsncat #define loc_scat_safe V_wcscat_safe #define loc_sncpy Q_wcsncpy diff --git a/sp/src/public/tier1/lzmaDecoder.h b/sp/src/public/tier1/lzmaDecoder.h index eb501c10..8aa1f2ca 100644 --- a/sp/src/public/tier1/lzmaDecoder.h +++ b/sp/src/public/tier1/lzmaDecoder.h @@ -1,4 +1,3 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// // // LZMA Decoder. Designed for run time decoding. // diff --git a/sp/src/public/tier1/strtools.h b/sp/src/public/tier1/strtools.h index 8e38436f..6089a8f4 100644 --- a/sp/src/public/tier1/strtools.h +++ b/sp/src/public/tier1/strtools.h @@ -290,7 +290,7 @@ template int V_vsprintf_safe( OUT_Z_ARRAY char (&pDe int V_snprintf( OUT_Z_CAP(maxLenInChars) char *pDest, int maxLenInChars, PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 3, 4 ); // gcc insists on only having format annotations on declarations, not definitions, which is why I have both. template int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 2, 3 ); -template int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], const char *pFormat, ... ) +template int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const char *pFormat, ... ) { va_list params; va_start( params, pFormat ); diff --git a/sp/src/public/tier1/utlrbtree.h b/sp/src/public/tier1/utlrbtree.h index b2665194..6ea22614 100644 --- a/sp/src/public/tier1/utlrbtree.h +++ b/sp/src/public/tier1/utlrbtree.h @@ -1350,7 +1350,7 @@ int CUtlRBTree::Depth( I node ) const int depthright = Depth( RightChild(node) ); int depthleft = Depth( LeftChild(node) ); - return max(depthright, depthleft) + 1; + return Max(depthright, depthleft) + 1; } diff --git a/sp/src/public/togl/glfuncs.inl b/sp/src/public/togl/glfuncs.inl new file mode 100644 index 00000000..dafd0949 --- /dev/null +++ b/sp/src/public/togl/glfuncs.inl @@ -0,0 +1,7 @@ +#if defined(LINUX) || defined(_WIN32) +#include "togl/linuxwin/glfuncs.h" +#endif +#if defined(OSX) +#include "togl/osx/glfuncs.h" +#endif + diff --git a/sp/src/public/togl/linuxwin/cglmbuffer.h b/sp/src/public/togl/linuxwin/cglmbuffer.h new file mode 100644 index 00000000..ffec2742 --- /dev/null +++ b/sp/src/public/togl/linuxwin/cglmbuffer.h @@ -0,0 +1,190 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmprogram.h +// GLMgr buffers (index / vertex) +// ... maybe add PBO later as well +//=============================================================================== + +#ifndef CGLMBUFFER_H +#define CGLMBUFFER_H + +#pragma once + +//=============================================================================== + +extern bool g_bUsePseudoBufs; + +// forward declarations + +class GLMContext; + +enum EGLMBufferType +{ + kGLMVertexBuffer, + kGLMIndexBuffer, + kGLMUniformBuffer, // for bindable uniform + kGLMPixelBuffer, // for PBO + + kGLMNumBufferTypes +}; + +// pass this in "options" to constructor to make a dynamic buffer +#define GLMBufferOptionDynamic 0x00000001 + +struct GLMBuffLockParams +{ + uint m_nOffset; + uint m_nSize; + bool m_bNoOverwrite; + bool m_bDiscard; +}; + +#define GL_STATIC_BUFFER_SIZE ( 2048 * 1024 ) +#define GL_MAX_STATIC_BUFFERS 2 + +extern void glBufferSubDataMaxSize( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data, uint nMaxSizePerCall = 128 * 1024 ); + +//=============================================================================== + +#if GL_ENABLE_INDEX_VERIFICATION + +struct GLDynamicBuf_t +{ + GLenum m_nGLType; + uint m_nHandle; + uint m_nActualBufSize; + uint m_nSize; + + uint m_nLockOffset; + uint m_nLockSize; +}; + +class CGLMBufferSpanManager +{ + CGLMBufferSpanManager( const CGLMBufferSpanManager& ); + CGLMBufferSpanManager& operator= ( const CGLMBufferSpanManager& ); + +public: + CGLMBufferSpanManager(); + ~CGLMBufferSpanManager(); + + void Init( GLMContext *pContext, EGLMBufferType nBufType, uint nInitialCapacity, uint nBufSize, bool bDynamic ); + void Deinit(); + + inline GLMContext *GetContext() const { return m_pCtx; } + + inline GLenum GetGLBufType() const { return ( m_nBufType == kGLMVertexBuffer ) ? GL_ARRAY_BUFFER_ARB : GL_ELEMENT_ARRAY_BUFFER_ARB; } + + struct ActiveSpan_t + { + uint m_nStart; + uint m_nEnd; + + GLDynamicBuf_t m_buf; + bool m_bOriginalAlloc; + + inline ActiveSpan_t() { } + inline ActiveSpan_t( uint nStart, uint nEnd, GLDynamicBuf_t &buf, bool bOriginalAlloc ) : m_nStart( nStart ), m_nEnd( nEnd ), m_buf( buf ), m_bOriginalAlloc( bOriginalAlloc ) { Assert( nStart <= nEnd ); } + }; + + ActiveSpan_t *AddSpan( uint nOffset, uint nMaxSize, uint nActualSize, bool bDiscard, bool bNoOverwrite ); + + void DiscardAllSpans(); + + bool IsValid( uint nOffset, uint nSize ) const; + +private: + bool AllocDynamicBuf( uint nSize, GLDynamicBuf_t &buf ); + void ReleaseDynamicBuf( GLDynamicBuf_t &buf ); + + GLMContext *m_pCtx; + + EGLMBufferType m_nBufType; + + uint m_nBufSize; + bool m_bDynamic; + + CUtlVector m_ActiveSpans; + CUtlVector m_DeletedSpans; + + int m_nSpanEndMax; + + int m_nNumAllocatedBufs; + int m_nTotalBytesAllocated; +}; + +#endif // GL_ENABLE_INDEX_VERIFICATION + +class CGLMBuffer +{ +public: + void Lock( GLMBuffLockParams *pParams, char **pAddressOut ); + void Unlock( int nActualSize = -1, const void *pActualData = NULL ); + + friend class GLMContext; // only GLMContext can make CGLMBuffer objects + friend class GLMTester; + friend struct IDirect3D9; + friend struct IDirect3DDevice9; + + CGLMBuffer( GLMContext *pCtx, EGLMBufferType type, uint size, uint options ); + ~CGLMBuffer(); + + void SetModes( bool bAsyncMap, bool bExplicitFlush, bool bForce = false ); + void FlushRange( uint offset, uint size ); + +#if GL_ENABLE_INDEX_VERIFICATION + bool IsSpanValid( uint nOffset, uint nSize ) const; +#endif + + GLMContext *m_pCtx; // link back to parent context + EGLMBufferType m_type; + uint m_nSize; + uint m_nActualSize; + + bool m_bDynamic; + + GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB + GLuint m_nHandle; // name of this program in the context + + uint m_nRevision; // bump anytime the size changes or buffer is orphaned + + bool m_bEnableAsyncMap; // mirror of the buffer state + bool m_bEnableExplicitFlush; // mirror of the buffer state + + bool m_bMapped; // is it currently mapped + + uint m_dirtyMinOffset; // when equal, range is empty + uint m_dirtyMaxOffset; + + float *m_pLastMappedAddress; + + int m_nPinnedMemoryOfs; + + bool m_bPseudo; // true if the m_name is 0, and the backing is plain RAM + + // in pseudo mode, there is just one RAM buffer that acts as the backing. + // expectation is that this mode would only be used for dynamic indices. + // since indices have to be consumed (copied to command stream) prior to return from a drawing call, + // there's no need to do any fencing or multibuffering. orphaning in particular becomes a no-op. + + char *m_pActualPseudoBuf; // storage for pseudo buffer + char *m_pPseudoBuf; // storage for pseudo buffer + char *m_pStaticBuffer; + + GLMBuffLockParams m_LockParams; + + static char ALIGN16 m_StaticBuffers[ GL_MAX_STATIC_BUFFERS ][ GL_STATIC_BUFFER_SIZE ] ALIGN16_POST; + static bool m_bStaticBufferUsed[ GL_MAX_STATIC_BUFFERS ]; + +#if GL_ENABLE_INDEX_VERIFICATION + CGLMBufferSpanManager m_BufferSpanManager; +#endif + +#if GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION + uint m_nDirtyRangeStart; + uint m_nDirtyRangeEnd; +#endif +}; + +#endif // CGLMBUFFER_H + diff --git a/sp/src/public/togl/linuxwin/cglmfbo.h b/sp/src/public/togl/linuxwin/cglmfbo.h new file mode 100644 index 00000000..f3415795 --- /dev/null +++ b/sp/src/public/togl/linuxwin/cglmfbo.h @@ -0,0 +1,82 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmfbo.h +// GLMgr FBO's (render targets) +// +//=============================================================================== + +#ifndef CGLMFBO_H +#define CGLMFBO_H + +#pragma once + +// good FBO references / recaps +// http://www.songho.ca/opengl/gl_fbo.html +// http://www.gamedev.net/reference/articles/article2331.asp + +// ext links + +// http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt +// http://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt + +//=============================================================================== + +// tokens not in the SDK headers + +#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT + #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; + +enum EGLMFBOAttachment +{ + kAttColor0, kAttColor1, kAttColor2, kAttColor3, + kAttDepth, kAttStencil, kAttDepthStencil, + kAttCount +}; + +struct GLMFBOTexAttachParams +{ + CGLMTex *m_tex; + int m_face; // keep zero if not cube map + int m_mip; // keep zero if notmip mapped + int m_zslice; // keep zero if not a 3D tex +}; + +class CGLMFBO +{ + friend class GLMContext; + friend class GLMTester; + friend class CGLMTex; + + friend struct IDirect3D9; + friend struct IDirect3DDevice9; + +public: + CGLMFBO( GLMContext *ctx ); + ~CGLMFBO( ); + +protected: + void TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); + void TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); + // you can also pass GL_READ_FRAMEBUFFER_EXT or GL_DRAW_FRAMEBUFFER_EXT to selectively bind the receiving FBO to one or the other. + + void TexScrub( CGLMTex *tex ); + // search and destroy any attachment for the named texture + + bool IsReady( void ); // aka FBO completeness check - ready to draw + + GLMContext *m_ctx; // link back to parent context + + GLuint m_name; // name of this FBO in the context + + GLMFBOTexAttachParams m_attach[ kAttCount ]; // indexed by EGLMFBOAttachment +}; + + +#endif \ No newline at end of file diff --git a/sp/src/public/togl/linuxwin/cglmprogram.h b/sp/src/public/togl/linuxwin/cglmprogram.h new file mode 100644 index 00000000..ca32af00 --- /dev/null +++ b/sp/src/public/togl/linuxwin/cglmprogram.h @@ -0,0 +1,420 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmprogram.h +// GLMgr programs (ARBVP/ARBfp) +// +//=============================================================================== + +#ifndef CGLMPROGRAM_H +#define CGLMPROGRAM_H + +#include + +#pragma once + +// good ARB program references +// http://petewarden.com/notes/archives/2005/05/fragment_progra_2.html +// http://petewarden.com/notes/archives/2005/06/fragment_progra_3.html + +// ext links + +// http://www.opengl.org/registry/specs/ARB/vertex_program.txt +// http://www.opengl.org/registry/specs/ARB/fragment_program.txt +// http://www.opengl.org/registry/specs/EXT/gpu_program_parameters.txt + + +//=============================================================================== + +// tokens not in the SDK headers + +//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT +// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +//#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; +class CGLMShaderPair; +class CGLMShaderPairCache; + +// CGLMProgram can contain two flavors of the same program, one in assembler, one in GLSL. +// these flavors are pretty different in terms of the API's that are used to activate them - +// for example, assembler programs can just get bound to the context, whereas GLSL programs +// have to be linked. To some extent we try to hide that detail inside GLM. + +// for now, make CGLMProgram a container, it does not set policy or hold a preference as to which +// flavor you want to use. GLMContext has to handle that. + +enum EGLMProgramType +{ + kGLMVertexProgram, + kGLMFragmentProgram, + + kGLMNumProgramTypes +}; + +enum EGLMProgramLang +{ + kGLMARB, + kGLMGLSL, + + kGLMNumProgramLangs +}; + +struct GLMShaderDesc +{ + union + { + GLuint arb; // ARB program object name + GLhandleARB glsl; // GLSL shader object handle (void*) + } m_object; + + // these can change if shader text is edited + bool m_textPresent; // is this flavor(lang) of text present in the buffer? + int m_textOffset; // where is it + int m_textLength; // how big + + bool m_compiled; // has this text been through a compile attempt + bool m_valid; // and if so, was the compile successful + + int m_slowMark; // has it been flagged during a non native draw batch before. increment every time it's slow. + + int m_highWater; // count of vec4's in the major uniform array ("vc" on vs, "pc" on ps) + // written by dxabstract.... gross! + int m_VSHighWaterBone; // count of vec4's in the bone-specific uniform array (only valid for vertex shaders) +}; + +GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target +GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target + +#define GL_SHADER_PAIR_CACHE_STATS 0 + +class CGLMProgram +{ +public: + friend class CGLMShaderPairCache; + friend class CGLMShaderPair; + friend class GLMContext; // only GLMContext can make CGLMProgram objects + friend class GLMTester; + friend struct IDirect3D9; + friend struct IDirect3DDevice9; + + //=============================== + + // constructor is very light, it just makes one empty program object per flavor. + CGLMProgram( GLMContext *ctx, EGLMProgramType type ); + ~CGLMProgram( ); + + void SetProgramText ( char *text ); // import text to GLM object - invalidate any prev compiled program + void SetShaderName ( const char *name ); // only used for debugging/telemetry markup + + bool CompileActiveSources ( void ); // compile only the flavors that were provided. + bool Compile ( EGLMProgramLang lang ); + bool CheckValidity ( EGLMProgramLang lang ); + + void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that + + void GetLabelIndexCombo ( char *labelOut, int labelOutMaxChars, int *indexOut, int *comboOut ); + void GetComboIndexNameString ( char *stringOut, int stringOutMaxChars ); // mmmmmmmm-nnnnnnnn-filename + +#if GLMDEBUG + bool PollForChanges( void ); // check mirror for changes. + void ReloadStringFromEditable( void ); // populate m_string from editable item (react to change) + bool SyncWithEditable( void ); +#endif + + //=============================== + + // common stuff + + GLMContext *m_ctx; // link back to parent context + + EGLMProgramType m_type; // vertex or pixel + + uint m_nHashTag; // serial number for hashing + + char *m_text; // copy of text passed into constructor. Can change if editable shaders is enabled. + // note - it can contain multiple flavors, so use CGLMTextSectioner to scan it and locate them +#if GLMDEBUG + CGLMEditableTextItem *m_editable; // editable text item for debugging +#endif + + GLMShaderDesc m_descs[ kGLMNumProgramLangs ]; + + uint m_samplerMask; // (1<> 16; + // Apply half pixel offset to output vertices to account for the pixel center difference between D3D9 and OpenGL. + // We output vertices in clip space, which ranges from [-1,1], so 1.0/width in clip space transforms into .5/width in screenspace, see: "Viewports and Clipping (Direct3D 9)" in the DXSDK + float v[4] = { 1.0f / nWidth, 1.0f / nHeight, nWidth, nHeight }; + if ( m_locVertexScreenParams >= 0 ) + gGL->glUniform4fv( m_locVertexScreenParams, 1, v ); + } + + //=============================== + + // common stuff + + GLMContext *m_ctx; // link back to parent context + + CGLMProgram *m_vertexProg; + CGLMProgram *m_fragmentProg; + + GLhandleARB m_program; // linked program object + + // need meta data for attribs / samplers / params + // actually we only need it for samplers and params. + // attributes are hardwired. + + // vertex stage uniforms + GLint m_locVertexParams; // "vc" per dx9asmtogl2 convention + GLint m_locVertexBoneParams; // "vcbones" + GLint m_locVertexInteger0; // "i0" + + GLint m_locVertexBool0; // "b0" + GLint m_locVertexBool1; // "b1" + GLint m_locVertexBool2; // "b2" + GLint m_locVertexBool3; // "b3" + bool m_bHasBoolOrIntUniforms; + + // fragment stage uniforms + GLint m_locFragmentParams; // "pc" per dx9asmtogl2 convention + + int m_NumUniformBufferParams[kGLMNumProgramTypes]; + GLint m_UniformBufferParams[kGLMNumProgramTypes][256]; + + GLint m_locFragmentFakeSRGBEnable; // "flSRGBWrite" - set to 1.0 to effect sRGB encoding on output + float m_fakeSRGBEnableValue; // shadow to avoid redundant sets of the m_locFragmentFakeSRGBEnable uniform + // init it to -1.0 at link or relink, so it will trip on any legit incoming value (0.0 or 1.0) + + GLint m_locSamplers[ 16 ]; // "sampler0 ... sampler1..." + + // other stuff + bool m_valid; // true on successful link + uint m_revision; // if this pair is relinked, bump this number. + + GLint m_locVertexScreenParams; // vcscreen + uint m_nScreenWidthHeight; + +}; + +//=============================================================================== + +// N-row, M-way associative cache with LRU per row. +// still needs some metric dump ability and some parameter tuning. +// extra credit would be to make an auto-tuner. + +struct CGLMPairCacheEntry +{ + long long m_lastMark; // a mark of zero means an empty entry + CGLMProgram *m_vertexProg; + CGLMProgram *m_fragmentProg; + uint m_extraKeyBits; + CGLMShaderPair *m_pair; +}; + +class CGLMShaderPairCache // cache for linked GLSL shader pairs +{ + +public: + +protected: + friend class CGLMShaderPair; + friend class CGLMProgram; + friend class GLMContext; + + //=============================== + + CGLMShaderPairCache( GLMContext *ctx ); + ~CGLMShaderPairCache( ); + + FORCEINLINE CGLMShaderPair *SelectShaderPair ( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ); + void QueryShaderPair ( int index, GLMShaderPairInfo *infoOut ); + + // shoot down linked pairs that use the program in the arg + // return true if any had to be skipped due to conflict with currently bound pair + bool PurgePairsWithShader( CGLMProgram *prog ); + + // purge everything (when would GLM know how to do this ? at context destroy time, but any other times?) + // return true if any had to be skipped due to conflict with currently bound pair + bool Purge ( void ); + + // stats + void DumpStats ( void ); + + //=============================== + + FORCEINLINE uint HashRowIndex( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) const; + FORCEINLINE CGLMPairCacheEntry* HashRowPtr( uint hashRowIndex ) const; + + FORCEINLINE void HashRowProbe( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int &hitway, int &emptyway, int &oldestway ); + + CGLMShaderPair *SelectShaderPairInternal( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int rowIndex ); + //=============================== + + // common stuff + + GLMContext *m_ctx; // link back to parent context + + long long m_mark; + + uint m_rowsLg2; + uint m_rows; + uint m_rowsMask; + + uint m_waysLg2; + uint m_ways; + + uint m_entryCount; + + CGLMPairCacheEntry *m_entries; // array[ m_rows ][ m_ways ] + + uint *m_evictions; // array[ m_rows ]; + +#if GL_SHADER_PAIR_CACHE_STATS + uint *m_hits; // array[ m_rows ]; +#endif +}; + +FORCEINLINE uint CGLMShaderPairCache::HashRowIndex( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) const +{ + return ( vp->m_nHashTag + fp->m_nHashTag + extraKeyBits * 7 ) & m_rowsMask; +} + +FORCEINLINE CGLMPairCacheEntry* CGLMShaderPairCache::HashRowPtr( uint hashRowIndex ) const +{ + return &m_entries[ hashRowIndex * m_ways ]; +} + +FORCEINLINE void CGLMShaderPairCache::HashRowProbe( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int& hitway, int& emptyway, int& oldestway ) +{ + hitway = -1; + emptyway = -1; + oldestway = -1; + + // scan this row to see if the desired pair is present + CGLMPairCacheEntry *cursor = row; + long long oldestmark = 0xFFFFFFFFFFFFFFFFLL; + + for( uint way = 0; way < m_ways; ++way ) + { + if ( cursor->m_lastMark != 0 ) // occupied slot + { + // check if this is the oldest one on the row - only occupied slots are checked + if ( cursor->m_lastMark < oldestmark ) + { + oldestway = way; + oldestmark = cursor->m_lastMark; + } + + if ( ( cursor->m_vertexProg == vp ) && ( cursor->m_fragmentProg == fp ) && ( cursor->m_extraKeyBits == extraKeyBits ) ) // match? + { + // found it + hitway = way; + break; + } + } + else + { + // empty way, log it if first one seen + if (emptyway<0) + { + emptyway = way; + } + } + cursor++; + } +} + +FORCEINLINE CGLMShaderPair *CGLMShaderPairCache::SelectShaderPair( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) +{ + // select row where pair would be found if it exists + uint rowIndex = HashRowIndex( vp, fp, extraKeyBits ); + + CGLMPairCacheEntry *pCursor = HashRowPtr( rowIndex ); + + if ( ( pCursor->m_fragmentProg != fp ) || ( pCursor->m_vertexProg != vp ) || ( pCursor->m_extraKeyBits != extraKeyBits ) ) + { + CGLMPairCacheEntry *pLastCursor = pCursor + m_ways; + + ++pCursor; + + while ( pCursor != pLastCursor ) + { + if ( ( pCursor->m_fragmentProg == fp ) && ( pCursor->m_vertexProg == vp ) && ( pCursor->m_extraKeyBits == extraKeyBits ) ) // match? + break; + ++pCursor; + }; + + if ( pCursor == pLastCursor ) + return SelectShaderPairInternal( vp, fp, extraKeyBits, rowIndex ); + } + + // found it. mark it and return + pCursor->m_lastMark = m_mark++; + +#if GL_SHADER_PAIR_CACHE_STATS + // count the hit + m_hits[ rowIndex ] ++; +#endif + + return pCursor->m_pair; +} + +#endif diff --git a/sp/src/public/togl/linuxwin/cglmquery.h b/sp/src/public/togl/linuxwin/cglmquery.h new file mode 100644 index 00000000..3cf6f79e --- /dev/null +++ b/sp/src/public/togl/linuxwin/cglmquery.h @@ -0,0 +1,90 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmquery.h +// GLMgr queries +// +//=============================================================================== + +#ifndef CGLMQUERY_H +#define CGLMQUERY_H + +#pragma once + +#ifdef OSX +#include "glmgr/glmgrbasics.h" +#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; +class CGLMQuery; + +//=============================================================================== + +enum EGLMQueryType +{ + EOcclusion, + EFence, + EGLMQueryCount +}; + +struct GLMQueryParams +{ + EGLMQueryType m_type; +}; + +class CGLMQuery +{ + // leave everything public til it's running +public: + friend class GLMContext; // only GLMContext can make CGLMTex objects + friend struct IDirect3DDevice9; + friend struct IDirect3DQuery9; + + GLMContext *m_ctx; // link back to parent context + GLMQueryParams m_params; // params created with + + GLuint m_name; // name of the query object per se - could be fence, could be query object ... NOT USED WITH GL_ARB_sync! +#ifdef HAVE_GL_ARB_SYNC + GLsync m_syncobj; // GL_ARB_sync object. NOT USED WITH GL_NV_fence or GL_APPLE_fence! +#else + GLuint m_syncobj; +#endif + + bool m_started; + bool m_stopped; + bool m_done; + + bool m_nullQuery; // was gl_nullqueries true at Start time - if so, continue to act like a null query through Stop/IsDone/Complete time + // restated - only Start should examine the convar. + static uint s_nTotalOcclusionQueryCreatesOrDeletes; + + CGLMQuery( GLMContext *ctx, GLMQueryParams *params ); + ~CGLMQuery( ); + + // for an occlusion query: + // Start = BeginQuery query-start goes into stream + // Stop = EndQuery query-end goes into stream - a fence is also set so we can probe for completion + // IsDone = TestFence use the added fence to ask if query-end has passed (i.e. will Complete block?) + // Complete = GetQueryObjectuivARB(uint id, enum pname, uint *params) - extract the sample count + + // for a fence query: + // Start = SetFence fence goes into command stream + // Stop = NOP fences are self finishing - no need to call Stop on a fence + // IsDone = TestFence ask if fence passed + // Complete = FinishFence + + void Start ( void ); + void Stop ( void ); + bool IsDone ( void ); + void Complete ( uint *result ); + + // accessors for the started/stopped state + bool IsStarted ( void ); + bool IsStopped ( void ); +}; + + +#endif diff --git a/sp/src/public/togl/linuxwin/cglmtex.h b/sp/src/public/togl/linuxwin/cglmtex.h new file mode 100644 index 00000000..bdb83776 --- /dev/null +++ b/sp/src/public/togl/linuxwin/cglmtex.h @@ -0,0 +1,502 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmtex.h +// GLMgr textures +// +//=============================================================================== + +#ifndef CGLMTEX_H +#define CGLMTEX_H + +#pragma once + +#ifdef OSX +#include "glmgr/glmgrbasics.h" +#endif +#include "tier1/utlhash.h" +#include "tier1/utlmap.h" + +//=============================================================================== + +// forward declarations + +class GLMContext; +class GLMTester; +class CGLMTexLayoutTable; +class CGLMTex; +class CGLMFBO; + +struct IDirect3DSurface9; + +#if GLMDEBUG +extern CGLMTex *g_pFirstCGMLTex; +#endif + +// For GL_EXT_texture_sRGB_decode +#ifndef GL_TEXTURE_SRGB_DECODE_EXT +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#endif + +#ifndef GL_DECODE_EXT +#define GL_DECODE_EXT 0x8A49 +#endif + +#ifndef GL_SKIP_DECODE_EXT +#define GL_SKIP_DECODE_EXT 0x8A4A +#endif + +//=============================================================================== + +struct GLMTexFormatDesc +{ + const char *m_formatSummary; // for debug visibility + + D3DFORMAT m_d3dFormat; // what D3D knows it as; see public/bitmap/imageformat.h + + GLenum m_glIntFormat; // GL internal format + GLenum m_glIntFormatSRGB; // internal format if SRGB flavor + GLenum m_glDataFormat; // GL data format + GLenum m_glDataType; // GL data type + + int m_chunkSize; // 1 or 4 - 4 is used for compressed textures + int m_bytesPerSquareChunk; // how many bytes for the smallest quantum (m_chunkSize x m_chunkSize) + // this description lets us calculate size cleanly without conditional logic for compression +}; +const GLMTexFormatDesc *GetFormatDesc( D3DFORMAT format ); + +//=============================================================================== + +// utility function for generating slabs of texels. mostly for test. +typedef struct +{ + // in + D3DFORMAT m_format; + void *m_dest; // dest address + int m_chunkCount; // square chunk count (single texels or compressed blocks) + int m_byteCountLimit; // caller expectation of max number of bytes to write out + float r,g,b,a; // color desired + + // out + int m_bytesWritten; +} GLMGenTexelParams; + +// return true if successful +bool GLMGenTexels( GLMGenTexelParams *params ); + + +//=============================================================================== + +struct GLMTexLayoutSlice +{ + int m_xSize,m_ySize,m_zSize; //texel dimensions of this slice + int m_storageOffset; //where in the storage slab does this slice live + int m_storageSize; //how much storage does this slice occupy +}; + +enum EGLMTexFlags +{ + kGLMTexMipped = 0x01, + kGLMTexMippedAuto = 0x02, + kGLMTexRenderable = 0x04, + kGLMTexIsStencil = 0x08, + kGLMTexIsDepth = 0x10, + kGLMTexSRGB = 0x20, + kGLMTexMultisampled = 0x40, // has an RBO backing it. Cannot combine with Mipped, MippedAuto. One slice maximum, only targeting GL_TEXTURE_2D. + // actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could + // have mipmaps generated. +}; + +//=============================================================================== + +struct GLMTexLayoutKey +{ + // input values: held const, these are the hash key for the form map + GLenum m_texGLTarget; // flavor of texture: GL_TEXTURE_2D, GL_TEXTURE_3D, GLTEXTURE_CUBE_MAP + D3DFORMAT m_texFormat; // D3D texel format + unsigned long m_texFlags; // mipped, autogen mips, render target, ... ? + unsigned long m_texSamples; // zero for a plain tex, 2/4/6/8 for "MSAA tex" (RBO backed) + int m_xSize,m_ySize,m_zSize; // size of base mip +}; + +bool LessFunc_GLMTexLayoutKey( const GLMTexLayoutKey &a, const GLMTexLayoutKey &b ); + +#define GLM_TEX_MAX_MIPS 14 +#define GLM_TEX_MAX_FACES 6 +#define GLM_TEX_MAX_SLICES (GLM_TEX_MAX_MIPS * GLM_TEX_MAX_FACES) + +#pragma warning( push ) +#pragma warning( disable : 4200 ) + +struct GLMTexLayout +{ + char *m_layoutSummary; // for debug visibility + + // const inputs used for hashing + GLMTexLayoutKey m_key; + + // refcount + int m_refCount; + + // derived values: + GLMTexFormatDesc *m_format; // format specific info + int m_mipCount; // derived by starying at base size and working down towards 1x1 + int m_faceCount; // 1 for 2d/3d, 6 for cubemap + int m_sliceCount; // product of faces and mips + int m_storageTotalSize; // size of storage slab required + + // slice array + GLMTexLayoutSlice m_slices[0]; // dynamically allocated 2-d array [faces][mips] +}; + +#pragma warning( pop ) + +class CGLMTexLayoutTable +{ +public: + CGLMTexLayoutTable(); + + GLMTexLayout *NewLayoutRef( GLMTexLayoutKey *pDesiredKey ); // pass in a pointer to layout key - receive ptr to completed layout + void DelLayoutRef( GLMTexLayout *layout ); // pass in pointer to completed layout. refcount is dropped. + + void DumpStats( void ); +protected: + CUtlMap< GLMTexLayoutKey, GLMTexLayout* > m_layoutMap; +}; + +//=============================================================================== + +// a sampler specifies desired state for drawing on a given sampler index +// this is the combination of a texture choice and a set of sampler parameters +// see http://msdn.microsoft.com/en-us/library/bb172602(VS.85).aspx + +struct GLMTexLockParams +{ + // input params which identify the slice of interest + CGLMTex *m_tex; + int m_face; + int m_mip; + + // identifies the region of the slice + GLMRegion m_region; + + // tells GLM to force re-read of the texels back from GL + // i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale" + bool m_readback; +}; + +struct GLMTexLockDesc +{ + GLMTexLockParams m_req; // form of the lock request + + bool m_active; // set true at lock time. cleared at unlock time. + + int m_sliceIndex; // which slice in the layout + int m_sliceBaseOffset; // where is that in the texture data + int m_sliceRegionOffset; // offset to the start (lowest address corner) of the region requested +}; + +//=============================================================================== + +#define GLM_SAMPLER_COUNT 16 + +typedef CBitVec CTexBindMask; + +enum EGLMTexSliceFlag +{ + kSliceValid = 0x01, // slice has been teximage'd in whole at least once - set to 0 initially + kSliceStorageValid = 0x02, // if backing store is available, this slice's data is a valid copy - set to 0 initially + kSliceLocked = 0x04, // are one or more locks outstanding on this slice + kSliceFullyDirty = 0x08, // does the slice need to be fully downloaded at unlock time (disregard dirty rects) +}; + +//=============================================================================== + +#define GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS (2) +#define GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS (2) +#define GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS (2) +#define GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS (2) +#define GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS (4) +#define GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS (5) +#define GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS (1) +#define GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS (1) + +struct GLMTexPackedSamplingParams +{ + uint32 m_addressU : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS; + uint32 m_addressV : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS; + uint32 m_addressW : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS; + + uint32 m_minFilter : GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS; + uint32 m_magFilter : GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS; + uint32 m_mipFilter : GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS; + + uint32 m_minLOD : GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS; + uint32 m_maxAniso : GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS; + uint32 m_compareMode : GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS; + uint32 m_srgb : GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS; + uint32 m_isValid : 1; +}; + +struct GLMTexSamplingParams +{ + union + { + GLMTexPackedSamplingParams m_packed; + uint32 m_bits; + }; + + uint32 m_borderColor; + + FORCEINLINE bool operator== (const GLMTexSamplingParams& rhs ) const + { + return ( m_bits == rhs.m_bits ) && ( m_borderColor == rhs.m_borderColor ); + } + + FORCEINLINE void SetToDefaults() + { + m_bits = 0; + m_borderColor = 0; + m_packed.m_addressU = D3DTADDRESS_WRAP; + m_packed.m_addressV = D3DTADDRESS_WRAP; + m_packed.m_addressW = D3DTADDRESS_WRAP; + m_packed.m_minFilter = D3DTEXF_POINT; + m_packed.m_magFilter = D3DTEXF_POINT; + m_packed.m_mipFilter = D3DTEXF_NONE; + m_packed.m_maxAniso = 1; + m_packed.m_isValid = true; + } + + FORCEINLINE void SetToSamplerObject( GLuint nSamplerObject ) const + { + static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 }; + static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR }; + static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter]. + { + /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT + /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling + }; + + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso ); + + float flBorderColor[4] = { 0, 0, 0, 0 }; + if ( m_borderColor ) + { + flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R + flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G + flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B + flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A + } + gGL->glSamplerParameterfv( nSamplerObject, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD ); + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ); + if ( m_packed.m_compareMode ) + { + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); + } + if ( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) + { + gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ); + } + } + + inline void DeltaSetToTarget( GLenum target, const GLMTexSamplingParams &curState ) + { + static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 }; + static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR }; + static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter]. + { + /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT + /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling + }; + + if ( m_packed.m_addressU != curState.m_packed.m_addressU ) + { + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] ); + } + + if ( m_packed.m_addressV != curState.m_packed.m_addressV ) + { + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] ); + } + + if ( m_packed.m_addressW != curState.m_packed.m_addressW ) + { + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] ); + } + + if ( ( m_packed.m_minFilter != curState.m_packed.m_minFilter ) || + ( m_packed.m_magFilter != curState.m_packed.m_magFilter ) || + ( m_packed.m_mipFilter != curState.m_packed.m_mipFilter ) || + ( m_packed.m_maxAniso != curState.m_packed.m_maxAniso ) ) + { + gGL->glTexParameteri( target, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] ); + gGL->glTexParameteri( target, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] ); + gGL->glTexParameteri( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso ); + } + + if ( m_borderColor != curState.m_borderColor ) + { + float flBorderColor[4] = { 0, 0, 0, 0 }; + if ( m_borderColor ) + { + flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R + flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G + flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B + flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A + } + + gGL->glTexParameterfv( target, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out + } + + if ( m_packed.m_minLOD != curState.m_packed.m_minLOD ) + { + gGL->glTexParameteri( target, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD ); + } + + if ( m_packed.m_compareMode != curState.m_packed.m_compareMode ) + { + gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ); + if ( m_packed.m_compareMode ) + { + gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); + } + } + + if ( ( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) && ( m_packed.m_srgb != curState.m_packed.m_srgb ) ) + { + gGL->glTexParameteri( target, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ); + } + } + + inline void SetToTargetTexture( GLenum target ) + { + static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 }; + static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR }; + static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter]. + { + /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT + /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, + /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling + }; + + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] ); + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] ); + gGL->glTexParameteri( target, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] ); + gGL->glTexParameteri( target, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] ); + gGL->glTexParameteri( target, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] ); + gGL->glTexParameteri( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso ); + + float flBorderColor[4] = { 0, 0, 0, 0 }; + if ( m_borderColor ) + { + flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R + flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G + flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B + flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A + } + gGL->glTexParameterfv( target, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out + gGL->glTexParameteri( target, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD ); + gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ); + if ( m_packed.m_compareMode ) + { + gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); + } + if ( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) + { + gGL->glTexParameteri( target, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ); + } + } +}; + +//=============================================================================== + +class CGLMTex +{ + +public: + + void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut ); + void Unlock( GLMTexLockParams *params ); + +protected: + friend class GLMContext; // only GLMContext can make CGLMTex objects + friend class GLMTester; + friend class CGLMFBO; + + friend struct IDirect3DDevice9; + friend struct IDirect3DBaseTexture9; + friend struct IDirect3DTexture9; + friend struct IDirect3DSurface9; + friend struct IDirect3DCubeTexture9; + friend struct IDirect3DVolumeTexture9; + + CGLMTex( GLMContext *ctx, GLMTexLayout *layout, const char *debugLabel = NULL ); + ~CGLMTex( ); + + int CalcSliceIndex( int face, int mip ); + void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut ); + + void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true ); + void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false ); + // last param lets us send NULL data ptr (only legal with uncompressed formats, beware) + // this helps out ResetSRGB. + + bool IsRBODirty() const; + void ForceRBONonDirty(); + void ForceRBODirty(); + + void AllocBacking(); + void ReleaseBacking(); + + // re-specify texture format to match desired sRGB form + // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's + + GLuint m_texName; // name of this texture in the context + GLenum m_texGLTarget; + uint m_nSamplerType; // SAMPLER_2D, etc. + GLMTexSamplingParams m_SamplingParams; + GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout) + + uint m_nLastResolvedBatchCounter; + + int m_minActiveMip;//index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. + int m_maxActiveMip;//index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. + int m_mipCount; + + GLMContext *m_ctx; // link back to parent context + + CGLMFBO *m_pBlitSrcFBO; + CGLMFBO *m_pBlitDstFBO; + + GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero) + + int m_rtAttachCount; // how many RT's have this texture attached somewhere + + char *m_pBacking; // backing storage if available + + int m_lockCount; // lock reqs are stored in the GLMContext for tracking + + CUtlVector m_sliceFlags; + + char *m_debugLabel; // strdup() of debugLabel passed in, or NULL + + bool m_texClientStorage; // was CS selected for texture + bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet + +#if GLMDEBUG + CGLMTex *m_pPrevTex; + CGLMTex *m_pNextTex; +#endif +}; + +#endif diff --git a/sp/src/public/togl/linuxwin/dxabstract.h b/sp/src/public/togl/linuxwin/dxabstract.h new file mode 100644 index 00000000..ab5940e5 --- /dev/null +++ b/sp/src/public/togl/linuxwin/dxabstract.h @@ -0,0 +1,1412 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// dxabstract.h +// +//================================================================================================== +#ifndef DXABSTRACT_H +#define DXABSTRACT_H + +#ifdef DX_TO_GL_ABSTRACTION + +#include "togl/rendermechanism.h" + +#include "tier0/platform.h" +#include "tier0/dbg.h" +#include "tier1/utlmap.h" + +// turn this on to get refcount logging from IUnknown +#define IUNKNOWN_ALLOC_SPEW 0 +#define IUNKNOWN_ALLOC_SPEW_MARK_ALL 0 + +TOGL_INTERFACE void toglGetClientRect( VD3DHWND hWnd, RECT *destRect ); + +struct TOGL_CLASS IUnknown +{ + int m_refcount[2]; + bool m_mark; + + IUnknown() + { + m_refcount[0] = 1; + m_refcount[1] = 0; + m_mark = (IUNKNOWN_ALLOC_SPEW_MARK_ALL != 0); // either all are marked, or only the ones that have SetMark(true) called on them + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUnew (%08x) refc -> (%d,%d) ",this,m_refcount[0],m_refcount[1])); + } + #endif + }; + + virtual ~IUnknown() + { + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUdel (%08x) ",this )); + } + #endif + }; + + void AddRef( int which=0, char *comment = NULL ) + { + Assert( which >= 0 ); + Assert( which < 2 ); + m_refcount[which]++; + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUAddRef (%08x,%d) refc -> (%d,%d) [%s]",this,which,m_refcount[0],m_refcount[1],comment?comment:"...")) ; + if (!comment) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + } + #endif + }; + + ULONG __stdcall Release( int which=0, char *comment = NULL ) + { + Assert( which >= 0 ); + Assert( which < 2 ); + + //int oldrefcs[2] = { m_refcount[0], m_refcount[1] }; + bool deleting = false; + + m_refcount[which]--; + if ( (!m_refcount[0]) && (!m_refcount[1]) ) + { + deleting = true; + } + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IURelease (%08x,%d) refc -> (%d,%d) [%s] %s",this,which,m_refcount[0],m_refcount[1],comment?comment:"...",deleting?"->DELETING":"")); + if (!comment) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + } + #endif + + if (deleting) + { + if (m_mark) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + delete this; + return 0; + } + else + { + return m_refcount[0]; + } + }; + + void SetMark( bool markValue, char *comment=NULL ) + { + #if IUNKNOWN_ALLOC_SPEW + if (!m_mark && markValue) // leading edge detect + { + // print the same thing that the constructor would have printed if it had been marked from the beginning + // i.e. it's anticipated that callers asking for marking will do so right at create time + GLMPRINTF(("-A- IUSetMark (%08x) refc -> (%d,%d) (%s) ",this,m_refcount[0],m_refcount[1],comment?comment:"...")); + } + #endif + + m_mark = markValue; + } +}; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// INTERFACES +// ------------------------------------------------------------------------------------------------------------------------------ // + +struct TOGL_CLASS IDirect3DResource9 : public IUnknown +{ + IDirect3DDevice9 *m_device; // parent device + D3DRESOURCETYPE m_restype; + + DWORD SetPriority(DWORD PriorityNew); +}; + +struct TOGL_CLASS IDirect3DBaseTexture9 : public IDirect3DResource9 // "A Texture.." +{ + D3DSURFACE_DESC m_descZero; // desc of top level. + CGLMTex *m_tex; // a CGLMTex can represent all forms of tex + int m_srgbFlipCount; + + virtual ~IDirect3DBaseTexture9(); + D3DRESOURCETYPE TOGLMETHODCALLTYPE GetType(); + DWORD TOGLMETHODCALLTYPE GetLevelCount(); + HRESULT TOGLMETHODCALLTYPE GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DTexture9 : public IDirect3DBaseTexture9 // "Texture 2D" +{ + IDirect3DSurface9 *m_surfZero; // surf of top level. + virtual ~IDirect3DTexture9(); + HRESULT TOGLMETHODCALLTYPE LockRect(UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); + HRESULT TOGLMETHODCALLTYPE UnlockRect(UINT Level); + HRESULT TOGLMETHODCALLTYPE GetSurfaceLevel(UINT Level,IDirect3DSurface9** ppSurfaceLevel); +}; + +struct TOGL_CLASS IDirect3DCubeTexture9 : public IDirect3DBaseTexture9 // "Texture Cube Map" +{ + IDirect3DSurface9 *m_surfZero[6]; // surfs of top level. + virtual ~IDirect3DCubeTexture9(); + HRESULT TOGLMETHODCALLTYPE GetCubeMapSurface(D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface); + HRESULT TOGLMETHODCALLTYPE GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DVolumeTexture9 : public IDirect3DBaseTexture9 // "Texture 3D" +{ + IDirect3DSurface9 *m_surfZero; // surf of top level. + D3DVOLUME_DESC m_volDescZero; // volume desc top level + virtual ~IDirect3DVolumeTexture9(); + HRESULT TOGLMETHODCALLTYPE LockBox(UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags); + HRESULT TOGLMETHODCALLTYPE UnlockBox(UINT Level); + HRESULT TOGLMETHODCALLTYPE GetLevelDesc( UINT level, D3DVOLUME_DESC *pDesc ); +}; + + +// for the moment, a "D3D surface" is modeled as a GLM tex, a face, and a mip. +// no Create method, these are filled in by the various create surface methods. + +struct TOGL_CLASS IDirect3DSurface9 : public IDirect3DResource9 +{ + virtual ~IDirect3DSurface9(); + HRESULT TOGLMETHODCALLTYPE LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); + HRESULT TOGLMETHODCALLTYPE UnlockRect(); + HRESULT TOGLMETHODCALLTYPE GetDesc(D3DSURFACE_DESC *pDesc); + + D3DSURFACE_DESC m_desc; + CGLMTex *m_tex; + int m_face; + int m_mip; +}; + +struct TOGL_CLASS IDirect3D9 : public IUnknown +{ + virtual ~IDirect3D9(); + + UINT TOGLMETHODCALLTYPE GetAdapterCount(); + + HRESULT TOGLMETHODCALLTYPE GetDeviceCaps (UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps); + HRESULT TOGLMETHODCALLTYPE GetAdapterIdentifier (UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier); + HRESULT TOGLMETHODCALLTYPE CheckDeviceFormat (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat); + UINT TOGLMETHODCALLTYPE GetAdapterModeCount (UINT Adapter,D3DFORMAT Format); + HRESULT TOGLMETHODCALLTYPE EnumAdapterModes (UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode); + HRESULT TOGLMETHODCALLTYPE CheckDeviceType (UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed); + HRESULT TOGLMETHODCALLTYPE GetAdapterDisplayMode (UINT Adapter,D3DDISPLAYMODE* pMode); + HRESULT TOGLMETHODCALLTYPE CheckDepthStencilMatch (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat); + HRESULT TOGLMETHODCALLTYPE CheckDeviceMultiSampleType (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels); + + HRESULT TOGLMETHODCALLTYPE CreateDevice (UINT Adapter,D3DDEVTYPE DeviceType,VD3DHWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface); +}; + +struct TOGL_CLASS IDirect3DVertexDeclaration9 : public IUnknown +{ + IDirect3DDevice9 *m_device; + uint m_elemCount; + D3DVERTEXELEMENT9_GL m_elements[ MAX_D3DVERTEXELEMENTS ]; + + uint8 m_VertexAttribDescToStreamIndex[256]; + + virtual ~IDirect3DVertexDeclaration9(); +}; + +struct TOGL_CLASS IDirect3DQuery9 : public IDirect3DResource9 //was IUnknown +{ + D3DQUERYTYPE m_type; // D3DQUERYTYPE_OCCLUSION or D3DQUERYTYPE_EVENT + GLMContext *m_ctx; + CGLMQuery *m_query; + + uint m_nIssueStartThreadID, m_nIssueEndThreadID; + uint m_nIssueStartDrawCallIndex, m_nIssueEndDrawCallIndex; + uint m_nIssueStartFrameIndex, m_nIssueEndFrameIndex; + uint m_nIssueStartQueryCreationCounter, m_nIssueEndQueryCreationCounter; + + virtual ~IDirect3DQuery9(); + + HRESULT Issue(DWORD dwIssueFlags); + HRESULT GetData(void* pData,DWORD dwSize,DWORD dwGetDataFlags); +}; + +struct TOGL_CLASS IDirect3DVertexBuffer9 : public IDirect3DResource9 //was IUnknown +{ + GLMContext *m_ctx; + CGLMBuffer *m_vtxBuffer; + D3DVERTEXBUFFER_DESC m_vtxDesc; // to satisfy GetDesc + + virtual ~IDirect3DVertexBuffer9(); + HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); + HRESULT Unlock(); + void UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); +}; + +struct TOGL_CLASS IDirect3DIndexBuffer9 : public IDirect3DResource9 //was IUnknown +{ + GLMContext *m_ctx; + CGLMBuffer *m_idxBuffer; + D3DINDEXBUFFER_DESC m_idxDesc; // to satisfy GetDesc + + virtual ~IDirect3DIndexBuffer9(); + + HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); + HRESULT Unlock(); + void UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); + + HRESULT GetDesc(D3DINDEXBUFFER_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DPixelShader9 : public IDirect3DResource9 //was IUnknown +{ + CGLMProgram *m_pixProgram; + uint m_pixHighWater; // count of active constant slots referenced by shader. + uint m_pixSamplerMask; // (1< CD3DMATRIXAllocator; + typedef class TOGL_CLASS CUtlVector CD3DMATRIXStack; +#else + typedef class CUtlMemory CD3DMATRIXAllocator; + typedef class CUtlVector CD3DMATRIXStack; +#endif + +struct TOGL_CLASS ID3DXMatrixStack //: public IUnknown +{ + int m_refcount[2]; + bool m_mark; + CD3DMATRIXStack m_stack; + int m_stackTop; // top of stack is at the highest index, this is that index. push increases, pop decreases. + + ID3DXMatrixStack(); + void AddRef( int which=0, char *comment = NULL ); + ULONG Release( int which=0, char *comment = NULL ); + + HRESULT Create( void ); + + D3DXMATRIX* GetTop(); + void Push(); + void Pop(); + void LoadIdentity(); + void LoadMatrix( const D3DXMATRIX *pMat ); + void MultMatrix( const D3DXMATRIX *pMat ); + void MultMatrixLocal( const D3DXMATRIX *pMat ); + HRESULT ScaleLocal(FLOAT x, FLOAT y, FLOAT z); + + // Left multiply the current matrix with the computed rotation + // matrix, counterclockwise about the given axis with the given angle. + // (rotation is about the local origin of the object) + HRESULT RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle); + + // Left multiply the current matrix with the computed translation + // matrix. (transformation is about the local origin of the object) + HRESULT TranslateLocal(FLOAT x, FLOAT y, FLOAT z); +}; + +typedef ID3DXMatrixStack* LPD3DXMATRIXSTACK; + +struct RenderTargetState_t +{ + void clear() { V_memset( this, 0, sizeof( *this ) ); } + + CGLMTex *m_pRenderTargets[4]; + CGLMTex *m_pDepthStencil; + + inline bool RefersTo( CGLMTex * pSurf ) const + { + for ( uint i = 0; i < 4; i++ ) + if ( m_pRenderTargets[i] == pSurf ) + return true; + + if ( m_pDepthStencil == pSurf ) + return true; + + return false; + } + + static inline bool LessFunc( const RenderTargetState_t &lhs, const RenderTargetState_t &rhs ) + { + COMPILE_TIME_ASSERT( sizeof( lhs.m_pRenderTargets[0] ) == sizeof( uint32 ) ); + uint64 lhs0 = reinterpret_cast(lhs.m_pRenderTargets)[0]; + uint64 rhs0 = reinterpret_cast(rhs.m_pRenderTargets)[0]; + if ( lhs0 < rhs0 ) + return true; + else if ( lhs0 == rhs0 ) + { + uint64 lhs1 = reinterpret_cast(lhs.m_pRenderTargets)[1]; + uint64 rhs1 = reinterpret_cast(rhs.m_pRenderTargets)[1]; + if ( lhs1 < rhs1 ) + return true; + else if ( lhs1 == rhs1 ) + { + return lhs.m_pDepthStencil < rhs.m_pDepthStencil; + } + } + return false; + } + + inline bool operator < ( const RenderTargetState_t &rhs ) const + { + return LessFunc( *this, rhs ); + } +}; + +typedef CUtlMap< RenderTargetState_t, CGLMFBO *> CGLMFBOMap; + +class simple_bitmap; + +struct TOGL_CLASS IDirect3DDevice9 : public IUnknown +{ + friend class GLMContext; + friend struct IDirect3DBaseTexture9; + friend struct IDirect3DTexture9; + friend struct IDirect3DCubeTexture9; + friend struct IDirect3DVolumeTexture9; + friend struct IDirect3DSurface9; + friend struct IDirect3DVertexBuffer9; + friend struct IDirect3DIndexBuffer9; + friend struct IDirect3DPixelShader9; + friend struct IDirect3DVertexShader9; + friend struct IDirect3DQuery9; + friend struct IDirect3DVertexDeclaration9; + + IDirect3DDevice9(); + virtual ~IDirect3DDevice9(); + + // Create call invoked from IDirect3D9 + HRESULT TOGLMETHODCALLTYPE Create( IDirect3DDevice9Params *params ); + + // + // Basics + // + HRESULT TOGLMETHODCALLTYPE Reset(D3DPRESENT_PARAMETERS* pPresentationParameters); + HRESULT TOGLMETHODCALLTYPE SetViewport(CONST D3DVIEWPORT9* pViewport); + HRESULT TOGLMETHODCALLTYPE BeginScene(); + HRESULT TOGLMETHODCALLTYPE Clear(DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil); + HRESULT TOGLMETHODCALLTYPE EndScene(); + HRESULT TOGLMETHODCALLTYPE Present(CONST RECT* pSourceRect,CONST RECT* pDestRect,VD3DHWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion); + + // textures + HRESULT TOGLMETHODCALLTYPE CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,VD3DHANDLE* pSharedHandle, char *debugLabel=NULL); + HRESULT TOGLMETHODCALLTYPE CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,VD3DHANDLE* pSharedHandle, char *debugLabel=NULL); + HRESULT TOGLMETHODCALLTYPE CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,VD3DHANDLE* pSharedHandle, char *debugLabel=NULL); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetTexture(DWORD Stage,IDirect3DBaseTexture9* pTexture); + HRESULT TOGLMETHODCALLTYPE SetTextureNonInline(DWORD Stage,IDirect3DBaseTexture9* pTexture); + + HRESULT TOGLMETHODCALLTYPE GetTexture(DWORD Stage,IDirect3DBaseTexture9** ppTexture); + + // render targets, color and depthstencil, surfaces, blit + HRESULT TOGLMETHODCALLTYPE CreateRenderTarget(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle, char *debugLabel=NULL); + HRESULT TOGLMETHODCALLTYPE SetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget); + HRESULT TOGLMETHODCALLTYPE GetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget); + + HRESULT TOGLMETHODCALLTYPE CreateOffscreenPlainSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle); + + HRESULT TOGLMETHODCALLTYPE CreateDepthStencilSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle); + HRESULT TOGLMETHODCALLTYPE SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil); + HRESULT TOGLMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface); + + HRESULT TOGLMETHODCALLTYPE GetRenderTargetData(IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface); // ? is anyone using this ? + HRESULT TOGLMETHODCALLTYPE GetFrontBufferData(UINT iSwapChain,IDirect3DSurface9* pDestSurface); + HRESULT TOGLMETHODCALLTYPE StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter); + + // pixel shaders + HRESULT TOGLMETHODCALLTYPE CreatePixelShader(CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader, const char *pShaderName, char *debugLabel = NULL, const uint32 *pCentroidMask = NULL ); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetPixelShader(IDirect3DPixelShader9* pShader); + HRESULT TOGLMETHODCALLTYPE SetPixelShaderNonInline(IDirect3DPixelShader9* pShader); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount); + HRESULT TOGLMETHODCALLTYPE SetPixelShaderConstantFNonInline(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount); + + HRESULT TOGLMETHODCALLTYPE SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount); + HRESULT TOGLMETHODCALLTYPE SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount); + + // vertex shaders + HRESULT TOGLMETHODCALLTYPE CreateVertexShader(CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader, const char *pShaderName, char *debugLabel = NULL); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexShader(IDirect3DVertexShader9* pShader); + HRESULT TOGLMETHODCALLTYPE SetVertexShaderNonInline(IDirect3DVertexShader9* pShader); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount); + HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantFNonInline(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount); + HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantBNonInline(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount); + HRESULT TOGLMETHODCALLTYPE SetVertexShaderConstantINonInline(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount); + + // POSIX only - preheating for a specific vertex/pixel shader pair - trigger GLSL link inside GLM + HRESULT TOGLMETHODCALLTYPE LinkShaderPair( IDirect3DVertexShader9* vs, IDirect3DPixelShader9* ps ); + HRESULT TOGLMETHODCALLTYPE QueryShaderPair( int index, GLMShaderPairInfo *infoOut ); + + // vertex buffers + HRESULT TOGLMETHODCALLTYPE CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl); + HRESULT TOGLMETHODCALLTYPE SetVertexDeclarationNonInline(IDirect3DVertexDeclaration9* pDecl); + + HRESULT TOGLMETHODCALLTYPE SetFVF(DWORD FVF); // we might not be using these ? + HRESULT TOGLMETHODCALLTYPE GetFVF(DWORD* pFVF); + + HRESULT CreateVertexBuffer(UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,VD3DHANDLE* pSharedHandle); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride); + HRESULT SetStreamSourceNonInline(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride); + + // index buffers + HRESULT TOGLMETHODCALLTYPE CreateIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,VD3DHANDLE* pSharedHandle); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetIndices(IDirect3DIndexBuffer9* pIndexData); + HRESULT TOGLMETHODCALLTYPE SetIndicesNonInline(IDirect3DIndexBuffer9* pIndexData); + + // State management. + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetRenderStateInline(D3DRENDERSTATETYPE State,DWORD Value); + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetRenderStateConstInline(D3DRENDERSTATETYPE State,DWORD Value); + HRESULT TOGLMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State,DWORD Value); + + FORCEINLINE HRESULT TOGLMETHODCALLTYPE SetSamplerState(DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value); + HRESULT TOGLMETHODCALLTYPE SetSamplerStateNonInline(DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value); + + FORCEINLINE void TOGLMETHODCALLTYPE SetSamplerStates(DWORD Sampler, DWORD AddressU, DWORD AddressV, DWORD AddressW, DWORD MinFilter, DWORD MagFilter, DWORD MipFilter ); + void TOGLMETHODCALLTYPE SetSamplerStatesNonInline(DWORD Sampler, DWORD AddressU, DWORD AddressV, DWORD AddressW, DWORD MinFilter, DWORD MagFilter, DWORD MipFilter ); + + // Draw. + HRESULT TOGLMETHODCALLTYPE DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount); + HRESULT TOGLMETHODCALLTYPE DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount); + HRESULT TOGLMETHODCALLTYPE DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride); + + // misc + BOOL TOGLMETHODCALLTYPE ShowCursor(BOOL bShow); + HRESULT TOGLMETHODCALLTYPE ValidateDevice(DWORD* pNumPasses); + HRESULT TOGLMETHODCALLTYPE SetMaterial(CONST D3DMATERIAL9* pMaterial); + HRESULT TOGLMETHODCALLTYPE LightEnable(DWORD Index,BOOL Enable); + HRESULT TOGLMETHODCALLTYPE SetScissorRect(CONST RECT* pRect); + HRESULT TOGLMETHODCALLTYPE CreateQuery(D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery); + HRESULT TOGLMETHODCALLTYPE GetDeviceCaps(D3DCAPS9* pCaps); + HRESULT TOGLMETHODCALLTYPE TestCooperativeLevel(); + HRESULT TOGLMETHODCALLTYPE EvictManagedResources(); + HRESULT TOGLMETHODCALLTYPE SetLight(DWORD Index,CONST D3DLIGHT9*); + void TOGLMETHODCALLTYPE SetGammaRamp(UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp); + + void TOGLMETHODCALLTYPE SaveGLState(); + void TOGLMETHODCALLTYPE RestoreGLState(); + + // Talk to JasonM about this one. It's tricky in GL. + HRESULT TOGLMETHODCALLTYPE SetClipPlane(DWORD Index,CONST float* pPlane); + + // + // + // **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. + // + // + HRESULT TOGLMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix); + HRESULT TOGLMETHODCALLTYPE SetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value); + + void TOGLMETHODCALLTYPE AcquireThreadOwnership( ); + void TOGLMETHODCALLTYPE ReleaseThreadOwnership( ); + inline DWORD TOGLMETHODCALLTYPE GetCurrentOwnerThreadId() const { return m_ctx->m_nCurOwnerThreadId; } + + FORCEINLINE void TOGLMETHODCALLTYPE SetMaxUsedVertexShaderConstantsHint( uint nMaxReg ); + void TOGLMETHODCALLTYPE SetMaxUsedVertexShaderConstantsHintNonInline( uint nMaxReg ); + + void DumpStatsToConsole( const CCommand *pArgs ); + +#if GLMDEBUG + void DumpTextures( const CCommand *pArgs ); +#endif + +private: + IDirect3DDevice9( const IDirect3DDevice9& ); + IDirect3DDevice9& operator= ( const IDirect3DDevice9& ); + + // Flushing changes to GL + void FlushClipPlaneEquation(); + void InitStates(); + void FullFlushStates(); + void UpdateBoundFBO(); + void ResetFBOMap(); + void ScrubFBOMap( CGLMTex *pTex ); + + // response to retired objects (when refcount goes to zero and they self-delete..) + void ReleasedVertexDeclaration( IDirect3DVertexDeclaration9 *pDecl ); + void ReleasedTexture( IDirect3DBaseTexture9 *baseTex ); // called from texture destructor - need to scrub samplers + void ReleasedCGLMTex( CGLMTex *pTex ); + void ReleasedSurface( IDirect3DSurface9 *surface ); // called from any surface destructor - need to scrub RT table if an RT + void ReleasedPixelShader( IDirect3DPixelShader9 *pixelShader ); // called from IDirect3DPixelShader9 destructor + void ReleasedVertexShader( IDirect3DVertexShader9 *vertexShader ); // called from IDirect3DVertexShader9 destructor + void ReleasedVertexBuffer( IDirect3DVertexBuffer9 *vertexBuffer ); // called from IDirect3DVertexBuffer9 destructor + void ReleasedIndexBuffer( IDirect3DIndexBuffer9 *indexBuffer ); // called from IDirect3DIndexBuffer9 destructor + void ReleasedQuery( IDirect3DQuery9 *query ); // called from IDirect3DQuery9 destructor + + // Member variables + + DWORD m_nValidMarker; + + IDirect3DDevice9Params m_params; // mirror of the creation inputs + + // D3D flavor stuff + IDirect3DSurface9 *m_pRenderTargets[4]; + IDirect3DSurface9 *m_pDepthStencil; + + IDirect3DSurface9 *m_pDefaultColorSurface; // default color surface. + IDirect3DSurface9 *m_pDefaultDepthStencilSurface; // queried by GetDepthStencilSurface. + + IDirect3DVertexDeclaration9 *m_pVertDecl; // Set by SetVertexDeclaration... + D3DStreamDesc m_streams[ D3D_MAX_STREAMS ]; // Set by SetStreamSource.. + CGLMBuffer *m_vtx_buffers[ D3D_MAX_STREAMS ]; + CGLMBuffer *m_pDummy_vtx_buffer; + D3DIndexDesc m_indices; // Set by SetIndices.. + + IDirect3DVertexShader9 *m_vertexShader; // Set by SetVertexShader... + IDirect3DPixelShader9 *m_pixelShader; // Set by SetPixelShader... + + IDirect3DBaseTexture9 *m_textures[16]; // set by SetTexture... NULL if stage inactive + D3DSamplerDesc m_samplers[16]; // set by SetSamplerState.. + // GLM flavor stuff + GLMContext *m_ctx; + CGLMFBOMap *m_pFBOs; + bool m_bFBODirty; + + struct ObjectStats_t + { + int m_nTotalFBOs; + int m_nTotalVertexShaders; + int m_nTotalPixelShaders; + int m_nTotalVertexDecls; + int m_nTotalIndexBuffers; + int m_nTotalVertexBuffers; + int m_nTotalRenderTargets; + int m_nTotalTextures; + int m_nTotalSurfaces; + int m_nTotalQueries; + + void clear() { V_memset( this, 0, sizeof(* this ) ); } + + ObjectStats_t &operator -= ( const ObjectStats_t &rhs ) + { + m_nTotalFBOs -= rhs.m_nTotalFBOs; + m_nTotalVertexShaders -= rhs.m_nTotalVertexShaders; + m_nTotalPixelShaders -= rhs.m_nTotalPixelShaders; + m_nTotalVertexDecls -= rhs.m_nTotalVertexDecls; + m_nTotalIndexBuffers -= rhs.m_nTotalIndexBuffers; + m_nTotalVertexBuffers -= rhs.m_nTotalVertexBuffers; + m_nTotalRenderTargets -= rhs.m_nTotalRenderTargets; + m_nTotalTextures -= rhs.m_nTotalTextures; + m_nTotalSurfaces -= rhs.m_nTotalSurfaces; + m_nTotalQueries -= m_nTotalQueries; + return *this; + } + }; + ObjectStats_t m_ObjectStats; + ObjectStats_t m_PrevObjectStats; + void PrintObjectStats( const ObjectStats_t &stats ); + + // GL state + struct + { + // render state buckets + GLAlphaTestEnable_t m_AlphaTestEnable; + GLAlphaTestFunc_t m_AlphaTestFunc; + + GLAlphaToCoverageEnable_t m_AlphaToCoverageEnable; + + GLDepthTestEnable_t m_DepthTestEnable; + GLDepthMask_t m_DepthMask; + GLDepthFunc_t m_DepthFunc; + + GLClipPlaneEnable_t m_ClipPlaneEnable[kGLMUserClipPlanes]; + GLClipPlaneEquation_t m_ClipPlaneEquation[kGLMUserClipPlanes]; + + GLColorMaskSingle_t m_ColorMaskSingle; + GLColorMaskMultiple_t m_ColorMaskMultiple; + + GLCullFaceEnable_t m_CullFaceEnable; + GLCullFrontFace_t m_CullFrontFace; + GLPolygonMode_t m_PolygonMode; + GLDepthBias_t m_DepthBias; + GLScissorEnable_t m_ScissorEnable; + GLScissorBox_t m_ScissorBox; + GLViewportBox_t m_ViewportBox; + GLViewportDepthRange_t m_ViewportDepthRange; + + GLBlendEnable_t m_BlendEnable; + GLBlendFactor_t m_BlendFactor; + GLBlendEquation_t m_BlendEquation; + GLBlendColor_t m_BlendColor; + GLBlendEnableSRGB_t m_BlendEnableSRGB; + + GLStencilTestEnable_t m_StencilTestEnable; + GLStencilFunc_t m_StencilFunc; + GLStencilOp_t m_StencilOp; + GLStencilWriteMask_t m_StencilWriteMask; + + GLClearColor_t m_ClearColor; + GLClearDepth_t m_ClearDepth; + GLClearStencil_t m_ClearStencil; + + bool m_FogEnable; // not really pushed to GL, just latched here + + // samplers + GLMTexSamplingParams m_samplers[ 16 ]; + } gl; + +#if GL_BATCH_PERF_ANALYSIS + simple_bitmap *m_pBatch_vis_bitmap; + uint m_nBatchVisY; + uint m_nBatchVisFrameIndex, m_nBatchVisFileIdx; + uint m_nNumProgramChanges; + + uint m_nTotalD3DCalls; + double m_flTotalD3DTime; + uint m_nTotalGLCalls; + double m_flTotalGLTime; + uint m_nTotalPrims; + + uint m_nOverallProgramChanges; + uint m_nOverallDraws; + uint m_nOverallPrims; + uint m_nOverallD3DCalls; + double m_flOverallD3DTime; + uint m_nOverallGLCalls; + double m_flOverallGLTime; + + double m_flOverallPresentTime; + double m_flOverallPresentTimeSquared; + double m_flOverallSwapWindowTime; + double m_flOverallSwapWindowTimeSquared; + uint m_nOverallPresents; +#endif +}; + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value ) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetSamplerStateNonInline( Sampler, Type, Value ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + Assert( Sampler < 16 ); + + m_ctx->SetSamplerDirty( Sampler ); + + switch( Type ) + { + case D3DSAMP_ADDRESSU: + m_ctx->SetSamplerAddressU( Sampler, Value ); + break; + case D3DSAMP_ADDRESSV: + m_ctx->SetSamplerAddressV( Sampler, Value ); + break; + case D3DSAMP_ADDRESSW: + m_ctx->SetSamplerAddressW( Sampler, Value ); + break; + case D3DSAMP_BORDERCOLOR: + m_ctx->SetSamplerBorderColor( Sampler, Value ); + break; + case D3DSAMP_MAGFILTER: + m_ctx->SetSamplerMagFilter( Sampler, Value ); + break; + case D3DSAMP_MIPFILTER: + m_ctx->SetSamplerMipFilter( Sampler, Value ); + break; + case D3DSAMP_MINFILTER: + m_ctx->SetSamplerMinFilter( Sampler, Value ); + break; + case D3DSAMP_MIPMAPLODBIAS: + m_ctx->SetSamplerMipMapLODBias( Sampler, Value ); + break; + case D3DSAMP_MAXMIPLEVEL: + m_ctx->SetSamplerMaxMipLevel( Sampler, Value); + break; + case D3DSAMP_MAXANISOTROPY: + m_ctx->SetSamplerMaxAnisotropy( Sampler, Value); + break; + case D3DSAMP_SRGBTEXTURE: + m_samplers[ Sampler ].m_srgb = Value; + m_ctx->SetSamplerSRGBTexture(Sampler, Value); + break; + case D3DSAMP_SHADOWFILTER: + m_ctx->SetShadowFilter(Sampler, Value); + break; + + default: DXABSTRACT_BREAK_ON_ERROR(); break; + } + return S_OK; +#endif +} + +FORCEINLINE void TOGLMETHODCALLTYPE IDirect3DDevice9::SetSamplerStates( + DWORD Sampler, DWORD AddressU, DWORD AddressV, DWORD AddressW, + DWORD MinFilter, DWORD MagFilter, DWORD MipFilter ) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + SetSamplerStatesNonInline( Sampler, AddressU, AddressV, AddressW, MinFilter, MagFilter, MipFilter ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + Assert( Sampler < 16); + + m_ctx->SetSamplerDirty( Sampler ); + + m_ctx->SetSamplerStates( Sampler, AddressU, AddressV, AddressW, MinFilter, MagFilter, MipFilter ); +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetTexture(DWORD Stage,IDirect3DBaseTexture9* pTexture) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetTextureNonInline( Stage, pTexture ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_textures[Stage] = pTexture; + m_ctx->SetSamplerTex( Stage, pTexture ? pTexture->m_tex : NULL ); + return S_OK; +#endif +} + +inline GLenum D3DCompareFuncToGL( DWORD function ) +{ + switch ( function ) + { + case D3DCMP_NEVER : return GL_NEVER; // Always fail the test. + case D3DCMP_LESS : return GL_LESS; // Accept the new pixel if its value is less than the value of the current pixel. + case D3DCMP_EQUAL : return GL_EQUAL; // Accept the new pixel if its value equals the value of the current pixel. + case D3DCMP_LESSEQUAL : return GL_LEQUAL; // Accept the new pixel if its value is less than or equal to the value of the current pixel. ** + case D3DCMP_GREATER : return GL_GREATER; // Accept the new pixel if its value is greater than the value of the current pixel. + case D3DCMP_NOTEQUAL : return GL_NOTEQUAL; // Accept the new pixel if its value does not equal the value of the current pixel. + case D3DCMP_GREATEREQUAL: return GL_GEQUAL; // Accept the new pixel if its value is greater than or equal to the value of the current pixel. + case D3DCMP_ALWAYS : return GL_ALWAYS; // Always pass the test. + default : DXABSTRACT_BREAK_ON_ERROR(); return 0xFFFFFFFF; + } +} + +FORCEINLINE GLenum D3DBlendOperationToGL( DWORD operation ) +{ + switch (operation) + { + case D3DBLENDOP_ADD : return GL_FUNC_ADD; // The result is the destination added to the source. Result = Source + Destination + + /* not covered by dxabstract.h.. + case D3DBLENDOP_SUBTRACT : return GL_FUNC_SUBTRACT; // The result is the destination subtracted from to the source. Result = Source - Destination + case D3DBLENDOP_REVSUBTRACT : return GL_FUNC_REVERSE_SUBTRACT; // The result is the source subtracted from the destination. Result = Destination - Source + case D3DBLENDOP_MIN : return GL_MIN; // The result is the minimum of the source and destination. Result = MIN(Source, Destination) + case D3DBLENDOP_MAX : return GL_MAX; // The result is the maximum of the source and destination. Result = MAX(Source, Destination) + */ + default: + DXABSTRACT_BREAK_ON_ERROR(); + return 0xFFFFFFFF; + break; + } +} + +FORCEINLINE GLenum D3DBlendFactorToGL( DWORD equation ) +{ + switch (equation) + { + case D3DBLEND_ZERO : return GL_ZERO; // Blend factor is (0, 0, 0, 0). + case D3DBLEND_ONE : return GL_ONE; // Blend factor is (1, 1, 1, 1). + case D3DBLEND_SRCCOLOR : return GL_SRC_COLOR; // Blend factor is (Rs, Gs, Bs, As). + case D3DBLEND_INVSRCCOLOR : return GL_ONE_MINUS_SRC_COLOR; // Blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As). + case D3DBLEND_SRCALPHA : return GL_SRC_ALPHA; // Blend factor is (As, As, As, As). + case D3DBLEND_INVSRCALPHA : return GL_ONE_MINUS_SRC_ALPHA; // Blend factor is ( 1 - As, 1 - As, 1 - As, 1 - As). + case D3DBLEND_DESTALPHA : return GL_DST_ALPHA; // Blend factor is (Ad Ad Ad Ad). + case D3DBLEND_INVDESTALPHA : return GL_ONE_MINUS_DST_ALPHA; // Blend factor is (1 - Ad 1 - Ad 1 - Ad 1 - Ad). + case D3DBLEND_DESTCOLOR : return GL_DST_COLOR; // Blend factor is (Rd, Gd, Bd, Ad). + case D3DBLEND_INVDESTCOLOR : return GL_ONE_MINUS_DST_COLOR; // Blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad). + case D3DBLEND_SRCALPHASAT : return GL_SRC_ALPHA_SATURATE; // Blend factor is (f, f, f, 1); where f = min(As, 1 - Ad). + + /* + // these are weird.... break if we hit them + case D3DBLEND_BOTHSRCALPHA : Assert(0); return GL_ZERO; // Obsolete. Starting with DirectX 6, you can achieve the same effect by setting the source and destination blend factors to D3DBLEND_SRCALPHA and D3DBLEND_INVSRCALPHA in separate calls. + case D3DBLEND_BOTHINVSRCALPHA: Assert(0); return GL_ZERO; // Source blend factor is (1 - As, 1 - As, 1 - As, 1 - As), and destination blend factor is (As, As, As, As); the destination blend selection is overridden. This blend mode is supported only for the D3DRS_SRCBLEND render state. + case D3DBLEND_BLENDFACTOR : Assert(0); return GL_ZERO; // Constant color blending factor used by the frame-buffer blender. This blend mode is supported only if D3DPBLENDCAPS_BLENDFACTOR is set in the SrcBlendCaps or DestBlendCaps members of D3DCAPS9. + + dxabstract.h has not heard of these, so let them hit the debugger if they come through + case D3DBLEND_INVBLENDFACTOR: //Inverted constant color-blending factor used by the frame-buffer blender. This blend mode is supported only if the D3DPBLENDCAPS_BLENDFACTOR bit is set in the SrcBlendCaps or DestBlendCaps members of D3DCAPS9. + case D3DBLEND_SRCCOLOR2: // Blend factor is (PSOutColor[1]r, PSOutColor[1]g, PSOutColor[1]b, not used). This flag is available in Direct3D 9Ex only. + case D3DBLEND_INVSRCCOLOR2: // Blend factor is (1 - PSOutColor[1]r, 1 - PSOutColor[1]g, 1 - PSOutColor[1]b, not used)). This flag is available in Direct3D 9Ex only. + */ + default: + DXABSTRACT_BREAK_ON_ERROR(); + return 0xFFFFFFFF; + break; + } +} + + +FORCEINLINE GLenum D3DStencilOpToGL( DWORD operation ) +{ + switch( operation ) + { + case D3DSTENCILOP_KEEP : return GL_KEEP; + case D3DSTENCILOP_ZERO : return GL_ZERO; + case D3DSTENCILOP_REPLACE : return GL_REPLACE; + case D3DSTENCILOP_INCRSAT : return GL_INCR; + case D3DSTENCILOP_DECRSAT : return GL_DECR; + case D3DSTENCILOP_INVERT : return GL_INVERT; + case D3DSTENCILOP_INCR : return GL_INCR_WRAP_EXT; + case D3DSTENCILOP_DECR : return GL_DECR_WRAP_EXT; + default : DXABSTRACT_BREAK_ON_ERROR(); return 0xFFFFFFFF; + } +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetRenderStateInline( D3DRENDERSTATETYPE State, DWORD Value ) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetRenderState( State, Value ); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + + switch (State) + { + case D3DRS_ZENABLE: // kGLDepthTestEnable + { + gl.m_DepthTestEnable.enable = Value; + m_ctx->WriteDepthTestEnable( &gl.m_DepthTestEnable ); + break; + } + case D3DRS_ZWRITEENABLE: // kGLDepthMask + { + gl.m_DepthMask.mask = Value; + m_ctx->WriteDepthMask( &gl.m_DepthMask ); + break; + } + case D3DRS_ZFUNC: + { + // kGLDepthFunc + GLenum func = D3DCompareFuncToGL( Value ); + gl.m_DepthFunc.func = func; + m_ctx->WriteDepthFunc( &gl.m_DepthFunc ); + break; + } + case D3DRS_COLORWRITEENABLE: // kGLColorMaskSingle + { + gl.m_ColorMaskSingle.r = ((Value & D3DCOLORWRITEENABLE_RED) != 0) ? 0xFF : 0x00; + gl.m_ColorMaskSingle.g = ((Value & D3DCOLORWRITEENABLE_GREEN)!= 0) ? 0xFF : 0x00; + gl.m_ColorMaskSingle.b = ((Value & D3DCOLORWRITEENABLE_BLUE) != 0) ? 0xFF : 0x00; + gl.m_ColorMaskSingle.a = ((Value & D3DCOLORWRITEENABLE_ALPHA)!= 0) ? 0xFF : 0x00; + m_ctx->WriteColorMaskSingle( &gl.m_ColorMaskSingle ); + break; + } + case D3DRS_CULLMODE: // kGLCullFaceEnable / kGLCullFrontFace + { + switch (Value) + { + case D3DCULL_NONE: + { + gl.m_CullFaceEnable.enable = false; + gl.m_CullFrontFace.value = GL_CCW; //doesn't matter + + m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable ); + m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace ); + break; + } + + case D3DCULL_CW: + { + gl.m_CullFaceEnable.enable = true; + gl.m_CullFrontFace.value = GL_CW; //origGL_CCW; + + m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable ); + m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace ); + break; + } + case D3DCULL_CCW: + { + gl.m_CullFaceEnable.enable = true; + gl.m_CullFrontFace.value = GL_CCW; //origGL_CW; + + m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable ); + m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace ); + break; + } + default: + { + DXABSTRACT_BREAK_ON_ERROR(); + break; + } + } + break; + } + //-------------------------------------------------------------------------------------------- alphablend stuff + case D3DRS_ALPHABLENDENABLE: // kGLBlendEnable + { + gl.m_BlendEnable.enable = Value; + m_ctx->WriteBlendEnable( &gl.m_BlendEnable ); + break; + } + case D3DRS_BLENDOP: // kGLBlendEquation // D3D blend-op ==> GL blend equation + { + GLenum equation = D3DBlendOperationToGL( Value ); + gl.m_BlendEquation.equation = equation; + m_ctx->WriteBlendEquation( &gl.m_BlendEquation ); + break; + } + case D3DRS_SRCBLEND: // kGLBlendFactor // D3D blend-factor ==> GL blend factor + case D3DRS_DESTBLEND: // kGLBlendFactor + { + GLenum factor = D3DBlendFactorToGL( Value ); + + if (State==D3DRS_SRCBLEND) + { + gl.m_BlendFactor.srcfactor = factor; + } + else + { + gl.m_BlendFactor.dstfactor = factor; + } + m_ctx->WriteBlendFactor( &gl.m_BlendFactor ); + break; + } + case D3DRS_SRGBWRITEENABLE: // kGLBlendEnableSRGB + { + gl.m_BlendEnableSRGB.enable = Value; + m_ctx->WriteBlendEnableSRGB( &gl.m_BlendEnableSRGB ); + break; + } + //-------------------------------------------------------------------------------------------- alphatest stuff + case D3DRS_ALPHATESTENABLE: + { + gl.m_AlphaTestEnable.enable = Value; + m_ctx->WriteAlphaTestEnable( &gl.m_AlphaTestEnable ); + break; + } + case D3DRS_ALPHAREF: + { + gl.m_AlphaTestFunc.ref = Value / 255.0f; + m_ctx->WriteAlphaTestFunc( &gl.m_AlphaTestFunc ); + break; + } + case D3DRS_ALPHAFUNC: + { + GLenum func = D3DCompareFuncToGL( Value );; + gl.m_AlphaTestFunc.func = func; + m_ctx->WriteAlphaTestFunc( &gl.m_AlphaTestFunc ); + break; + } + //-------------------------------------------------------------------------------------------- stencil stuff + case D3DRS_STENCILENABLE: // GLStencilTestEnable_t + { + gl.m_StencilTestEnable.enable = Value; + m_ctx->WriteStencilTestEnable( &gl.m_StencilTestEnable ); + break; + } + case D3DRS_STENCILFAIL: // GLStencilOp_t "what do you do if stencil test fails" + { + GLenum stencilop = D3DStencilOpToGL( Value ); + gl.m_StencilOp.sfail = stencilop; + + m_ctx->WriteStencilOp( &gl.m_StencilOp,0 ); + m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this + break; + } + case D3DRS_STENCILZFAIL: // GLStencilOp_t "what do you do if stencil test passes *but* depth test fails, if depth test happened" + { + GLenum stencilop = D3DStencilOpToGL( Value ); + gl.m_StencilOp.dpfail = stencilop; + + m_ctx->WriteStencilOp( &gl.m_StencilOp,0 ); + m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this + break; + } + case D3DRS_STENCILPASS: // GLStencilOp_t "what do you do if stencil test and depth test both pass" + { + GLenum stencilop = D3DStencilOpToGL( Value ); + gl.m_StencilOp.dppass = stencilop; + + m_ctx->WriteStencilOp( &gl.m_StencilOp,0 ); + m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this + break; + } + case D3DRS_STENCILFUNC: // GLStencilFunc_t + { + GLenum stencilfunc = D3DCompareFuncToGL( Value ); + gl.m_StencilFunc.frontfunc = gl.m_StencilFunc.backfunc = stencilfunc; + + m_ctx->WriteStencilFunc( &gl.m_StencilFunc ); + break; + } + case D3DRS_STENCILREF: // GLStencilFunc_t + { + gl.m_StencilFunc.ref = Value; + m_ctx->WriteStencilFunc( &gl.m_StencilFunc ); + break; + } + case D3DRS_STENCILMASK: // GLStencilFunc_t + { + gl.m_StencilFunc.mask = Value; + m_ctx->WriteStencilFunc( &gl.m_StencilFunc ); + break; + } + case D3DRS_STENCILWRITEMASK: // GLStencilWriteMask_t + { + gl.m_StencilWriteMask.mask = Value; + m_ctx->WriteStencilWriteMask( &gl.m_StencilWriteMask ); + break; + } + case D3DRS_FOGENABLE: // none of these are implemented yet... erk + { + gl.m_FogEnable = (Value != 0); + GLMPRINTF(("-D- fogenable = %d",Value )); + break; + } + case D3DRS_SCISSORTESTENABLE: // kGLScissorEnable + { + gl.m_ScissorEnable.enable = Value; + m_ctx->WriteScissorEnable( &gl.m_ScissorEnable ); + break; + } + case D3DRS_DEPTHBIAS: // kGLDepthBias + { + // the value in the dword is actually a float + float fvalue = *(float*)&Value; + gl.m_DepthBias.units = fvalue; + + m_ctx->WriteDepthBias( &gl.m_DepthBias ); + break; + } + // good ref on these: http://aras-p.info/blog/2008/06/12/depth-bias-and-the-power-of-deceiving-yourself/ + case D3DRS_SLOPESCALEDEPTHBIAS: + { + // the value in the dword is actually a float + float fvalue = *(float*)&Value; + gl.m_DepthBias.factor = fvalue; + + m_ctx->WriteDepthBias( &gl.m_DepthBias ); + break; + } + // Alpha to coverage + case D3DRS_ADAPTIVETESS_Y: + { + gl.m_AlphaToCoverageEnable.enable = Value; + m_ctx->WriteAlphaToCoverageEnable( &gl.m_AlphaToCoverageEnable ); + break; + } + case D3DRS_CLIPPLANEENABLE: // kGLClipPlaneEnable + { + // d3d packs all the enables into one word. + // we break that out so we don't do N glEnable calls to sync - + // GLM is tracking one unique enable per plane. + for( int i=0; iWriteClipPlaneEnable( &gl.m_ClipPlaneEnable[x], x ); + break; + } + //-------------------------------------------------------------------------------------------- polygon/fill mode + case D3DRS_FILLMODE: + { + GLuint mode = 0; + switch(Value) + { + case D3DFILL_POINT: mode = GL_POINT; break; + case D3DFILL_WIREFRAME: mode = GL_LINE; break; + case D3DFILL_SOLID: mode = GL_FILL; break; + default: DXABSTRACT_BREAK_ON_ERROR(); break; + } + gl.m_PolygonMode.values[0] = gl.m_PolygonMode.values[1] = mode; + m_ctx->WritePolygonMode( &gl.m_PolygonMode ); + break; + } + } + + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetRenderStateConstInline( D3DRENDERSTATETYPE State, DWORD Value ) +{ + // State is a compile time constant - luckily no need to do anything special to get the compiler to optimize this case. + return SetRenderStateInline( State, Value ); +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetIndices(IDirect3DIndexBuffer9* pIndexData) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetIndicesNonInline( pIndexData ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + // just latch it. + m_indices.m_idxBuffer = pIndexData; + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetStreamSourceNonInline( StreamNumber, pStreamData, OffsetInBytes, Stride ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + Assert( StreamNumber < D3D_MAX_STREAMS ); + Assert( ( Stride & 3 ) == 0 ); // we support non-DWORD aligned strides, but on some drivers (like AMD's) perf goes off a cliff + + // perfectly legal to see a vertex buffer of NULL get passed in here. + // so we need an array to track these. + // OK, we are being given the stride, we don't need to calc it.. + + GLMPRINTF(("-X- IDirect3DDevice9::SetStreamSource setting stream #%d to D3D buf %p (GL name %d); offset %d, stride %d", StreamNumber, pStreamData, (pStreamData) ? pStreamData->m_vtxBuffer->m_name: -1, OffsetInBytes, Stride)); + + if ( !pStreamData ) + { + OffsetInBytes = 0; + Stride = 0; + + m_vtx_buffers[ StreamNumber ] = m_pDummy_vtx_buffer; + } + else + { + // We do not support strides of 0 + Assert( Stride > 0 ); + m_vtx_buffers[ StreamNumber ] = pStreamData->m_vtxBuffer; + } + + m_streams[ StreamNumber ].m_vtxBuffer = pStreamData; + m_streams[ StreamNumber ].m_offset = OffsetInBytes; + m_streams[ StreamNumber ].m_stride = Stride; + + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) // groups of 4 floats! +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexShaderConstantFNonInline( StartRegister, pConstantData, Vector4fCount ); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetProgramParametersF( kGLMVertexProgram, StartRegister, (float *)pConstantData, Vector4fCount ); + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexShaderConstantBNonInline( StartRegister, pConstantData, BoolCount ); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetProgramParametersB( kGLMVertexProgram, StartRegister, (int *)pConstantData, BoolCount ); + return S_OK; +#endif +} + +FORCEINLINE HRESULT IDirect3DDevice9::SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) // groups of 4 ints! +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexShaderConstantINonInline( StartRegister, pConstantData, Vector4iCount ); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetProgramParametersI( kGLMVertexProgram, StartRegister, (int *)pConstantData, Vector4iCount ); + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetPixelShaderConstantFNonInline(StartRegister, pConstantData, Vector4fCount); +#else + TOGL_NULL_DEVICE_CHECK; + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetProgramParametersF( kGLMFragmentProgram, StartRegister, (float *)pConstantData, Vector4fCount ); + return S_OK; +#endif +} + +HRESULT IDirect3DDevice9::SetVertexShader(IDirect3DVertexShader9* pShader) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexShaderNonInline(pShader); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetVertexProgram( pShader ? pShader->m_vtxProgram : NULL ); + m_vertexShader = pShader; + return S_OK; +#endif +} + +FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetPixelShader(IDirect3DPixelShader9* pShader) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetPixelShaderNonInline(pShader); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetFragmentProgram( pShader ? pShader->m_pixProgram : NULL ); + m_pixelShader = pShader; + return S_OK; +#endif +} + +FORCEINLINE HRESULT IDirect3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetVertexDeclarationNonInline(pDecl); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_pVertDecl = pDecl; + return S_OK; +#endif +} + +FORCEINLINE void IDirect3DDevice9::SetMaxUsedVertexShaderConstantsHint( uint nMaxReg ) +{ +#if GLMDEBUG || GL_BATCH_PERF_ANALYSIS + return SetMaxUsedVertexShaderConstantsHintNonInline( nMaxReg ); +#else + Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + m_ctx->SetMaxUsedVertexShaderConstantsHint( nMaxReg ); +#endif +} + +// ------------------------------------------------------------------------------------------------------------------------------ // +// D3DX +// ------------------------------------------------------------------------------------------------------------------------------ // +struct ID3DXInclude +{ + virtual HRESULT Open(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes); + virtual HRESULT Close(LPCVOID pData); +}; +typedef ID3DXInclude* LPD3DXINCLUDE; + + +struct TOGL_CLASS ID3DXBuffer : public IUnknown +{ + void* GetBufferPointer(); + DWORD GetBufferSize(); +}; + +typedef ID3DXBuffer* LPD3DXBUFFER; + +class ID3DXConstantTable : public IUnknown +{ +}; +typedef ID3DXConstantTable* LPD3DXCONSTANTTABLE; + +TOGL_INTERFACE const char* D3DXGetPixelShaderProfile( IDirect3DDevice9 *pDevice ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); +TOGL_INTERFACE D3DXVECTOR3* D3DXVec3TransformCoord( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack); +TOGL_INTERFACE void D3DXMatrixIdentity( D3DXMATRIX * ); + +TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Subtract( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + return pOut; +} + +TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Cross( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + D3DXVECTOR3 v; + + v.x = pV1->y * pV2->z - pV1->z * pV2->y; + v.y = pV1->z * pV2->x - pV1->x * pV2->z; + v.z = pV1->x * pV2->y - pV1->y * pV2->x; + + *pOut = v; + return pOut; +} + +TOGL_INTERFACE D3DXINLINE FLOAT D3DXVec3Dot( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; +} + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP); + +TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM ); + + +TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z ); + +// Build an ortho projection matrix. (right-handed) +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf ); + +// Transform a plane by a matrix. The vector (a,b,c) must be normal. +// M should be the inverse transpose of the transformation desired. +TOGL_INTERFACE D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE IDirect3D9 *Direct3DCreate9(UINT SDKVersion); + +TOGL_INTERFACE void D3DPERF_SetOptions( DWORD dwOptions ); + +TOGL_INTERFACE HRESULT D3DXCompileShader( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +// fake D3D usage constant for SRGB tex creation +#define D3DUSAGE_TEXTURE_SRGB (0x80000000L) + +#else + + //USE_ACTUAL_DX + #ifndef WIN32 + #error sorry man + #endif + + #ifdef _X360 + #include "d3d9.h" + #include "d3dx9.h" + #else + #include + #include "../../dx9sdk/include/d3d9.h" + #include "../../dx9sdk/include/d3dx9.h" + #endif + typedef HWND VD3DHWND; + +#endif // DX_TO_GL_ABSTRACTION + +#endif // DXABSTRACT_H diff --git a/sp/src/public/togl/linuxwin/dxabstract_types.h b/sp/src/public/togl/linuxwin/dxabstract_types.h new file mode 100644 index 00000000..c021ca78 --- /dev/null +++ b/sp/src/public/togl/linuxwin/dxabstract_types.h @@ -0,0 +1,1712 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// dxabstract_types.h +// +//================================================================================================== +#ifndef DXABSTRACT_TYPES_H +#define DXABSTRACT_TYPES_H + +#pragma once + +#if GL_BATCH_PERF_ANALYSIS + class simple_bitmap; +#endif + +struct IUnknown; +struct IDirect3D9; +struct IDirect3DDevice9; +struct IDirect3DResource9; +struct IDirect3DBaseTexture9; +struct IDirect3DTexture9; +struct IDirect3DCubeTexture9; +struct IDirect3DVolumeTexture9; +struct IDirect3DSurface9; +struct IDirect3DVertexDeclaration9; +struct IDirect3DQuery9; +struct IDirect3DVertexBuffer9; +struct IDirect3DIndexBuffer9; +struct IDirect3DPixelShader9; +struct IDirect3DVertexShader9; +struct IDirect3DDevice9Params; + +class GLMContext; +struct GLMRect; +struct GLMShaderPairInfo; +class CGLMBuffer; +class CGLMQuery; +class CGLMTex; +class CGLMProgram; +class CGLMFBO; + +#ifdef TOGL_DLL_EXPORT + #define TOGL_INTERFACE DLL_EXPORT + #define TOGL_OVERLOAD DLL_GLOBAL_EXPORT + #define TOGL_CLASS DLL_CLASS_EXPORT + #define TOGL_GLOBAL DLL_GLOBAL_EXPORT +#else + #define TOGL_INTERFACE DLL_IMPORT + #define TOGL_OVERLOAD DLL_GLOBAL_IMPORT + #define TOGL_CLASS DLL_CLASS_IMPORT + #define TOGL_GLOBAL DLL_GLOBAL_IMPORT +#endif + +#ifdef OSX +#error "Do not use this header's types on OSX until togo is ported to Mac!" +#endif + +#define TOGLMETHODCALLTYPE __stdcall +//#define TOGLMETHODCALLTYPE + +#define DXABSTRACT_BREAK_ON_ERROR() DebuggerBreak() + +typedef void* VD3DHWND; +typedef void* VD3DHANDLE; + +#define MAKEFOURCC(ch0, ch1, ch2, ch3) ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) + +// +// +// Stuff that would be in windows.h +// +// +#if !defined(_WINNT_) + + typedef int INT; + typedef unsigned long ULONG; + typedef long LONG; + typedef float FLOAT; + typedef unsigned int DWORD; + typedef unsigned short WORD; + typedef long long LONGLONG; + typedef unsigned int UINT; + typedef long HRESULT; + typedef unsigned char BYTE; + #define CONST const + + #if defined(POSIX) + typedef size_t ULONG_PTR; + #else + typedef unsigned long ULONG_PTR; + #endif + + typedef ULONG_PTR SIZE_T; + + typedef const char* LPCSTR; + typedef char* LPSTR; + typedef DWORD* LPDWORD; + + #define ZeroMemory RtlZeroMemory + #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length)) + + typedef union _LARGE_INTEGER + { + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + LONGLONG QuadPart; + } LARGE_INTEGER; + + typedef struct _GUID + { + bool operator==( const struct _GUID &other ) const; + + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; + } GUID; + + typedef struct _RECT + { + int left; + int top; + int right; + int bottom; + } RECT; + + typedef struct tagPOINT + { + LONG x; + LONG y; + } POINT, *PPOINT, *LPPOINT; + + typedef struct _MEMORYSTATUS + { + DWORD dwLength; + SIZE_T dwTotalPhys; + } MEMORYSTATUS, *LPMEMORYSTATUS; + + typedef DWORD COLORREF; + #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) + + #define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + + #define S_FALSE ((HRESULT)0x00000001L) + #define S_OK 0 + #define E_FAIL ((HRESULT)0x80004005L) + #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) + + #define FAILED(hr) ((HRESULT)(hr) < 0) + #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) + + struct RGNDATA + { + }; + + typedef const void* LPCVOID; +#endif + +//----------------------------------------------------------------------------- + +typedef enum _D3DFORMAT D3DFORMAT; + +#define D3DSI_OPCODE_MASK 0x0000FFFF +#define D3DSP_TEXTURETYPE_MASK 0x78000000 + +#define D3DUSAGE_AUTOGENMIPMAP 0x00000400L +#define D3DSP_DCL_USAGE_MASK 0x0000000f + +#define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000 +#define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16 + + +/* Flags to construct D3DRS_COLORWRITEENABLE */ +#define D3DCOLORWRITEENABLE_RED (1L<<0) +#define D3DCOLORWRITEENABLE_GREEN (1L<<1) +#define D3DCOLORWRITEENABLE_BLUE (1L<<2) +#define D3DCOLORWRITEENABLE_ALPHA (1L<<3) + +#define D3DSGR_NO_CALIBRATION 0x00000000L + +#define D3DXINLINE inline + +#define D3D_SDK_VERSION 32 + +#define _FACD3D 0x876 +#define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) + +#define D3DERR_NOTFOUND MAKE_D3DHRESULT(2150) +#define D3DERR_DEVICELOST MAKE_D3DHRESULT(2152) +#define D3DERR_NOTAVAILABLE MAKE_D3DHRESULT(2154) +#define D3DERR_DEVICENOTRESET MAKE_D3DHRESULT(2153) +#define D3DERR_INVALIDCALL MAKE_D3DHRESULT(2156) +#define D3DERR_DRIVERINTERNALERROR MAKE_D3DHRESULT(2087) +#define D3DERR_OUTOFVIDEOMEMORY MAKE_D3DHRESULT(380) +#define D3D_OK S_OK + +#define D3DPRESENT_RATE_DEFAULT 0x00000000 + +// +// DevCaps +// +// we need to see who in Source land is interested in these values, as dxabstract is currently reporting zero for the whole Caps word +#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ +#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ +#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ +#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */ +#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */ +#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */ +#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */ +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */ +#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */ +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ +#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */ +#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */ +#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */ + +// +// PrimitiveMiscCaps +// +#define D3DPMISCCAPS_MASKZ 0x00000002L +#define D3DPMISCCAPS_CULLNONE 0x00000010L +#define D3DPMISCCAPS_CULLCW 0x00000020L +#define D3DPMISCCAPS_CULLCCW 0x00000040L +#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L +#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */ +#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */ +#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */ +#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */ +#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */ +#define D3DPMISCCAPS_PERSTAGECONSTANT 0x00008000L /* Device supports per-stage constants */ +#define D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS 0x00040000L /* Device supports different bit depths for MRT */ +#define D3DPMISCCAPS_FOGVERTEXCLAMPED 0x00100000L /* Device clamps fog blend factor per vertex */ + +// Flags field for Issue +#define D3DISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled". +#define D3DISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginng of a query. + + +#define D3DPRESENT_INTERVAL_ONE 0x00000001L +#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L + +/* + * Options for clearing + */ +#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ +#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ +#define D3DCLEAR_STENCIL 0x00000004l /* Clear stencil planes */ + + +#define D3DENUM_WHQL_LEVEL 0x00000002L + + + + +#define D3DPTEXTURECAPS_NOPROJECTEDBUMPENV 0x00200000L /* Device does not support projected bump env lookup operation + in programmable and fixed function pixel shaders */ +#define D3DDEVCAPS2_STREAMOFFSET 0x00000001L /* Device supports offsets in streams. Must be set by DX9 drivers */ + +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ + +#define D3DCREATE_PUREDEVICE 0x00000010L +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0x00000020L +#define D3DCREATE_HARDWARE_VERTEXPROCESSING 0x00000040L +#define D3DCREATE_FPU_PRESERVE 0x00000002L +#define D3DPRASTERCAPS_FOGRANGE 0x00010000L +#define D3DPRASTERCAPS_FOGTABLE 0x00000100L +#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L +#define D3DPRASTERCAPS_WFOG 0x00100000L +#define D3DPRASTERCAPS_ZFOG 0x00200000L +#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L +#define D3DPRASTERCAPS_WBUFFER 0x00040000L +#define D3DPRASTERCAPS_ZTEST 0x00000010L + +// +// Caps2 +// +#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L +#define D3DPRASTERCAPS_SCISSORTEST 0x01000000L +#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */ +#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */ +#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */ +#define D3DCREATE_MULTITHREADED 0x00000004L +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L +#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L +#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */ +#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */ +#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L +#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */ +#define D3DTEXOPCAPS_ADD 0x00000040L +#define D3DTEXOPCAPS_MODULATE2X 0x00000010L +#define D3DPRASTERCAPS_DEPTHBIAS 0x04000000L +#define D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS 0x02000000L +#define D3DVTXPCAPS_TEXGEN_SPHEREMAP 0x00000100L /* device supports D3DTSS_TCI_SPHEREMAP */ +#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L + +// The following usages are valid only for querying CheckDeviceFormat +#define D3DUSAGE_QUERY_SRGBREAD (0x00010000L) +#define D3DUSAGE_QUERY_FILTER (0x00020000L) +#define D3DUSAGE_QUERY_SRGBWRITE (0x00040000L) +#define D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING (0x00080000L) +#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) + +/* Usages for Vertex/Index buffers */ +#define D3DUSAGE_WRITEONLY (0x00000008L) +#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) +#define D3DUSAGE_DONOTCLIP (0x00000020L) +#define D3DUSAGE_POINTS (0x00000040L) +#define D3DUSAGE_RTPATCHES (0x00000080L) +#define D3DUSAGE_NPATCHES (0x00000100L) + + +// Flags field for GetData +#define D3DGETDATA_FLUSH (1 << 0) // Tells the runtime to flush if the query is outstanding. + +#define D3DFVF_XYZ 0x002 + + +#define D3DTA_SELECTMASK 0x0000000f // mask for arg selector +#define D3DTA_DIFFUSE 0x00000000 // select diffuse color (read only) +#define D3DTA_CURRENT 0x00000001 // select stage destination register (read/write) +#define D3DTA_TEXTURE 0x00000002 // select texture color (read only) +#define D3DTA_TFACTOR 0x00000003 // select D3DRS_TEXTUREFACTOR (read only) +#define D3DTA_SPECULAR 0x00000004 // select specular color (read only) +#define D3DTA_TEMP 0x00000005 // select temporary register color (read/write) +#define D3DTA_CONSTANT 0x00000006 // select texture stage constant +#define D3DTA_COMPLEMENT 0x00000010 // take 1.0 - x (read modifier) +#define D3DTA_ALPHAREPLICATE 0x00000020 // replicate alpha to color components (read modifier) + + +#define D3DUSAGE_RENDERTARGET (0x00000001L) +#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) +#define D3DUSAGE_QUERY_FILTER (0x00020000L) +#define D3DUSAGE_DEPTHSTENCIL (0x00000002L) +#define D3DUSAGE_WRITEONLY (0x00000008L) +#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) +#define D3DUSAGE_DYNAMIC (0x00000200L) + +#define D3DSI_INSTLENGTH_MASK 0x0F000000 +#define D3DSI_INSTLENGTH_SHIFT 24 +#define D3DSP_TEXTURETYPE_SHIFT 27 +#define D3DSP_REGTYPE_SHIFT 28 +#define D3DSP_REGTYPE_SHIFT2 8 +#define D3DSP_REGTYPE_MASK 0x70000000 +#define D3DSP_REGTYPE_MASK2 0x00001800 + +#define D3DSP_REGNUM_MASK 0x000007FF + +#define D3DSP_DSTMOD_SHIFT 20 +#define D3DSP_DSTMOD_MASK 0x00F00000 +#define D3DSPDM_MSAMPCENTROID (4<>8)&0xFF) +#define D3DSHADER_VERSION_MINOR(_Version) (((_Version)>>0)&0xFF) + +#define D3DSHADER_ADDRESSMODE_SHIFT 13 +#define D3DSHADER_ADDRESSMODE_MASK (1 << D3DSHADER_ADDRESSMODE_SHIFT) + +#define D3DPS_END() 0x0000FFFF + +// ps_2_0 texld controls +#define D3DSI_TEXLD_PROJECT (0x01 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) +#define D3DSI_TEXLD_BIAS (0x02 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) + + +// destination parameter write mask +#define D3DSP_WRITEMASK_0 0x00010000 // Component 0 (X;Red) +#define D3DSP_WRITEMASK_1 0x00020000 // Component 1 (Y;Green) +#define D3DSP_WRITEMASK_2 0x00040000 // Component 2 (Z;Blue) +#define D3DSP_WRITEMASK_3 0x00080000 // Component 3 (W;Alpha) +#define D3DSP_WRITEMASK_ALL 0x000F0000 // All Components + +#define D3DVS_SWIZZLE_SHIFT 16 +#define D3DVS_SWIZZLE_MASK 0x00FF0000 + +// The following bits define where to take component X from: + +#define D3DVS_X_X (0 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_Y (1 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_Z (2 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_W (3 << D3DVS_SWIZZLE_SHIFT) + +// The following bits define where to take component Y from: + +#define D3DVS_Y_X (0 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_Y (1 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_Z (2 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_W (3 << (D3DVS_SWIZZLE_SHIFT + 2)) + +// The following bits define where to take component Z from: + +#define D3DVS_Z_X (0 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_Y (1 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_Z (2 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_W (3 << (D3DVS_SWIZZLE_SHIFT + 4)) + +// The following bits define where to take component W from: + +#define D3DVS_W_X (0 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_Y (1 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_Z (2 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_W (3 << (D3DVS_SWIZZLE_SHIFT + 6)) + +// source parameter modifiers +#define D3DSP_SRCMOD_SHIFT 24 +#define D3DSP_SRCMOD_MASK 0x0F000000 + +// ------------------------------------------------------------------------------------------------------------------------------ // +// ENUMS +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef enum _D3DSHADER_PARAM_SRCMOD_TYPE +{ + D3DSPSM_NONE = 0<= 2.0 + + + D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 + D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) + D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) + D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) + D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) + D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) + D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) + D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) + D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values + D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. +} D3DDECLTYPE; + +typedef enum _D3DDECLMETHOD +{ + D3DDECLMETHOD_DEFAULT = 0, + D3DDECLMETHOD_PARTIALU, + D3DDECLMETHOD_PARTIALV, + D3DDECLMETHOD_CROSSUV, // Normal + D3DDECLMETHOD_UV, + D3DDECLMETHOD_LOOKUP, // Lookup a displacement map + D3DDECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map +} D3DDECLMETHOD; + +typedef enum _D3DDECLUSAGE +{ + D3DDECLUSAGE_POSITION = 0, + D3DDECLUSAGE_BLENDWEIGHT = 1, + D3DDECLUSAGE_BLENDINDICES = 2, + D3DDECLUSAGE_NORMAL = 3, + D3DDECLUSAGE_PSIZE = 4, + D3DDECLUSAGE_TEXCOORD = 5, + D3DDECLUSAGE_TANGENT = 6, + D3DDECLUSAGE_BINORMAL = 7, + D3DDECLUSAGE_TESSFACTOR = 8, + D3DDECLUSAGE_PLUGH = 9, // mystery value + D3DDECLUSAGE_COLOR = 10, + D3DDECLUSAGE_FOG = 11, + D3DDECLUSAGE_DEPTH = 12, + D3DDECLUSAGE_SAMPLE = 13, +} D3DDECLUSAGE; + +typedef enum _D3DPRIMITIVETYPE +{ + D3DPT_POINTLIST = 1, + D3DPT_LINELIST = 2, + D3DPT_TRIANGLELIST = 4, + D3DPT_TRIANGLESTRIP = 5, + D3DPT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DPRIMITIVETYPE; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// STRUCTURES +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef struct TOGL_CLASS D3DXPLANE +{ + float& operator[]( int i ); + bool operator==( const D3DXPLANE &o ); + bool operator!=( const D3DXPLANE &o ); + operator float*(); + operator const float*() const; + + float a, b, c, d; +} D3DXPLANE; + +typedef enum _D3DVERTEXBLENDFLAGS +{ + D3DVBF_DISABLE = 0, // Disable vertex blending + D3DVBF_1WEIGHTS = 1, // 2 matrix blending + D3DVBF_2WEIGHTS = 2, // 3 matrix blending + D3DVBF_3WEIGHTS = 3, // 4 matrix blending + D3DVBF_TWEENING = 255, // blending using D3DRS_TWEENFACTOR + D3DVBF_0WEIGHTS = 256, // one matrix is used with weight 1.0 + D3DVBF_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} D3DVERTEXBLENDFLAGS; + +typedef struct _D3DINDEXBUFFER_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + UINT Size; +} D3DINDEXBUFFER_DESC; + +typedef struct _D3DVERTEXELEMENT9 +{ + WORD Stream; // Stream index + WORD Offset; // Offset in the stream in bytes + BYTE Type; // Data type + BYTE Method; // Processing method + BYTE Usage; // Semantics + BYTE UsageIndex; // Semantic index +} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; + + +#define MAX_DEVICE_IDENTIFIER_STRING 512 +typedef struct _D3DADAPTER_IDENTIFIER9 +{ + char Driver[MAX_DEVICE_IDENTIFIER_STRING]; + char Description[MAX_DEVICE_IDENTIFIER_STRING]; + char DeviceName[32]; /* Device name for GDI (ex. \\.\DISPLAY1) */ + + LARGE_INTEGER DriverVersion; /* Defined for 32 bit components */ + + DWORD VendorId; + DWORD DeviceId; + DWORD SubSysId; + DWORD Revision; + DWORD VideoMemory; + +} D3DADAPTER_IDENTIFIER9; + +typedef struct _D3DCOLORVALUE +{ + float r; + float g; + float b; + float a; +} D3DCOLORVALUE; + +typedef struct _D3DMATERIAL9 +{ + D3DCOLORVALUE Diffuse; /* Diffuse color RGBA */ + D3DCOLORVALUE Ambient; /* Ambient color RGB */ + D3DCOLORVALUE Specular; /* Specular 'shininess' */ + D3DCOLORVALUE Emissive; /* Emissive color RGB */ + float Power; /* Sharpness if specular highlight */ +} D3DMATERIAL9; + +typedef struct _D3DVOLUME_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + + UINT Width; + UINT Height; + UINT Depth; +} D3DVOLUME_DESC; + +typedef struct _D3DVIEWPORT9 +{ + DWORD X; + DWORD Y; /* Viewport Top left */ + DWORD Width; + DWORD Height; /* Viewport Dimensions */ + float MinZ; /* Min/max of clip Volume */ + float MaxZ; +} D3DVIEWPORT9; + +typedef struct _D3DPSHADERCAPS2_0 +{ + DWORD Caps; + INT DynamicFlowControlDepth; + INT NumTemps; + INT StaticFlowControlDepth; + INT NumInstructionSlots; +} D3DPSHADERCAPS2_0; + +typedef struct _D3DCAPS9 +{ + /* Device Info */ + D3DDEVTYPE DeviceType; + + /* Caps from DX7 Draw */ + DWORD Caps; + DWORD Caps2; + + /* Cursor Caps */ + DWORD CursorCaps; + + /* 3D Device Caps */ + DWORD DevCaps; + + DWORD PrimitiveMiscCaps; + DWORD RasterCaps; + DWORD TextureCaps; + DWORD TextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DTexture9's + + DWORD MaxTextureWidth, MaxTextureHeight; + DWORD MaxVolumeExtent; + + DWORD MaxTextureAspectRatio; + DWORD MaxAnisotropy; + + DWORD TextureOpCaps; + DWORD MaxTextureBlendStages; + DWORD MaxSimultaneousTextures; + + DWORD VertexProcessingCaps; + DWORD MaxActiveLights; + DWORD MaxUserClipPlanes; + DWORD MaxVertexBlendMatrices; + DWORD MaxVertexBlendMatrixIndex; + + DWORD MaxPrimitiveCount; // max number of primitives per DrawPrimitive call + DWORD MaxStreams; + + DWORD VertexShaderVersion; + DWORD MaxVertexShaderConst; // number of vertex shader constant registers + + DWORD PixelShaderVersion; + + // Here are the DX9 specific ones + DWORD DevCaps2; + D3DPSHADERCAPS2_0 PS20Caps; + + DWORD NumSimultaneousRTs; // Will be at least 1 + DWORD MaxVertexShader30InstructionSlots; + DWORD MaxPixelShader30InstructionSlots; + + // only on Posix/GL + DWORD FakeSRGBWrite; // 1 for parts which can't support SRGB writes due to driver issues - 0 for others + DWORD MixedSizeTargets; // 1 for parts which can mix attachment sizes (RT's color vs depth) + DWORD CanDoSRGBReadFromRTs; // 0 when we're on Leopard, 1 when on Snow Leopard +} D3DCAPS9; + +typedef struct _D3DDISPLAYMODE +{ + UINT Width; + UINT Height; + UINT RefreshRate; + D3DFORMAT Format; +} D3DDISPLAYMODE; + +typedef struct _D3DGAMMARAMP +{ + WORD red [256]; + WORD green[256]; + WORD blue [256]; +} D3DGAMMARAMP; + + +/* Resize Optional Parameters */ +typedef struct _D3DPRESENT_PARAMETERS_ +{ + UINT BackBufferWidth; + UINT BackBufferHeight; + D3DFORMAT BackBufferFormat; + UINT BackBufferCount; + + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + + D3DSWAPEFFECT SwapEffect; + VD3DHWND hDeviceWindow; + BOOL Windowed; + BOOL EnableAutoDepthStencil; + D3DFORMAT AutoDepthStencilFormat; + DWORD Flags; + + /* FullScreen_RefreshRateInHz must be zero for Windowed mode */ + UINT FullScreen_RefreshRateInHz; + UINT PresentationInterval; +} D3DPRESENT_PARAMETERS; + +typedef struct _D3DDEVICE_CREATION_PARAMETERS +{ + UINT AdapterOrdinal; + D3DDEVTYPE DeviceType; + VD3DHWND hFocusWindow; + DWORD BehaviorFlags; +} D3DDEVICE_CREATION_PARAMETERS; + +/* Structures for LockBox */ +typedef struct _D3DBOX +{ + UINT Left; + UINT Top; + UINT Right; + UINT Bottom; + UINT Front; + UINT Back; +} D3DBOX; + +typedef struct _D3DLOCKED_BOX +{ + INT RowPitch; + INT SlicePitch; + void* pBits; +} D3DLOCKED_BOX; + +typedef struct _D3DSURFACE_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + UINT Width; + UINT Height; +} D3DSURFACE_DESC; + + +typedef struct _D3DLOCKED_RECT +{ + INT Pitch; + void* pBits; +} D3DLOCKED_RECT; + + +typedef struct _D3DRASTER_STATUS +{ + BOOL InVBlank; + UINT ScanLine; +} D3DRASTER_STATUS; + +typedef enum _D3DLIGHTTYPE +{ + D3DLIGHT_POINT = 1, + D3DLIGHT_SPOT = 2, + D3DLIGHT_DIRECTIONAL = 3, + D3DLIGHT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DLIGHTTYPE; + +typedef struct TOGL_CLASS _D3DVECTOR +{ + float x; + float y; + float z; +} D3DVECTOR; + +class TOGL_CLASS D3DXVECTOR2 +{ +public: + operator FLOAT* (); + operator CONST FLOAT* () const; + + float x,y; +}; + +class TOGL_CLASS D3DXVECTOR3 : public D3DVECTOR +{ +public: + D3DXVECTOR3() {} + D3DXVECTOR3( float a, float b, float c ); + operator FLOAT* (); + operator CONST FLOAT* () const; +}; + +typedef enum _D3DXINCLUDE_TYPE +{ + D3DXINC_LOCAL, + + // force 32-bit size enum + D3DXINC_FORCE_DWORD = 0x7fffffff + +} D3DXINCLUDE_TYPE; + +typedef struct _D3DLIGHT9 +{ + D3DLIGHTTYPE Type; /* Type of light source */ + D3DCOLORVALUE Diffuse; /* Diffuse color of light */ + D3DCOLORVALUE Specular; /* Specular color of light */ + D3DCOLORVALUE Ambient; /* Ambient color of light */ + D3DVECTOR Position; /* Position in world space */ + D3DVECTOR Direction; /* Direction in world space */ + float Range; /* Cutoff range */ + float Falloff; /* Falloff */ + float Attenuation0; /* Constant attenuation */ + float Attenuation1; /* Linear attenuation */ + float Attenuation2; /* Quadratic attenuation */ + float Theta; /* Inner angle of spotlight cone */ + float Phi; /* Outer angle of spotlight cone */ +} D3DLIGHT9; + +class TOGL_CLASS D3DXVECTOR4 +{ +public: + D3DXVECTOR4() {} + D3DXVECTOR4( float a, float b, float c, float d ); + + float x,y,z,w; +}; + +//---------------------------------------------------------------------------- +// D3DXMACRO: +// ---------- +// Preprocessor macro definition. The application pass in a NULL-terminated +// array of this structure to various D3DX APIs. This enables the application +// to #define tokens at runtime, before the file is parsed. +//---------------------------------------------------------------------------- + +typedef struct _D3DXMACRO +{ + LPCSTR Name; + LPCSTR Definition; + +} D3DXMACRO, *LPD3DXMACRO; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// ------------------------------------------------------------------------------------------------------------------------------ // +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +// +// Also look for any functions marked with "**** FIXED FUNCTION STUFF" +// +// It's only laying around here so we don't have to chop up the shader system a lot to strip out the fixed function code paths. +// ------------------------------------------------------------------------------------------------------------------------------ // +// ------------------------------------------------------------------------------------------------------------------------------ // + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTRANSFORMSTATETYPE +{ + D3DTS_VIEW = 2, + D3DTS_PROJECTION = 3, + D3DTS_TEXTURE0 = 16, + D3DTS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTRANSFORMSTATETYPE; + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTEXTUREOP +{ + // Control + D3DTOP_DISABLE = 1, // disables stage + D3DTOP_SELECTARG1 = 2, // the default + D3DTOP_SELECTARG2 = 3, + + // Modulate + D3DTOP_MODULATE = 4, // multiply args together + D3DTOP_MODULATE2X = 5, // multiply and 1 bit + D3DTOP_MODULATE4X = 6, // multiply and 2 bits + + // Add + D3DTOP_ADD = 7, // add arguments together + D3DTOP_ADDSIGNED = 8, // add with -0.5 bias + D3DTOP_ADDSIGNED2X = 9, // as above but left 1 bit + D3DTOP_SUBTRACT = 10, // Arg1 - Arg2, with no saturation + D3DTOP_ADDSMOOTH = 11, // add 2 args, subtract product + // Arg1 + Arg2 - Arg1*Arg2 + // = Arg1 + (1-Arg1)*Arg2 + + // Linear alpha blend: Arg1*(Alpha) + Arg2*(1-Alpha) + D3DTOP_BLENDDIFFUSEALPHA = 12, // iterated alpha + D3DTOP_BLENDTEXTUREALPHA = 13, // texture alpha + D3DTOP_BLENDFACTORALPHA = 14, // alpha from D3DRS_TEXTUREFACTOR + + // Linear alpha blend with pre-multiplied arg1 input: Arg1 + Arg2*(1-Alpha) + D3DTOP_BLENDTEXTUREALPHAPM = 15, // texture alpha + D3DTOP_BLENDCURRENTALPHA = 16, // by alpha of current color + + // Specular mapping + D3DTOP_PREMODULATE = 17, // modulate with next texture before use + D3DTOP_MODULATEALPHA_ADDCOLOR = 18, // Arg1.RGB + Arg1.A*Arg2.RGB + // COLOROP only + D3DTOP_MODULATECOLOR_ADDALPHA = 19, // Arg1.RGB*Arg2.RGB + Arg1.A + // COLOROP only + D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20, // (1-Arg1.A)*Arg2.RGB + Arg1.RGB + // COLOROP only + D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21, // (1-Arg1.RGB)*Arg2.RGB + Arg1.A + // COLOROP only + + // Bump mapping + D3DTOP_BUMPENVMAP = 22, // per pixel env map perturbation + D3DTOP_BUMPENVMAPLUMINANCE = 23, // with luminance channel + + // This can do either diffuse or specular bump mapping with correct input. + // Performs the function (Arg1.R*Arg2.R + Arg1.G*Arg2.G + Arg1.B*Arg2.B) + // where each component has been scaled and offset to make it signed. + // The result is replicated into all four (including alpha) channels. + // This is a valid COLOROP only. + D3DTOP_DOTPRODUCT3 = 24, + + // Triadic ops + D3DTOP_MULTIPLYADD = 25, // Arg0 + Arg1*Arg2 + D3DTOP_LERP = 26, // (Arg0)*Arg1 + (1-Arg0)*Arg2 + + D3DTOP_FORCE_DWORD = 0x7fffffff, +} D3DTEXTUREOP; + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTEXTURESTAGESTATETYPE +{ + D3DTSS_COLOROP = 1, /* D3DTEXTUREOP - per-stage blending controls for color channels */ + D3DTSS_COLORARG1 = 2, /* D3DTA_* (texture arg) */ + D3DTSS_COLORARG2 = 3, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAOP = 4, /* D3DTEXTUREOP - per-stage blending controls for alpha channel */ + D3DTSS_ALPHAARG1 = 5, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAARG2 = 6, /* D3DTA_* (texture arg) */ + D3DTSS_BUMPENVMAT00 = 7, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT01 = 8, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT10 = 9, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT11 = 10, /* float (bump mapping matrix) */ + D3DTSS_TEXCOORDINDEX = 11, /* identifies which set of texture coordinates index this texture */ + D3DTSS_BUMPENVLOFFSET = 23, /* float offset for bump map luminance */ + D3DTSS_TEXTURETRANSFORMFLAGS = 24, /* D3DTEXTURETRANSFORMFLAGS controls texture transform */ + D3DTSS_COLORARG0 = 26, /* D3DTA_* third arg for triadic ops */ + D3DTSS_RESULTARG = 28, /* D3DTA_* arg for result (CURRENT or TEMP) */ + + + D3DTSS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTEXTURESTAGESTATETYPE; + +//===========================================================================// + +enum GLMVertexAttributeIndex +{ + kGLMGenericAttr00 = 0, + kGLMGenericAttr01, + kGLMGenericAttr02, + kGLMGenericAttr03, + kGLMGenericAttr04, + kGLMGenericAttr05, + kGLMGenericAttr06, + kGLMGenericAttr07, + kGLMGenericAttr08, + kGLMGenericAttr09, + kGLMGenericAttr10, + kGLMGenericAttr11, + kGLMGenericAttr12, + kGLMGenericAttr13, + kGLMGenericAttr14, + kGLMGenericAttr15, + + kGLMVertexAttributeIndexMax // ideally < 32 +}; + +struct GLMVertexAttributeDesc // all the info you need to do vertex setup for one attribute +{ + CGLMBuffer *m_pBuffer; // NULL allowed in which case m_offset is the full 32-bit pointer.. so you can draw from plain RAM if desired + GLuint m_nCompCount; // comp count of the attribute (1-4) + GLenum m_datatype; // data type of the attribute (GL_FLOAT, GL_UNSIGNED_BYTE, etc) + GLuint m_stride; + GLuint m_offset; // net offset to attribute 'zero' within the buffer. + GLuint m_streamOffset; // net offset to attribute 'zero' within the buffer. + GLboolean m_normalized; // apply to any fixed point data that needs normalizing, esp color bytes + + inline uint GetDataTypeSizeInBytes() const + { + switch ( m_datatype ) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return 1; + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_HALF_FLOAT: + return 2; + case GL_INT: + case GL_FLOAT: + return 4; + default: + Assert( 0 ); + break; + } + return 0; + } + + inline uint GetTotalAttributeSizeInBytes() const { Assert( m_nCompCount ); return m_nCompCount * GetDataTypeSizeInBytes(); } + + // may need a seed value at some point to be able to disambiguate re-lifed buffers holding same pointer + // simpler alternative is to do shoot-down inside the vertex/index buffer free calls. + // I'd rather not have to have each attribute fiddling a ref count on the buffer to which it refers.. + +//#define EQ(fff) ( (src.fff) == (fff) ) + // test in decreasing order of likelihood of difference, but do not include the buffer revision as caller is not supplying it.. + //inline bool operator== ( const GLMVertexAttributeDesc& src ) const { return EQ( m_pBuffer ) && EQ( m_offset ) && EQ( m_stride ) && EQ( m_datatype ) && EQ( m_normalized ) && EQ( m_nCompCount ); } +//#undef EQ + + uint m_bufferRevision; // only set in GLM context's copy, to disambiguate references that are same offset / same buffer but cross an orphan event +}; + +#define MAX_D3DVERTEXELEMENTS 16 + +struct D3DVERTEXELEMENT9_GL +{ + // fields right out of the original decl element (copied) + D3DVERTEXELEMENT9 m_dxdecl; // d3d info + // WORD Stream; // Stream index + // WORD Offset; // Offset in the stream in bytes + // BYTE Type; // Data type + // BYTE Method; // Processing method + // BYTE Usage; // Semantics + // BYTE UsageIndex; // Semantic index + + GLMVertexAttributeDesc m_gldecl; + // CGLMBuffer *m_buffer; // late-dropped from selected stream desc (left NULL, will replace with stream source buffer at sync time) + // GLuint m_datasize; // component count (1,2,3,4) of the attrib + // GLenum m_datatype; // data type of the attribute (GL_FLOAT et al) + // GLuint m_stride; // late-dropped from stream desc + // GLuint m_offset; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. + // GLuint m_normalized; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. +}; + +struct IDirect3DDevice9Params +{ + UINT m_adapter; + D3DDEVTYPE m_deviceType; + VD3DHWND m_focusWindow; + DWORD m_behaviorFlags; + D3DPRESENT_PARAMETERS m_presentationParameters; +}; + +#define D3D_MAX_STREAMS 4 +struct D3DStreamDesc +{ + IDirect3DVertexBuffer9 *m_vtxBuffer; + uint m_offset; + uint m_stride; +}; + +struct D3DIndexDesc +{ + IDirect3DIndexBuffer9 *m_idxBuffer; +}; + +// we latch sampler values until draw time and then convert them all to GL form +// note these are similar in name to the fields of a GLMTexSamplingParams but contents are not +// particularly in the texture filtering area + +struct D3DSamplerDesc +{ + DWORD m_srgb; // D3DSAMP_SRGBTEXTURE 0 = no SRGB sampling +}; + +// Tracking and naming sampler dimensions +#define SAMPLER_TYPE_2D 0 +#define SAMPLER_TYPE_CUBE 1 +#define SAMPLER_TYPE_3D 2 +#define SAMPLER_TYPE_UNUSED 3 + +#endif // DXABSTRACT_TYPES_H diff --git a/sp/src/public/togl/linuxwin/glbase.h b/sp/src/public/togl/linuxwin/glbase.h new file mode 100644 index 00000000..445d3665 --- /dev/null +++ b/sp/src/public/togl/linuxwin/glbase.h @@ -0,0 +1,104 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glbase.h +// +//=============================================================================== + +#ifndef GLBASE_H +#define GLBASE_H + +#ifdef DX_TO_GL_ABSTRACTION + +#undef HAVE_GL_ARB_SYNC + +#ifndef OSX + #define HAVE_GL_ARB_SYNC 1 +#endif + +#ifdef OSX + #include + #include + #include + #include + #include + #include + #include + #include +#elif defined(DX_TO_GL_ABSTRACTION) + #include + #include +#else + #error +#endif + +#ifdef DX_TO_GL_ABSTRACTION + #ifndef WIN32 + #define Debugger DebuggerBreak + #endif + #undef CurrentTime + + // prevent some conflicts in SDL headers... + #undef M_PI + #include + #ifndef _STDINT_H_ + #define _STDINT_H_ 1 + #endif +#endif + +//=============================================================================== +// glue to call out to Obj-C land (these are in glmgrcocoa.mm) +#ifdef OSX + bool NewNSGLContext( unsigned long *attribs, PseudoNSGLContextPtr nsglShareCtx, PseudoNSGLContextPtr *nsglCtxOut, CGLContextObj *cglCtxOut ); + CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx ); + void DelNSGLContext( PseudoNSGLContextPtr nsglCtx ); +#endif + +// Set TOGL_SUPPORT_NULL_DEVICE to 1 to support the NULL ref device +#define TOGL_SUPPORT_NULL_DEVICE 0 + +#if TOGL_SUPPORT_NULL_DEVICE + #define TOGL_NULL_DEVICE_CHECK if( m_params.m_deviceType == D3DDEVTYPE_NULLREF ) return S_OK; + #define TOGL_NULL_DEVICE_CHECK_RET_VOID if( m_params.m_deviceType == D3DDEVTYPE_NULLREF ) return; +#else + #define TOGL_NULL_DEVICE_CHECK + #define TOGL_NULL_DEVICE_CHECK_RET_VOID +#endif + +// GL_ENABLE_INDEX_VERIFICATION enables index range verification on all dynamic IB/VB's (obviously slow) +#define GL_ENABLE_INDEX_VERIFICATION 0 + +// GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION (currently win32 only) - If 1, VirtualAlloc/VirtualProtect is used to detect cases where the app locks a buffer, copies the ptr away, unlocks, then tries to later write to the buffer. +#define GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION 0 + +#define GL_BATCH_TELEMETRY_ZONES 0 + +// GL_BATCH_PERF_ANALYSIS - Enables gl_batch_vis, and various per-batch telemetry statistics messages. +#define GL_BATCH_PERF_ANALYSIS 0 +#define GL_BATCH_PERF_ANALYSIS_WRITE_PNGS 0 + +// GL_TELEMETRY_ZONES - Causes every single OpenGL call to generate a telemetry event +#define GL_TELEMETRY_ZONES 0 + +// GL_DUMP_ALL_API_CALLS - Causes a debug message to be printed for every API call if s_bDumpCalls bool is set to 1 +#define GL_DUMP_ALL_API_CALLS 0 + +// Must also enable PIX_ENABLE to use GL_TELEMETRY_GPU_ZONES. +#define GL_TELEMETRY_GPU_ZONES 0 + +// Records global # of OpenGL calls/total cycles spent inside GL +#define GL_TRACK_API_TIME GL_BATCH_PERF_ANALYSIS + +#define GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS ( GL_TELEMETRY_ZONES || GL_TRACK_API_TIME || GL_DUMP_ALL_API_CALLS ) + +#if GL_BATCH_PERF_ANALYSIS + #define GL_BATCH_PERF(...) __VA_ARGS__ +#else + #define GL_BATCH_PERF(...) +#endif + +#define kGLMUserClipPlanes 2 +#define kGLMScratchFBOCount 4 + +#endif // DX_TO_GL_ABSTRACTION + +#endif // GLBASE_H diff --git a/sp/src/public/togl/linuxwin/glentrypoints.h b/sp/src/public/togl/linuxwin/glentrypoints.h new file mode 100644 index 00000000..d1347175 --- /dev/null +++ b/sp/src/public/togl/linuxwin/glentrypoints.h @@ -0,0 +1,378 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glentrypoints.h +// +//=============================================================================== + +#ifndef GLENTRYPOINTS_H +#define GLENTRYPOINTS_H + +#pragma once + +#ifdef DX_TO_GL_ABSTRACTION + +#include "tier0/platform.h" +#include "tier0/dynfunction.h" +#include "tier0/vprof_telemetry.h" +#include "interface.h" + +#include "togl/rendermechanism.h" + +void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback=NULL); + +#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS +class CGLExecuteHelperBase +{ +public: + inline void StartCall(const char *pName); + inline void StopCall(const char *pName); +#if GL_TRACK_API_TIME + TmU64 m_nStartTime; +#endif +}; + +template < class FunctionType, typename Result > +class CGLExecuteHelper : public CGLExecuteHelperBase +{ +public: + inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } + + inline operator Result() const { return m_Result; } + inline operator char*() const { return (char*)m_Result; } + + FunctionType m_pFn; + + Result m_Result; +}; + +template < class FunctionType> +class CGLExecuteHelper : public CGLExecuteHelperBase +{ +public: + inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } + + FunctionType m_pFn; +}; +#endif + +template < class FunctionType, typename Result > +class CDynamicFunctionOpenGLBase +{ +public: + // Construct with a NULL function pointer. You must manually call + // Lookup() before you can call a dynamic function through this interface. + CDynamicFunctionOpenGLBase() : m_pFn(NULL) {} + + // Construct and do a lookup right away. You will need to make sure that + // the lookup actually succeeded, as the gl library might have failed to load + // or (fn) might not exist in it. + CDynamicFunctionOpenGLBase(const char *fn, FunctionType fallback=NULL) : m_pFn(NULL) + { + Lookup(fn, fallback); + } + + // Construct and do a lookup right away. See comments in Lookup() about what (okay) does. + CDynamicFunctionOpenGLBase(const char *fn, bool &okay, FunctionType fallback=NULL) : m_pFn(NULL) + { + Lookup(fn, okay, fallback); + } + + // Load library if necessary, look up symbol. Returns true and sets + // m_pFn on successful lookup, returns false otherwise. If the + // function pointer is already looked up, this return true immediately. + // Use Reset() first if you want to look up the symbol again. + // This function will return false immediately unless (okay) is true. + // This allows you to chain lookups like this: + // bool okay = true; + // x.Lookup(lib, "x", okay); + // y.Lookup(lib, "y", okay); + // z.Lookup(lib, "z", okay); + // if (okay) { printf("All functions were loaded successfully!\n"); } + // If you supply a fallback, it'll be used if the lookup fails (and if + // non-NULL, means this will always return (okay)). + bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) + { + if (!okay) + return false; + else if (this->m_pFn == NULL) + { + this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, false, (void *) fallback); + this->SetFuncName( fn ); + } + okay = m_pFn != NULL; + return okay; + } + + // Load library if necessary, look up symbol. Returns true and sets + // m_pFn on successful lookup, returns false otherwise. If the + // function pointer is already looked up, this return true immediately. + // Use Reset() first if you want to look up the symbol again. + // This function will return false immediately unless (okay) is true. + // If you supply a fallback, it'll be used if the lookup fails (and if + // non-NULL, means this will always return true). + bool Lookup(const char *fn, FunctionType fallback=NULL) + { + bool okay = true; + return Lookup(fn, okay, fallback); + } + + // Invalidates the current lookup. Makes the function pointer NULL. You + // will need to call Lookup() before you can call a dynamic function + // through this interface again. + void Reset() { m_pFn = NULL; } + + // Force this to be a specific function pointer. + void Force(FunctionType ptr) { m_pFn = ptr; } + + // Retrieve the actual function pointer. + FunctionType Pointer() const { return m_pFn; } + +#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS + #if GL_TELEMETRY_ZONES || GL_DUMP_ALL_API_CALLS + #define GL_FUNC_NAME m_szName + #else + #define GL_FUNC_NAME "" + #endif + + inline CGLExecuteHelper operator() () const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME ); } + + template + inline CGLExecuteHelper operator() (T a) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a); } + + template + inline CGLExecuteHelper operator() (T a, U b) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c ) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i, C j) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i, j); } +#else + operator FunctionType() const { return m_pFn; } +#endif + + // Can be used to verify that we have an actual function looked up and + // ready to call: if (!MyDynFunc) { printf("Function not found!\n"); } + operator bool () const { return m_pFn != NULL; } + bool operator !() const { return m_pFn == NULL; } + +protected: + FunctionType m_pFn; + +#if GL_TELEMETRY_ZONES || GL_DUMP_ALL_API_CALLS + char m_szName[32]; + inline void SetFuncName(const char *pFn) { V_strncpy( m_szName, pFn, sizeof( m_szName ) ); } +#else + inline void SetFuncName(const char *pFn) { (void)pFn; } +#endif +}; + +// This works a lot like CDynamicFunctionMustInit, but we use SDL_GL_GetProcAddress(). +template < const bool bRequired, class FunctionType, typename Result > +class CDynamicFunctionOpenGL : public CDynamicFunctionOpenGLBase< FunctionType, Result > +{ +private: // forbid default constructor. + CDynamicFunctionOpenGL() {} + +public: + CDynamicFunctionOpenGL(const char *fn, FunctionType fallback=NULL) + { + bool okay = true; + Lookup(fn, okay, fallback); + this->SetFuncName( fn ); + } + + CDynamicFunctionOpenGL(const char *fn, bool &okay, FunctionType fallback=NULL) + { + Lookup(fn, okay, fallback); + this->SetFuncName( fn ); + } + + // Please note this is not virtual. + // !!! FIXME: we might want to fall back and try "EXT" or "ARB" versions in some case. + bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) + { + if (this->m_pFn == NULL) + { + this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, bRequired, (void *) fallback); + this->SetFuncName( fn ); + } + return okay; + } +}; + +enum GLDriverStrings_t +{ + cGLVendorString, + cGLRendererString, + cGLVersionString, + cGLExtensionsString, + + cGLTotalDriverStrings +}; + +enum GLDriverProvider_t +{ + cGLDriverProviderUnknown, + cGLDriverProviderNVIDIA, + cGLDriverProviderAMD, + cGLDriverProviderIntel, + cGLDriverProviderIntelOpenSource, + cGLDriverProviderApple, + + cGLTotalDriverProviders +}; + +// This provides all the entry points for a given OpenGL context. +// ENTRY POINTS ARE ONLY VALID FOR THE CONTEXT THAT WAS CURRENT WHEN +// YOU LOOKED THEM UP. 99% of the time, this is not a problem, but +// that 1% is really hard to track down. Always access the GL +// through this class! +class COpenGLEntryPoints +{ + COpenGLEntryPoints( const COpenGLEntryPoints & ); + COpenGLEntryPoints &operator= ( const COpenGLEntryPoints & ); + +public: + // The GL context you are looking up entry points for must be current when you construct this object! + COpenGLEntryPoints(); + ~COpenGLEntryPoints(); + + void ClearEntryPoints(); + + uint64 m_nTotalGLCycles, m_nTotalGLCalls; + + int m_nOpenGLVersionMajor; // if GL_VERSION is 2.1.0, this will be set to 2. + int m_nOpenGLVersionMinor; // if GL_VERSION is 2.1.0, this will be set to 1. + int m_nOpenGLVersionPatch; // if GL_VERSION is 2.1.0, this will be set to 0. + bool m_bHave_OpenGL; + + char *m_pGLDriverStrings[cGLTotalDriverStrings]; + GLDriverProvider_t m_nDriverProvider; + + #define GL_EXT(x,glmajor,glminor) bool m_bHave_##x; + #define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn; + #define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn; + #include "togl/glfuncs.inl" + #undef GL_FUNC_VOID + #undef GL_FUNC + #undef GL_EXT + + bool HasSwapTearExtension() const + { +#ifdef _WIN32 + return m_bHave_WGL_EXT_swap_control_tear; +#else + return m_bHave_GLX_EXT_swap_control_tear; +#endif + } +}; + +// This will be set to the current OpenGL context's entry points. +extern COpenGLEntryPoints *gGL; +typedef void * (*GL_GetProcAddressCallbackFunc_t)(const char *, bool &, const bool, void *); + +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); + DLL_EXPORT void ToGLDisconnectLibraries(); + DLL_EXPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); + DLL_EXPORT void ClearOpenGLEntryPoints(); +#else + DLL_IMPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); + DLL_IMPORT void ToGLDisconnectLibraries(); + DLL_IMPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); + DLL_IMPORT void ClearOpenGLEntryPoints(); +#endif + +#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS +inline void CGLExecuteHelperBase::StartCall(const char *pName) +{ + (void)pName; + +#if GL_TELEMETRY_ZONES + tmEnter( TELEMETRY_LEVEL3, TMZF_NONE, pName ); +#endif + +#if GL_TRACK_API_TIME + m_nStartTime = tmFastTime(); +#endif + +#if GL_DUMP_ALL_API_CALLS + static bool s_bDumpCalls; + if ( s_bDumpCalls ) + { + char buf[128]; + buf[0] = 'G'; + buf[1] = 'L'; + buf[2] = ':'; + size_t l = strlen( pName ); + memcpy( buf + 3, pName, l ); + buf[3 + l] = '\n'; + buf[4 + l] = '\0'; + Plat_DebugString( buf ); + } +#endif +} + +inline void CGLExecuteHelperBase::StopCall(const char *pName) +{ +#if GL_TRACK_API_TIME + uint64 nTotalCycles = tmFastTime() - m_nStartTime; +#endif + +#if GL_TELEMETRY_ZONES + tmLeave( TELEMETRY_LEVEL3 ); +#endif + +#if GL_TRACK_API_TIME + //double flMilliseconds = g_Telemetry.flRDTSCToMilliSeconds * nTotalCycles; + if (gGL) + { + gGL->m_nTotalGLCycles += nTotalCycles; + gGL->m_nTotalGLCalls++; + } +#endif +} +#endif + +#endif // DX_TO_GL_ABSTRACTION + +#endif // GLENTRYPOINTS_H diff --git a/sp/src/public/togl/linuxwin/glfuncs.h b/sp/src/public/togl/linuxwin/glfuncs.h new file mode 100644 index 00000000..3ef3772c --- /dev/null +++ b/sp/src/public/togl/linuxwin/glfuncs.h @@ -0,0 +1,236 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// !!! FIXME: Some of these aren't base OpenGL...pick out the extensions. +// !!! FIXME: Also, look up these -1, -1 versions numbers. +GL_FUNC(OpenGL,true,GLenum,glGetError,(void),()) +GL_FUNC_VOID(OpenGL,true,glActiveTexture,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glAlphaFunc,(GLenum a,GLclampf b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glAttachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBegin,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glBindAttribLocationARB,(GLhandleARB a,GLuint b,const GLcharARB *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glBindBufferARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindProgramARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindTexture,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBlendColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glBlendEquation,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glBlendFunc,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBufferDataARB,(GLenum a,GLsizeiptrARB b,const GLvoid *c,GLenum d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glClear,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glClearColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glClearDepth,(GLclampd a),(a)) +GL_FUNC_VOID(OpenGL,true,glClearStencil,(GLint a),(a)) +GL_FUNC_VOID(OpenGL,true,glClipPlane,(GLenum a,const GLdouble *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glColorMask,(GLboolean a,GLboolean b,GLboolean c,GLboolean d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glCompileShaderARB,(GLhandleARB a),(a)) +GL_FUNC_VOID(OpenGL,true,glCompressedTexImage2D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLint f,GLsizei g,const GLvoid *h),(a,b,c,d,e,f,g,h)) +GL_FUNC_VOID(OpenGL,true,glCompressedTexImage3D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLsizei h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC(OpenGL,true,GLhandleARB,glCreateProgramObjectARB,(void),()) +GL_FUNC(OpenGL,true,GLhandleARB,glCreateShaderObjectARB,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteBuffersARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteObjectARB,(GLhandleARB a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteProgramsARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteQueriesARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteShader,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteTextures,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDepthFunc,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDepthMask,(GLboolean a),(a)) +GL_FUNC_VOID(OpenGL,true,glDepthRange,(GLclampd a,GLclampd b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDetachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDisable,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDisableVertexAttribArray,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawArrays,(GLenum a,GLint b,GLsizei c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glDrawBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawRangeElements,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glDrawRangeElementsBaseVertex,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f, GLenum g),(a,b,c,d,e,f,g)) +GL_FUNC_VOID(OpenGL,true,glEnable,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glEnableVertexAttribArray,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glEnd,(void),()) +GL_FUNC_VOID(OpenGL,true,glFinish,(void),()) +GL_FUNC_VOID(OpenGL,true,glFlush,(void),()) +GL_FUNC_VOID(OpenGL,true,glFrontFace,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glGenBuffersARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenProgramsARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenQueriesARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenTextures,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetBooleanv,(GLenum a,GLboolean *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetCompressedTexImage,(GLenum a,GLint b,GLvoid *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGetDoublev,(GLenum a,GLdouble *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetFloatv,(GLenum a,GLfloat *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetInfoLogARB,(GLhandleARB a,GLsizei b,GLsizei *c,GLcharARB *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glGetIntegerv,(GLenum a,GLint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetObjectParameterivARB,(GLhandleARB a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGetProgramivARB,(GLenum a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC(OpenGL,true,const GLubyte *,glGetString,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glGetTexImage,(GLenum a,GLint b,GLenum c,GLenum d,GLvoid *e),(a,b,c,d,e)) +GL_FUNC(OpenGL,true,GLint,glGetUniformLocationARB,(GLhandleARB a,const GLcharARB *b),(a,b)) +GL_FUNC(OpenGL,true,GLboolean,glIsEnabled,(GLenum a),(a)) +GL_FUNC(OpenGL,true,GLboolean,glIsTexture,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glLinkProgramARB,(GLhandleARB a),(a)) +GL_FUNC(OpenGL,true,GLvoid*,glMapBufferARB,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glOrtho,(GLdouble a,GLdouble b,GLdouble c,GLdouble d,GLdouble e,GLdouble f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glPixelStorei,(GLenum a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPolygonMode,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPolygonOffset,(GLfloat a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPopAttrib,(void),()) +GL_FUNC_VOID(OpenGL,true,glProgramStringARB,(GLenum a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glPushAttrib,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glReadBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glScissor,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glShaderSourceARB,(GLhandleARB a,GLsizei b,const GLcharARB **c,const GLint *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glStencilFunc,(GLenum a,GLint b,GLuint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glStencilMask,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glStencilOp,(GLenum a,GLenum b,GLenum c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexCoord2f,(GLfloat a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glTexImage2D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLint f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC_VOID(OpenGL,true,glTexImage3D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLenum h,GLenum i,const GLvoid *j),(a,b,c,d,e,f,g,h,i,j)) +GL_FUNC_VOID(OpenGL,true,glTexParameterfv,(GLenum a,GLenum b,const GLfloat *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexParameteri,(GLenum a,GLenum b,GLint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexSubImage2D,(GLenum a,GLint b,GLint c,GLint d,GLsizei e,GLsizei f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC_VOID(OpenGL,true,glUniform1f,(GLint a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform1i,(GLint a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform1iARB,(GLint a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform4fv,(GLint a,GLsizei b,const GLfloat *c),(a,b,c)) +GL_FUNC(OpenGL,true,GLboolean,glUnmapBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glUseProgram,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glVertex3f,(GLfloat a,GLfloat b,GLfloat c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glVertexAttribPointer,(GLuint a,GLint b,GLenum c,GLboolean d,GLsizei e,const GLvoid *f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glViewport,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glEnableClientState,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDisableClientState,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glClientActiveTexture,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glVertexPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glTexCoordPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glProgramEnvParameters4fvEXT,(GLenum a,GLuint b,GLsizei c,const GLfloat *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glColor4sv,(const GLshort *a),(a)) +GL_FUNC_VOID(OpenGL,true,glStencilOpSeparate,(GLenum a,GLenum b,GLenum c,GLenum d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glStencilFuncSeparate,(GLenum a,GLenum b,GLint c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glGetTexLevelParameteriv,(GLenum a,GLint b,GLenum c,GLint *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glColor4f,(GLfloat a,GLfloat b,GLfloat c,GLfloat d),(a,b,c,d)) +GL_EXT(GL_EXT_framebuffer_object,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindFramebufferEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindRenderbufferEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC(GL_EXT_framebuffer_object,false,GLenum,glCheckFramebufferStatusEXT,(GLenum a),(a)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteRenderbuffersEXT,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferRenderbufferEXT,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture2DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture3DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenFramebuffersEXT,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenRenderbuffersEXT,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteFramebuffersEXT,(GLsizei a,const GLuint *b),(a,b)) +GL_EXT(GL_EXT_framebuffer_blit,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_blit,false,glBlitFramebufferEXT,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) +GL_EXT(GL_EXT_framebuffer_multisample,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_multisample,false,glRenderbufferStorageMultisampleEXT,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) +GL_EXT(GL_APPLE_fence,-1,-1) +GL_FUNC(GL_APPLE_fence,false,GLboolean,glTestFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glSetFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glFinishFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glDeleteFencesAPPLE,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_APPLE_fence,false,glGenFencesAPPLE,(GLsizei a,GLuint *b),(a,b)) +GL_EXT(GL_NV_fence,-1,-1) +GL_FUNC(GL_NV_fence,false,GLboolean,glTestFenceNV,(GLuint a),(a)) +GL_FUNC_VOID(GL_NV_fence,false,glSetFenceNV,(GLuint a,GLenum b),(a,b)) +GL_FUNC_VOID(GL_NV_fence,false,glFinishFenceNV,(GLuint a),(a)) +GL_FUNC_VOID(GL_NV_fence,false,glDeleteFencesNV,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_NV_fence,false,glGenFencesNV,(GLsizei a,GLuint *b),(a,b)) +GL_EXT(GL_ARB_sync,3,2) +#ifdef HAVE_GL_ARB_SYNC +GL_FUNC_VOID(GL_ARB_sync,false,glGetSynciv,(GLsync a, GLenum b, GLsizei c, GLsizei *d, GLint *e),(a,b,c,d,e)) +GL_FUNC(GL_ARB_sync,false,GLenum,glClientWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_sync,false,glWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_sync,false,glDeleteSync,(GLsync a),(a)) +GL_FUNC(GL_ARB_sync,false,GLsync,glFenceSync,(GLenum a, GLbitfield b),(a,b)) +#endif +GL_EXT(GL_EXT_draw_buffers2,-1,-1) +GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glColorMaskIndexedEXT,(GLuint a,GLboolean b,GLboolean c,GLboolean d,GLboolean e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glEnableIndexedEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glDisableIndexedEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glGetBooleanIndexedvEXT,(GLenum a,GLuint b,GLboolean *c),(a,b,c)) +GL_EXT(GL_EXT_bindable_uniform,-1,-1) +GL_FUNC_VOID(GL_EXT_bindable_uniform,false,glUniformBufferEXT,(GLuint a,GLint b,GLuint c),(a,b,c)) +GL_FUNC(GL_EXT_bindable_uniform,false,int,glGetUniformBufferSizeEXT,(GLenum a, GLenum b),(a,b)) +GL_FUNC(GL_EXT_bindable_uniform,false,GLintptr,glGetUniformOffsetEXT,(GLenum a, GLenum b),(a,b)) +GL_EXT(GL_APPLE_flush_buffer_range,-1,-1) +GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glBufferParameteriAPPLE,(GLenum a,GLenum b,GLint c),(a,b,c)) +GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glFlushMappedBufferRangeAPPLE,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) +GL_EXT(GL_ARB_map_buffer_range,-1,-1) +GL_FUNC(GL_ARB_map_buffer_range,false,void*,glMapBufferRange,(GLenum a,GLintptr b,GLsizeiptr c,GLbitfield d),(a,b,c,d)) +GL_FUNC_VOID(GL_ARB_map_buffer_range,false,glFlushMappedBufferRange,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) +GL_EXT(GL_ARB_vertex_buffer_object,-1,-1) +GL_FUNC_VOID(GL_ARB_vertex_buffer_object,true,glBufferSubData,(GLenum a,GLintptr b,GLsizeiptr c,const GLvoid *d),(a,b,c,d)) +GL_EXT(GL_ARB_occlusion_query,-1,-1) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glBeginQueryARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glEndQueryARB,(GLenum a),(a)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectivARB,(GLuint a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectuivARB,(GLuint a,GLenum b,GLuint *c),(a,b,c)) +GL_EXT(GL_APPLE_texture_range,-1,-1) +GL_FUNC_VOID(GL_APPLE_texture_range,false,glTextureRangeAPPLE,(GLenum a,GLsizei b,void *c),(a,b,c)) +GL_FUNC_VOID(GL_APPLE_texture_range,false,glGetTexParameterPointervAPPLE,(GLenum a,GLenum b,void* *c),(a,b,c)) +GL_EXT(GL_APPLE_client_storage,-1,-1) +GL_EXT(GL_ARB_uniform_buffer,-1,-1) +GL_EXT(GL_ARB_vertex_array_bgra,-1,-1) +GL_EXT(GL_EXT_vertex_array_bgra,-1,-1) +GL_EXT(GL_ARB_framebuffer_object,3,0) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindFramebuffer,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindRenderbuffer,(GLenum a,GLuint b),(a,b)) +GL_FUNC(GL_ARB_framebuffer_object,false,GLenum,glCheckFramebufferStatus,(GLenum a),(a)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteRenderbuffers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferRenderbuffer,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture2D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture3D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenFramebuffers,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenRenderbuffers,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteFramebuffers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBlitFramebuffer,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glRenderbufferStorageMultisample,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) +GL_EXT(GL_GREMEDY_string_marker,-1,-1) +GL_FUNC_VOID(GL_GREMEDY_string_marker,false,glStringMarkerGREMEDY,(GLsizei a,const void *b),(a,b)) +GL_EXT(GL_ARB_debug_output,-1,-1) +GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageCallbackARB,(void (APIENTRY *a)(GLenum, GLenum , GLuint , GLenum , GLsizei , const GLchar* , GLvoid*) ,void* b),(a,b)) +GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageControlARB,(GLenum a, GLenum b, GLenum c, GLsizei d, const GLuint* e, GLboolean f),(a,b,c,d,e,f)) +GL_EXT(GL_EXT_direct_state_access,-1,-1) +GL_FUNC_VOID(GL_EXT_direct_state_access,false,glBindMultiTextureEXT,(GLenum a,GLuint b, GLuint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGenSamplers,(GLuint a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteSamplers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindSampler,(GLuint a, GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glSamplerParameteri,(GLuint a, GLenum b, GLint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glSamplerParameterf,(GLuint a, GLenum b, GLfloat c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glSamplerParameterfv,(GLuint a, GLenum b, const GLfloat *c),(a,b,c)) +GL_EXT(GL_NV_bindless_texture,-1,-1) +GL_FUNC(GL_NV_bindless_texture, false, GLuint64, glGetTextureHandleNV, (GLuint texture), (texture)) +GL_FUNC(GL_NV_bindless_texture, false, GLuint64, glGetTextureSamplerHandleNV, (GLuint texture, GLuint sampler), (texture, sampler)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glMakeTextureHandleResidentNV, (GLuint64 handle), (handle)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glMakeTextureHandleNonResidentNV, (GLuint64 handle), (handle)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glUniformHandleui64NV, (GLint location, GLuint64 value), (location, value)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glUniformHandleui64vNV, (int location, GLsizei count, const GLuint64 *value), (location count, value)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glProgramUniformHandleui64NV, (GLuint program, GLint location, GLuint64 value), (program, location, value)) +GL_FUNC_VOID(GL_NV_bindless_texture, false, glProgramUniformHandleui64vNV, (GLuint program, GLint location, GLsizei count, const GLuint64 *values), (program, location, count, values)) +GL_FUNC(GL_NV_bindless_texture, false, GLboolean, glIsTextureHandleResidentNV, (GLuint64 handle), (handle)) +GL_FUNC_VOID(OpenGL,true,glGenQueries,(GLsizei n, GLuint *ids), (n, ids)) +GL_FUNC_VOID(OpenGL,true,glDeleteQueries,(GLsizei n, const GLuint *ids),(n, ids)) +GL_FUNC_VOID(OpenGL,true,glBeginQuery,(GLenum target, GLuint id), (target, id)) +GL_FUNC_VOID(OpenGL,true,glEndQuery,(GLenum target), (target)) +GL_FUNC_VOID(OpenGL,true,glQueryCounter,(GLuint id, GLenum target), (id, target)) +GL_FUNC_VOID(OpenGL,true,glGetQueryObjectiv,(GLuint id, GLenum pname, GLint *params), (id, pname, params)) +GL_FUNC_VOID(OpenGL,true,glGetQueryObjectui64v,(GLuint id, GLenum pname, GLuint64 *params), (id, pname, params)) +GL_FUNC_VOID(OpenGL,true,glCopyBufferSubData,(GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size),(readtarget, writetarget, readoffset, writeoffset, size)) +GL_EXT(GL_AMD_pinned_memory,-1,-1) +GL_EXT(GL_EXT_framebuffer_multisample_blit_scaled,-1,-1) +GL_FUNC_VOID(OpenGL,true,glGenVertexArrays,(GLsizei n, GLuint *arrays),(n, arrays)) +GL_FUNC_VOID(OpenGL,true,glDeleteVertexArrays,(GLsizei n, GLuint *arrays),(n, arrays)) +GL_FUNC_VOID(OpenGL,true,glBindVertexArray,(GLuint a),(a)) +GL_EXT(GL_EXT_texture_sRGB_decode,-1,-1) +GL_FUNC_VOID(OpenGL,true,glPushClientAttrib,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glPopClientAttrib,(void),()) +GL_EXT(GL_NVX_gpu_memory_info,-1,-1) +GL_EXT(GL_ATI_meminfo,-1,-1) +GL_EXT(GL_EXT_texture_compression_s3tc,-1,-1) +GL_EXT(GL_EXT_texture_compression_dxt1,-1,-1) +GL_EXT(GL_ANGLE_texture_compression_dxt3,-1,-1) +GL_EXT(GL_ANGLE_texture_compression_dxt5,-1,-1) + +// This one is an OS extension. We'll add a little helper function to look for it. +#ifdef _WIN32 + GL_EXT(WGL_EXT_swap_control_tear,-1,-1) +#else + GL_EXT(GLX_EXT_swap_control_tear,-1,-1) +#endif diff --git a/sp/src/public/togl/linuxwin/glmdebug.h b/sp/src/public/togl/linuxwin/glmdebug.h new file mode 100644 index 00000000..80df86f1 --- /dev/null +++ b/sp/src/public/togl/linuxwin/glmdebug.h @@ -0,0 +1,160 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef GLMDEBUG_H +#define GLMDEBUG_H + +#include "tier0/platform.h" + +// include this anywhere you need to be able to compile-out code related specifically to GLM debugging. + +// we expect DEBUG to be driven by the build system so you can include this header anywhere. +// when we come out, GLMDEBUG will be defined to a value - 0, 1, or 2 +// 0 means no GLM debugging is possible +// 1 means it's possible and resulted from being a debug build +// 2 means it's possible and resulted from being manually forced on for a release build + +#ifdef POSIX + #ifndef GLMDEBUG + #ifdef DEBUG + #define GLMDEBUG 1 // normally 1 here, testing + #else + // #define GLMDEBUG 2 // don't check this in enabled.. + #endif + + #ifndef GLMDEBUG + #define GLMDEBUG 0 + #endif + #endif +#else + #ifndef GLMDEBUG + #define GLMDEBUG 0 + #endif +#endif + + +//=============================================================================== +// debug channels + +enum EGLMDebugChannel +{ + ePrintf, + eDebugger, + eGLProfiler +}; + +#if GLMDEBUG + // make all these prototypes disappear in non GLMDEBUG + void GLMDebugInitialize( bool forceReinit=false ); + + bool GLMDetectOGLP( void ); + bool GLMDetectGDB( void ); + uint GLMDetectAvailableChannels( void ); + + uint GLMDebugChannelMask( uint *newValue = NULL ); + // note that GDB and OGLP can both come and go during run - forceCheck will allow that to be detected. + // mask returned is in form of 1< < + eComment, // 3 one off messages --- + eMatrixData, // 4 matrix data -M- + eShaderData, // 5 shader data (params) -S- + eFrameBufData, // 6 FBO data (attachments) -F- + eDXStuff, // 7 dxabstract spew -X- + eAllocations, // 8 tracking allocs and frees -A- + eSlowness, // 9 slow things happening (srgb flips..) -Z- + eDefaultFlavor, // not specified (no marker) + eFlavorCount +}; +uint GLMDebugFlavorMask( uint *newValue = NULL ); + +// make all these prototypes disappear in non GLMDEBUG +#if GLMDEBUG + // these are unconditional outputs, they don't interrogate the string + void GLMStringOut( const char *string ); + void GLMStringOutIndented( const char *string, int indentColumns ); + + #ifdef TOGL_DLL_EXPORT + // these will look at the string to guess its flavor: <, >, ---, -M-, -S- + DLL_EXPORT void GLMPrintfVA( const char *fmt, va_list vargs ); + DLL_EXPORT void GLMPrintf( const char *fmt, ... ); + #else + DLL_IMPORT void GLMPrintfVA( const char *fmt, va_list vargs ); + DLL_IMPORT void GLMPrintf( const char *fmt, ... ); + #endif + + // these take an explicit flavor with a default value + void GLMPrintStr( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor ); + + #define GLMPRINTTEXT_NUMBEREDLINES 0x80000000 + void GLMPrintText( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor, uint options=0 ); // indent each newline + + int GLMIncIndent( int indentDelta ); + int GLMGetIndent( void ); + void GLMSetIndent( int indent ); + +#endif + +// helpful macro if you are in a position to call GLM functions directly (i.e. you live in materialsystem / shaderapidx9) +#if GLMDEBUG + #define GLMPRINTF(args) GLMPrintf args + #define GLMPRINTSTR(args) GLMPrintStr args + #define GLMPRINTTEXT(args) GLMPrintText args +#else + #define GLMPRINTF(args) + #define GLMPRINTSTR(args) + #define GLMPRINTTEXT(args) +#endif + + +//=============================================================================== +// knob twiddling +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value + DLL_EXPORT float GLMKnobToggle( char *knobname ); +#else + DLL_IMPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value + DLL_IMPORT float GLMKnobToggle( char *knobname ); +#endif + +//=============================================================================== +// other stuff + +#if GLMDEBUG +void GLMTriggerDebuggerBreak(); +inline void GLMDebugger( void ) +{ + if (GLMDebugChannelMask() & (1< +#include +#include +#include +#include +#include +#include +#elif defined(DX_TO_GL_ABSTRACTION) +#include +#include +#include "tier0/platform.h" +#else +#error +#endif + +typedef void _PseudoNSGLContext; // aka NSOpenGLContext +typedef _PseudoNSGLContext *PseudoNSGLContextPtr; + +struct GLMDisplayModeInfoFields +{ + uint m_modePixelWidth; + uint m_modePixelHeight; + uint m_modeRefreshHz; + // are we even going to talk about bit depth... not yet +}; + +struct GLMDisplayInfoFields +{ +#ifdef OSX + CGDirectDisplayID m_cgDisplayID; + CGOpenGLDisplayMask m_glDisplayMask; // result of CGDisplayIDToOpenGLDisplayMask on the cg_displayID. +#endif + uint m_displayPixelWidth; + uint m_displayPixelHeight; +}; + +struct GLMRendererInfoFields +{ + /*properties of interest and their desired values. + + kCGLRPFullScreen = 54, true + kCGLRPAccelerated = 73, true + kCGLRPWindow = 80, true + + kCGLRPRendererID = 70, informational + kCGLRPDisplayMask = 84, informational + kCGLRPBufferModes = 100, informational + kCGLRPColorModes = 103, informational + kCGLRPAccumModes = 104, informational + kCGLRPDepthModes = 105, informational + kCGLRPStencilModes = 106, informational + kCGLRPMaxAuxBuffers = 107, informational + kCGLRPMaxSampleBuffers = 108, informational + kCGLRPMaxSamples = 109, informational + kCGLRPSampleModes = 110, informational + kCGLRPSampleAlpha = 111, informational + kCGLRPVideoMemory = 120, informational + kCGLRPTextureMemory = 121, informational + kCGLRPRendererCount = 128 number of renderers in the CGLRendererInfoObj under examination + + kCGLRPOffScreen = 53, D/C + kCGLRPRobust = 75, FALSE or D/C - aka we're asking for no-fallback + kCGLRPBackingStore = 76, D/C + kCGLRPMPSafe = 78, D/C + kCGLRPMultiScreen = 81, D/C + kCGLRPCompliant = 83, D/C + */ + + + //--------------------------- info we have from CGL renderer queries, IOKit, Gestalt + //--------------------------- these are set up in the displayDB by CocoaMgr + GLint m_fullscreen; + GLint m_accelerated; + GLint m_windowed; + + GLint m_rendererID; + GLint m_displayMask; + GLint m_bufferModes; + GLint m_colorModes; + GLint m_accumModes; + GLint m_depthModes; + GLint m_stencilModes; + + GLint m_maxAuxBuffers; + GLint m_maxSampleBuffers; + GLint m_maxSamples; + GLint m_sampleModes; + GLint m_sampleAlpha; + + GLint m_vidMemory; + GLint m_texMemory; + + uint m_pciVendorID; + uint m_pciDeviceID; + char m_pciModelString[64]; + char m_driverInfoString[64]; + + //--------------------------- OS version related - set up by CocoaMgr + + // OS version found + uint m_osComboVersion; // 0x00XXYYZZ : XX major, YY minor, ZZ minor minor : 10.6.3 --> 0x000A0603. 10.5.8 --> 0x000A0508. + + //--------------------------- shorthands - also set up by CocoaMgr - driven by vendorid / deviceid + + bool m_ati; + bool m_atiR5xx; + bool m_atiR6xx; + bool m_atiR7xx; + bool m_atiR8xx; + bool m_atiNewer; + + bool m_intel; + bool m_intel95x; + bool m_intel3100; + bool m_intelNewer; + + bool m_nv; + bool m_nvG7x; + bool m_nvG8x; + bool m_nvNewer; + + //--------------------------- context query results - left blank in the display DB - but valid in a GLMContext (call ctx->Caps() to get a const ref) + + // booleans + bool m_hasGammaWrites; // aka glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT) / glEnable(GL_FRAMEBUFFER_SRGB_EXT) + bool m_hasMixedAttachmentSizes; // aka ARB_fbo in 10.6.3 - test for min OS vers, then exported ext string + bool m_hasBGRA; // aka GL_BGRA vertex attribs in 10.6.3 - - test for min OS vers, then exported ext string + bool m_hasNewFullscreenMode; // aka 10.6.x "big window" fullscreen mode + bool m_hasNativeClipVertexMode; // aka GLSL gl_ClipVertex does not fall back to SW- OS version and folklore-based + bool m_hasOcclusionQuery; // occlusion query: do you speak it ?! + bool m_hasFramebufferBlit; // framebuffer blit: know what I'm sayin?! + bool m_hasPerfPackage1; // means new MTGL, fast OQ, fast uniform upload, NV can resolve flipped (late summer 2010 post 10.6.4 update) + + // counts + int m_maxAniso; // aniso limit - context query + + // other exts + bool m_hasBindableUniforms; + int m_maxVertexBindableUniforms; + int m_maxFragmentBindableUniforms; + int m_maxBindableUniformSize; + + bool m_hasUniformBuffers; + + // runtime options that aren't negotiable once set + bool m_hasDualShaders; // must supply CLI arg "-glmdualshaders" or we go GLSL only + + //--------------------------- " can'ts " - specific problems that need to be worked around + + bool m_cantBlitReliably; // Intel chipsets have problems blitting sRGB sometimes + bool m_cantAttachSRGB; // NV G8x on 10.5.8 can't have srgb tex on FBO color - separate issue from hasGammaWrites + bool m_cantResolveFlipped; // happens on NV in 10.6.4 and prior - console variable "gl_can_resolve_flipped" can overrule + bool m_cantResolveScaled; // happens everywhere per GL spec but may be relaxed some day - console variable "gl_can_resolve_scaled" can overrule + bool m_costlyGammaFlips; // this means that sRGB sampling state affects shader code gen, resulting in state-dependent code regen + + + //--------------------------- " bads " - known bad drivers + bool m_badDriver1064NV; // this is the bad NVIDIA driver on 10.6.4 - stutter, tex corruption, black screen issues +}; + + + +#endif diff --git a/sp/src/public/togl/linuxwin/glmdisplaydb.h b/sp/src/public/togl/linuxwin/glmdisplaydb.h new file mode 100644 index 00000000..7f78f910 --- /dev/null +++ b/sp/src/public/togl/linuxwin/glmdisplaydb.h @@ -0,0 +1,92 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef GLMDISPLAYDB_H +#define GLMDISPLAYDB_H + +#include "tier1/utlvector.h" + +//=============================================================================== +// modes, displays, and renderers +//=============================================================================== + +// GLMDisplayModeInfoFields is in glmdisplay.h + +class GLMDisplayMode +{ +public: + GLMDisplayModeInfoFields m_info; + + GLMDisplayMode( uint width, uint height, uint refreshHz ); + GLMDisplayMode() { }; + ~GLMDisplayMode( void ); + + void Init( uint width, uint height, uint refreshHz ); + void Dump( int which ); +}; + +//=============================================================================== + +// GLMDisplayInfoFields is in glmdisplay.h + +class GLMDisplayInfo +{ +public: + GLMDisplayInfoFields m_info; + CUtlVector< GLMDisplayMode* > *m_modes; // starts out NULL, set by PopulateModes + + GLMDisplayInfo( void ); + ~GLMDisplayInfo( void ); + + void PopulateModes( void ); + + void Dump( int which ); +}; + +//=============================================================================== + +// GLMRendererInfoFields is in glmdisplay.h + +class GLMRendererInfo +{ +public: + GLMRendererInfoFields m_info; + GLMDisplayInfo *m_display; + + GLMRendererInfo (); + ~GLMRendererInfo ( void ); + + void Init( GLMRendererInfoFields *info ); + void PopulateDisplays(); + void Dump( int which ); +}; + +//=============================================================================== + +class GLMDisplayDB +{ +public: + GLMRendererInfo m_renderer; + + GLMDisplayDB ( void ); + ~GLMDisplayDB ( void ); + + virtual void PopulateRenderers( void ); + virtual void PopulateFakeAdapters( uint realRendererIndex ); // fake adapters = one real adapter times however many displays are on it + virtual void Populate( void ); + + // The info-get functions return false on success. + virtual int GetFakeAdapterCount( void ); + virtual bool GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut ); + + virtual int GetRendererCount( void ); + virtual bool GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut ); + + virtual int GetDisplayCount( int rendererIndex ); + virtual bool GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut ); + + virtual int GetModeCount( int rendererIndex, int displayIndex ); + virtual bool GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut ); + + virtual void Dump( void ); +}; + +#endif // GLMDISPLAYDB_H diff --git a/sp/src/public/togl/linuxwin/glmgr.h b/sp/src/public/togl/linuxwin/glmgr.h new file mode 100644 index 00000000..cc828636 --- /dev/null +++ b/sp/src/public/togl/linuxwin/glmgr.h @@ -0,0 +1,2259 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgr.h +// singleton class, common basis for managing GL contexts +// responsible for tracking adapters and contexts +// +//=============================================================================== + +#ifndef GLMGR_H +#define GLMGR_H + +#pragma once + +#include "glbase.h" +#include "glentrypoints.h" +#include "glmdebug.h" +#include "glmdisplay.h" +#include "glmgrext.h" +#include "glmgrbasics.h" +#include "cglmtex.h" +#include "cglmfbo.h" +#include "cglmprogram.h" +#include "cglmbuffer.h" +#include "cglmquery.h" + +#include "tier0/vprof_telemetry.h" +#include "materialsystem/IShader.h" +#include "dxabstract_types.h" +#include "tier0/icommandline.h" + +//=============================================================================== + +#define GLM_OPENGL_VENDOR_ID 1 +#define GLM_OPENGL_DEFAULT_DEVICE_ID 1 +#define GLM_OPENGL_LOW_PERF_DEVICE_ID 2 + +extern void GLMDebugPrintf( const char *pMsg, ... ); + +extern uint g_nTotalDrawsOrClears, g_nTotalVBLockBytes, g_nTotalIBLockBytes; + +#if GL_TELEMETRY_GPU_ZONES +struct TelemetryGPUStats_t +{ + uint m_nTotalBufferLocksAndUnlocks; + uint m_nTotalTexLocksAndUnlocks; + uint m_nTotalBlit2; + uint m_nTotalResolveTex; + uint m_nTotalPresent; + + inline void Clear() { memset( this, 0, sizeof( *this ) ); } + inline uint GetTotal() const { return m_nTotalBufferLocksAndUnlocks + m_nTotalTexLocksAndUnlocks + m_nTotalBlit2 + m_nTotalResolveTex + m_nTotalPresent; } +}; +extern TelemetryGPUStats_t g_TelemetryGPUStats; +#endif + +struct GLMRect; +typedef void *PseudoGLContextPtr; + +// parrot the D3D present parameters, more or less... "adapter" translates into "active display index" per the m_activeDisplayCount below. +class GLMDisplayParams +{ + public: + + // presumption, these indices are in sync with the current display DB that GLMgr has handy + //int m_rendererIndex; // index of renderer (-1 if root context) + //int m_displayIndex; // index of display in renderer - for FS + //int m_modeIndex; // index of mode in display - for FS + + void *m_focusWindow; // (VD3DHWND aka WindowRef) - what window does this context display into + + bool m_fsEnable; // fullscreen on or not + bool m_vsyncEnable; // vsync on or not + + // height and width have to match the display mode info if full screen. + + uint m_backBufferWidth; // pixel width (aka screen h-resolution if full screen) + uint m_backBufferHeight; // pixel height (aka screen v-resolution if full screen) + D3DFORMAT m_backBufferFormat; // pixel format + uint m_multiSampleCount; // 0 means no MSAA, 2 means 2x MSAA, etc + // uint m_multiSampleQuality; // no MSAA quality control yet + + bool m_enableAutoDepthStencil; // generally set to 'TRUE' per CShaderDeviceDx8::SetPresentParameters + D3DFORMAT m_autoDepthStencilFormat; + + uint m_fsRefreshHz; // if full screen, this refresh rate (likely 0 for LCD's) + + //uint m_rootRendererID; // only used if m_rendererIndex is -1. + //uint m_rootDisplayMask; // only used if m_rendererIndex is -1. + + bool m_mtgl; // enable multi threaded GL driver +}; + +//=============================================================================== + +class GLMgr +{ +public: + + //=========================================================================== + // class methods - singleton + static void NewGLMgr( void ); // instantiate singleton.. + static GLMgr *aGLMgr( void ); // return singleton.. + static void DelGLMgr( void ); // tear down singleton.. + + //=========================================================================== + // plain methods + + #if 0 // turned all these off while new approach is coded + void RefreshDisplayDB( void ); // blow away old display DB, make a new one + GLMDisplayDB *GetDisplayDB( void ); // get a ptr to the one GLMgr keeps. only valid til next refresh. + + // eligible renderers will be ranked by desirability starting at index 0 within the db + // within each renderer, eligible displays will be ranked some kind of desirability (area? dist from menu bar?) + // within each display, eligible modes will be ranked by descending areas + + // calls supplying indices are implicitly making reference to the current DB + bool CaptureDisplay( int rendIndex, int displayIndex, bool captureAll ); // capture one display or all displays + void ReleaseDisplays( void ); // release all captures + + int GetDisplayMode( int rendIndex, int displayIndex ); // retrieve current display res (returns modeIndex) + void SetDisplayMode( GLMDisplayParams *params ); // set the display res (only useful for FS) + #endif + + GLMContext *NewContext( IDirect3DDevice9 *pDevice, GLMDisplayParams *params ); // this will have to change + void DelContext( GLMContext *context ); + + // with usage of CGLMacro.h we could dispense with the "current context" thing + // and just declare a member variable of GLMContext, allowing each glXXX call to be routed directly + // to the correct context + void SetCurrentContext( GLMContext *context ); // make current in calling thread only + GLMContext *GetCurrentContext( void ); + +protected: + friend class GLMContext; + + GLMgr(); + ~GLMgr(); +}; + + +//===========================================================================// + +// helper function to do enable or disable in one step +FORCEINLINE void glSetEnable( GLenum which, bool enable ) +{ + if (enable) + gGL->glEnable(which); + else + gGL->glDisable(which); +} + +// helper function for int vs enum clarity +FORCEINLINE void glGetEnumv( GLenum which, GLenum *dst ) +{ + gGL->glGetIntegerv( which, (int*)dst ); +} + +//===========================================================================// +// +// types to support the GLMContext +// +//===========================================================================// + +// Each state set/get path we are providing caching for, needs its own struct and a comparison operator. +// we also provide an enum of how many such types there are, handy for building dirty masks etc. + +// shorthand macros +#define EQ(fff) ( (src.fff) == (fff) ) + +//rasterizer +struct GLAlphaTestEnable_t { GLint enable; inline bool operator==(const GLAlphaTestEnable_t& src) const { return EQ(enable); } }; +struct GLAlphaTestFunc_t { GLenum func; GLclampf ref; inline bool operator==(const GLAlphaTestFunc_t& src) const { return EQ(func) && EQ(ref); } }; +struct GLCullFaceEnable_t { GLint enable; inline bool operator==(const GLCullFaceEnable_t& src) const { return EQ(enable); } }; +struct GLCullFrontFace_t { GLenum value; inline bool operator==(const GLCullFrontFace_t& src) const { return EQ(value); } }; +struct GLPolygonMode_t { GLenum values[2]; inline bool operator==(const GLPolygonMode_t& src) const { return EQ(values[0]) && EQ(values[1]); } }; +struct GLDepthBias_t { GLfloat factor; GLfloat units; inline bool operator==(const GLDepthBias_t& src) const { return EQ(factor) && EQ(units); } }; +struct GLScissorEnable_t { GLint enable; inline bool operator==(const GLScissorEnable_t& src) const { return EQ(enable); } }; +struct GLScissorBox_t { GLint x,y; GLsizei width, height; inline bool operator==(const GLScissorBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; +struct GLAlphaToCoverageEnable_t{ GLint enable; inline bool operator==(const GLAlphaToCoverageEnable_t& src) const { return EQ(enable); } }; +struct GLViewportBox_t { GLint x,y; GLsizei width, height; uint widthheight; inline bool operator==(const GLViewportBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; +struct GLViewportDepthRange_t { GLdouble flNear,flFar; inline bool operator==(const GLViewportDepthRange_t& src) const { return EQ(flNear) && EQ(flFar); } }; +struct GLClipPlaneEnable_t { GLint enable; inline bool operator==(const GLClipPlaneEnable_t& src) const { return EQ(enable); } }; +struct GLClipPlaneEquation_t { GLfloat x,y,z,w; inline bool operator==(const GLClipPlaneEquation_t& src) const { return EQ(x) && EQ(y) && EQ(z) && EQ(w); } }; + +//blend +struct GLColorMaskSingle_t { char r,g,b,a; inline bool operator==(const GLColorMaskSingle_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLColorMaskMultiple_t { char r,g,b,a; inline bool operator==(const GLColorMaskMultiple_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLBlendEnable_t { GLint enable; inline bool operator==(const GLBlendEnable_t& src) const { return EQ(enable); } }; +struct GLBlendFactor_t { GLenum srcfactor,dstfactor; inline bool operator==(const GLBlendFactor_t& src) const { return EQ(srcfactor) && EQ(dstfactor); } }; +struct GLBlendEquation_t { GLenum equation; inline bool operator==(const GLBlendEquation_t& src) const { return EQ(equation); } }; +struct GLBlendColor_t { GLfloat r,g,b,a; inline bool operator==(const GLBlendColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLBlendEnableSRGB_t { GLint enable; inline bool operator==(const GLBlendEnableSRGB_t& src) const { return EQ(enable); } }; + +//depth +struct GLDepthTestEnable_t { GLint enable; inline bool operator==(const GLDepthTestEnable_t& src) const { return EQ(enable); } }; +struct GLDepthFunc_t { GLenum func; inline bool operator==(const GLDepthFunc_t& src) const { return EQ(func); } }; +struct GLDepthMask_t { char mask; inline bool operator==(const GLDepthMask_t& src) const { return EQ(mask); } }; + +//stencil +struct GLStencilTestEnable_t { GLint enable; inline bool operator==(const GLStencilTestEnable_t& src) const { return EQ(enable); } }; +struct GLStencilFunc_t { GLenum frontfunc, backfunc; GLint ref; GLuint mask; inline bool operator==(const GLStencilFunc_t& src) const { return EQ(frontfunc) && EQ(backfunc) && EQ(ref) && EQ(mask); } }; +struct GLStencilOp_t { GLenum sfail; GLenum dpfail; GLenum dppass; inline bool operator==(const GLStencilOp_t& src) const { return EQ(sfail) && EQ(dpfail) && EQ(dppass); } }; +struct GLStencilWriteMask_t { GLint mask; inline bool operator==(const GLStencilWriteMask_t& src) const { return EQ(mask); } }; + +//clearing +struct GLClearColor_t { GLfloat r,g,b,a; inline bool operator==(const GLClearColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLClearDepth_t { GLdouble d; inline bool operator==(const GLClearDepth_t& src) const { return EQ(d); } }; +struct GLClearStencil_t { GLint s; inline bool operator==(const GLClearStencil_t& src) const { return EQ(s); } }; + +#undef EQ + +enum EGLMStateBlockType +{ + kGLAlphaTestEnable, + kGLAlphaTestFunc, + + kGLCullFaceEnable, + kGLCullFrontFace, + + kGLPolygonMode, + + kGLDepthBias, + + kGLScissorEnable, + kGLScissorBox, + + kGLViewportBox, + kGLViewportDepthRange, + + kGLClipPlaneEnable, + kGLClipPlaneEquation, + + kGLColorMaskSingle, + kGLColorMaskMultiple, + + kGLBlendEnable, + kGLBlendFactor, + kGLBlendEquation, + kGLBlendColor, + kGLBlendEnableSRGB, + + kGLDepthTestEnable, + kGLDepthFunc, + kGLDepthMask, + + kGLStencilTestEnable, + kGLStencilFunc, + kGLStencilOp, + kGLStencilWriteMask, + + kGLClearColor, + kGLClearDepth, + kGLClearStencil, + + kGLAlphaToCoverageEnable, + + kGLMStateBlockLimit +}; + +//===========================================================================// + +// templated functions representing GL R/W bottlenecks +// one set of set/get/getdefault is instantiated for each of the GL*** types above. + +// use these from the non array state objects +template void GLContextSet( T *src ); +template void GLContextGet( T *dst ); +template void GLContextGetDefault( T *dst ); + +// use these from the array state objects +template void GLContextSetIndexed( T *src, int index ); +template void GLContextGetIndexed( T *dst, int index ); +template void GLContextGetDefaultIndexed( T *dst, int index ); + +//=============================================================================== +// template specializations for each type of state + +// --- GLAlphaTestEnable --- +FORCEINLINE void GLContextSet( GLAlphaTestEnable_t *src ) +{ + glSetEnable( GL_ALPHA_TEST, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLAlphaTestEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_ALPHA_TEST ); +} + +FORCEINLINE void GLContextGetDefault( GLAlphaTestEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + +// --- GLAlphaTestFunc --- +FORCEINLINE void GLContextSet( GLAlphaTestFunc_t *src ) +{ + gGL->glAlphaFunc( src->func, src->ref ); +} + +FORCEINLINE void GLContextGet( GLAlphaTestFunc_t *dst ) +{ + glGetEnumv( GL_ALPHA_TEST_FUNC, &dst->func ); + gGL->glGetFloatv( GL_ALPHA_TEST_REF, &dst->ref ); +} + +FORCEINLINE void GLContextGetDefault( GLAlphaTestFunc_t *dst ) +{ + dst->func = GL_ALWAYS; + dst->ref = 0.0f; +} + +// --- GLAlphaToCoverageEnable --- +FORCEINLINE void GLContextSet( GLAlphaToCoverageEnable_t *src ) +{ + glSetEnable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLAlphaToCoverageEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ); +} + +FORCEINLINE void GLContextGetDefault( GLAlphaToCoverageEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + +// --- GLCullFaceEnable --- +FORCEINLINE void GLContextSet( GLCullFaceEnable_t *src ) +{ + glSetEnable( GL_CULL_FACE, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLCullFaceEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_CULL_FACE ); +} + +FORCEINLINE void GLContextGetDefault( GLCullFaceEnable_t *dst ) +{ + dst->enable = GL_TRUE; +} + + +// --- GLCullFrontFace --- +FORCEINLINE void GLContextSet( GLCullFrontFace_t *src ) +{ + gGL->glFrontFace( src->value ); // legal values are GL_CW or GL_CCW +} + +FORCEINLINE void GLContextGet( GLCullFrontFace_t *dst ) +{ + glGetEnumv( GL_FRONT_FACE, &dst->value ); +} + +FORCEINLINE void GLContextGetDefault( GLCullFrontFace_t *dst ) +{ + dst->value = GL_CCW; +} + + +// --- GLPolygonMode --- +FORCEINLINE void GLContextSet( GLPolygonMode_t *src ) +{ + gGL->glPolygonMode( GL_FRONT, src->values[0] ); + gGL->glPolygonMode( GL_BACK, src->values[1] ); +} + +FORCEINLINE void GLContextGet( GLPolygonMode_t *dst ) +{ + glGetEnumv( GL_POLYGON_MODE, &dst->values[0] ); + +} + +FORCEINLINE void GLContextGetDefault( GLPolygonMode_t *dst ) +{ + dst->values[0] = dst->values[1] = GL_FILL; +} + + +// --- GLDepthBias --- +// note the implicit enable / disable. +// if you set non zero values, it is enabled, otherwise not. +FORCEINLINE void GLContextSet( GLDepthBias_t *src ) +{ + bool enable = (src->factor != 0.0f) || (src->units != 0.0f); + + glSetEnable( GL_POLYGON_OFFSET_FILL, enable ); + gGL->glPolygonOffset( src->factor, src->units ); +} + +FORCEINLINE void GLContextGet( GLDepthBias_t *dst ) +{ + gGL->glGetFloatv ( GL_POLYGON_OFFSET_FACTOR, &dst->factor ); + gGL->glGetFloatv ( GL_POLYGON_OFFSET_UNITS, &dst->units ); +} + +FORCEINLINE void GLContextGetDefault( GLDepthBias_t *dst ) +{ + dst->factor = 0.0; + dst->units = 0.0; +} + + +// --- GLScissorEnable --- +FORCEINLINE void GLContextSet( GLScissorEnable_t *src ) +{ + glSetEnable( GL_SCISSOR_TEST, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLScissorEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_SCISSOR_TEST ); +} + +FORCEINLINE void GLContextGetDefault( GLScissorEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLScissorBox --- +FORCEINLINE void GLContextSet( GLScissorBox_t *src ) +{ + gGL->glScissor ( src->x, src->y, src->width, src->height ); +} + +FORCEINLINE void GLContextGet( GLScissorBox_t *dst ) +{ + gGL->glGetIntegerv ( GL_SCISSOR_BOX, &dst->x ); +} + +FORCEINLINE void GLContextGetDefault( GLScissorBox_t *dst ) +{ + // hmmmm, good question? we can't really know a good answer so we pick a silly one + // and the client better come back with a better answer later. + dst->x = dst->y = 0; + dst->width = dst->height = 16; +} + + +// --- GLViewportBox --- + +FORCEINLINE void GLContextSet( GLViewportBox_t *src ) +{ + Assert( src->width == (int)( src->widthheight & 0xFFFF ) ); + Assert( src->height == (int)( src->widthheight >> 16 ) ); + gGL->glViewport (src->x, src->y, src->width, src->height ); +} + +FORCEINLINE void GLContextGet( GLViewportBox_t *dst ) +{ + gGL->glGetIntegerv ( GL_VIEWPORT, &dst->x ); + dst->widthheight = dst->width | ( dst->height << 16 ); +} + +FORCEINLINE void GLContextGetDefault( GLViewportBox_t *dst ) +{ + // as with the scissor box, we don't know yet, so pick a silly one and change it later + dst->x = dst->y = 0; + dst->width = dst->height = 16; + dst->widthheight = dst->width | ( dst->height << 16 ); +} + + +// --- GLViewportDepthRange --- +FORCEINLINE void GLContextSet( GLViewportDepthRange_t *src ) +{ + gGL->glDepthRange ( src->flNear, src->flFar ); +} + +FORCEINLINE void GLContextGet( GLViewportDepthRange_t *dst ) +{ + gGL->glGetDoublev ( GL_DEPTH_RANGE, &dst->flNear ); +} + +FORCEINLINE void GLContextGetDefault( GLViewportDepthRange_t *dst ) +{ + dst->flNear = 0.0; + dst->flFar = 1.0; +} + +// --- GLClipPlaneEnable --- +FORCEINLINE void GLContextSetIndexed( GLClipPlaneEnable_t *src, int index ) +{ +#if GLMDEBUG + if (CommandLine()->FindParm("-caps_noclipplanes")) + { + if (GLMKnob("caps-key",NULL) > 0.0) + { + // caps ON means NO clipping + src->enable = false; + } + } +#endif + glSetEnable( GL_CLIP_PLANE0 + index, src->enable != 0 ); +} + +FORCEINLINE void GLContextGetIndexed( GLClipPlaneEnable_t *dst, int index ) +{ + dst->enable = gGL->glIsEnabled( GL_CLIP_PLANE0 + index ); +} + +FORCEINLINE void GLContextGetDefaultIndexed( GLClipPlaneEnable_t *dst, int index ) +{ + dst->enable = 0; +} + + + +// --- GLClipPlaneEquation --- +FORCEINLINE void GLContextSetIndexed( GLClipPlaneEquation_t *src, int index ) +{ + // shove into glGlipPlane + GLdouble coeffs[4] = { src->x, src->y, src->z, src->w }; + + gGL->glClipPlane( GL_CLIP_PLANE0 + index, coeffs ); +} + +FORCEINLINE void GLContextGetIndexed( GLClipPlaneEquation_t *dst, int index ) +{ + DebuggerBreak(); // do this later + // glClipPlane( GL_CLIP_PLANE0 + index, coeffs ); + // GLdouble coeffs[4] = { src->x, src->y, src->z, src->w }; +} + +FORCEINLINE void GLContextGetDefaultIndexed( GLClipPlaneEquation_t *dst, int index ) +{ + dst->x = 1.0; + dst->y = 0.0; + dst->z = 0.0; + dst->w = 0.0; +} + + +// --- GLColorMaskSingle --- +FORCEINLINE void GLContextSet( GLColorMaskSingle_t *src ) +{ + gGL->glColorMask( src->r, src->g, src->b, src->a ); +} + +FORCEINLINE void GLContextGet( GLColorMaskSingle_t *dst ) +{ + gGL->glGetBooleanv( GL_COLOR_WRITEMASK, (GLboolean*)&dst->r); +} + +FORCEINLINE void GLContextGetDefault( GLColorMaskSingle_t *dst ) +{ + dst->r = dst->g = dst->b = dst->a = 1; +} + + +// --- GLColorMaskMultiple --- +FORCEINLINE void GLContextSetIndexed( GLColorMaskMultiple_t *src, int index ) +{ + gGL->glColorMaskIndexedEXT ( index, src->r, src->g, src->b, src->a ); +} + +FORCEINLINE void GLContextGetIndexed( GLColorMaskMultiple_t *dst, int index ) +{ + gGL->glGetBooleanIndexedvEXT ( GL_COLOR_WRITEMASK, index, (GLboolean*)&dst->r ); +} + +FORCEINLINE void GLContextGetDefaultIndexed( GLColorMaskMultiple_t *dst, int index ) +{ + dst->r = dst->g = dst->b = dst->a = 1; +} + + +// --- GLBlendEnable --- +FORCEINLINE void GLContextSet( GLBlendEnable_t *src ) +{ + glSetEnable( GL_BLEND, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLBlendEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_BLEND ); +} + +FORCEINLINE void GLContextGetDefault( GLBlendEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLBlendFactor --- +FORCEINLINE void GLContextSet( GLBlendFactor_t *src ) +{ + gGL->glBlendFunc ( src->srcfactor, src->dstfactor ); +} + +FORCEINLINE void GLContextGet( GLBlendFactor_t *dst ) +{ + glGetEnumv ( GL_BLEND_SRC, &dst->srcfactor ); + glGetEnumv ( GL_BLEND_DST, &dst->dstfactor ); +} + +FORCEINLINE void GLContextGetDefault( GLBlendFactor_t *dst ) +{ + dst->srcfactor = GL_ONE; + dst->dstfactor = GL_ZERO; +} + + +// --- GLBlendEquation --- +FORCEINLINE void GLContextSet( GLBlendEquation_t *src ) +{ + gGL->glBlendEquation ( src->equation ); +} + +FORCEINLINE void GLContextGet( GLBlendEquation_t *dst ) +{ + glGetEnumv ( GL_BLEND_EQUATION, &dst->equation ); +} + +FORCEINLINE void GLContextGetDefault( GLBlendEquation_t *dst ) +{ + dst->equation = GL_FUNC_ADD; +} + + +// --- GLBlendColor --- +FORCEINLINE void GLContextSet( GLBlendColor_t *src ) +{ + gGL->glBlendColor ( src->r, src->g, src->b, src->a ); +} + +FORCEINLINE void GLContextGet( GLBlendColor_t *dst ) +{ + gGL->glGetFloatv ( GL_BLEND_COLOR, &dst->r ); +} + +FORCEINLINE void GLContextGetDefault( GLBlendColor_t *dst ) +{ + //solid white + dst->r = dst->g = dst->b = dst->a = 1.0; +} + + +// --- GLBlendEnableSRGB --- + +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_COLOR_ATTACHMENT0 0x8CE0 + +FORCEINLINE void GLContextSet( GLBlendEnableSRGB_t *src ) +{ +#if GLMDEBUG + // just check in debug... this is too expensive to look at on MTGL + if (src->enable) + { + GLboolean srgb_capable = false; + gGL->glGetBooleanv( GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable); + + if (src->enable && !srgb_capable) + { + GLMPRINTF(("-Z- srgb-state-set FBO conflict: attempt to enable SRGB on non SRGB capable FBO config")); + } + } +#endif + // this query is not useful unless you have the ARB_framebuffer_srgb ext. + //GLint encoding = 0; + //pfnglGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encoding ); + + glSetEnable( GL_FRAMEBUFFER_SRGB_EXT, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLBlendEnableSRGB_t *dst ) +{ + //dst->enable = glIsEnabled( GL_FRAMEBUFFER_SRGB_EXT ); + dst->enable = true; // wtf ? +} + +FORCEINLINE void GLContextGetDefault( GLBlendEnableSRGB_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLDepthTestEnable --- +FORCEINLINE void GLContextSet( GLDepthTestEnable_t *src ) +{ + glSetEnable( GL_DEPTH_TEST, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLDepthTestEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_DEPTH_TEST ); +} + +FORCEINLINE void GLContextGetDefault( GLDepthTestEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLDepthFunc --- +FORCEINLINE void GLContextSet( GLDepthFunc_t *src ) +{ + gGL->glDepthFunc ( src->func ); +} + +FORCEINLINE void GLContextGet( GLDepthFunc_t *dst ) +{ + glGetEnumv ( GL_DEPTH_FUNC, &dst->func ); +} + +FORCEINLINE void GLContextGetDefault( GLDepthFunc_t *dst ) +{ + dst->func = GL_GEQUAL; +} + + +// --- GLDepthMask --- +FORCEINLINE void GLContextSet( GLDepthMask_t *src ) +{ + gGL->glDepthMask ( src->mask ); +} + +FORCEINLINE void GLContextGet( GLDepthMask_t *dst ) +{ + gGL->glGetBooleanv ( GL_DEPTH_WRITEMASK, (GLboolean*)&dst->mask ); +} + +FORCEINLINE void GLContextGetDefault( GLDepthMask_t *dst ) +{ + dst->mask = GL_TRUE; +} + + +// --- GLStencilTestEnable --- +FORCEINLINE void GLContextSet( GLStencilTestEnable_t *src ) +{ + glSetEnable( GL_STENCIL_TEST, src->enable != 0 ); +} + +FORCEINLINE void GLContextGet( GLStencilTestEnable_t *dst ) +{ + dst->enable = gGL->glIsEnabled( GL_STENCIL_TEST ); +} + +FORCEINLINE void GLContextGetDefault( GLStencilTestEnable_t *dst ) +{ + dst->enable = GL_FALSE; +} + + +// --- GLStencilFunc --- +FORCEINLINE void GLContextSet( GLStencilFunc_t *src ) +{ + if (src->frontfunc == src->backfunc) + gGL->glStencilFuncSeparate( GL_FRONT_AND_BACK, src->frontfunc, src->ref, src->mask); + else + { + gGL->glStencilFuncSeparate( GL_FRONT, src->frontfunc, src->ref, src->mask); + gGL->glStencilFuncSeparate( GL_BACK, src->backfunc, src->ref, src->mask); + } +} + +FORCEINLINE void GLContextGet( GLStencilFunc_t *dst ) +{ + glGetEnumv ( GL_STENCIL_FUNC, &dst->frontfunc ); + glGetEnumv ( GL_STENCIL_BACK_FUNC, &dst->backfunc ); + gGL->glGetIntegerv ( GL_STENCIL_REF, &dst->ref ); + gGL->glGetIntegerv ( GL_STENCIL_VALUE_MASK, (GLint*)&dst->mask ); +} + +FORCEINLINE void GLContextGetDefault( GLStencilFunc_t *dst ) +{ + dst->frontfunc = GL_ALWAYS; + dst->backfunc = GL_ALWAYS; + dst->ref = 0; + dst->mask = 0xFFFFFFFF; +} + + +// --- GLStencilOp --- indexed 0=front, 1=back + +FORCEINLINE void GLContextSetIndexed( GLStencilOp_t *src, int index ) +{ + GLenum face = (index==0) ? GL_FRONT : GL_BACK; + gGL->glStencilOpSeparate( face, src->sfail, src->dpfail, src->dppass ); +} + +FORCEINLINE void GLContextGetIndexed( GLStencilOp_t *dst, int index ) +{ + glGetEnumv ( (index==0) ? GL_STENCIL_FAIL : GL_STENCIL_BACK_FAIL, &dst->sfail ); + glGetEnumv ( (index==0) ? GL_STENCIL_PASS_DEPTH_FAIL : GL_STENCIL_BACK_PASS_DEPTH_FAIL, &dst->dpfail ); + glGetEnumv ( (index==0) ? GL_STENCIL_PASS_DEPTH_PASS : GL_STENCIL_BACK_PASS_DEPTH_PASS, &dst->dppass ); +} + +FORCEINLINE void GLContextGetDefaultIndexed( GLStencilOp_t *dst, int index ) +{ + dst->sfail = dst->dpfail = dst->dppass = GL_KEEP; +} + + +// --- GLStencilWriteMask --- +FORCEINLINE void GLContextSet( GLStencilWriteMask_t *src ) +{ + gGL->glStencilMask( src->mask ); +} + +FORCEINLINE void GLContextGet( GLStencilWriteMask_t *dst ) +{ + gGL->glGetIntegerv ( GL_STENCIL_WRITEMASK, &dst->mask ); +} + +FORCEINLINE void GLContextGetDefault( GLStencilWriteMask_t *dst ) +{ + dst->mask = 0xFFFFFFFF; +} + + +// --- GLClearColor --- +FORCEINLINE void GLContextSet( GLClearColor_t *src ) +{ + gGL->glClearColor( src->r, src->g, src->b, src->a ); +} + +FORCEINLINE void GLContextGet( GLClearColor_t *dst ) +{ + gGL->glGetFloatv ( GL_COLOR_CLEAR_VALUE, &dst->r ); +} + +FORCEINLINE void GLContextGetDefault( GLClearColor_t *dst ) +{ + dst->r = dst->g = dst->b = 0.5; + dst->a = 1.0; +} + + +// --- GLClearDepth --- +FORCEINLINE void GLContextSet( GLClearDepth_t *src ) +{ + gGL->glClearDepth ( src->d ); +} + +FORCEINLINE void GLContextGet( GLClearDepth_t *dst ) +{ + gGL->glGetDoublev ( GL_DEPTH_CLEAR_VALUE, &dst->d ); +} + +FORCEINLINE void GLContextGetDefault( GLClearDepth_t *dst ) +{ + dst->d = 1.0; +} + + +// --- GLClearStencil --- +FORCEINLINE void GLContextSet( GLClearStencil_t *src ) +{ + gGL->glClearStencil( src->s ); +} + +FORCEINLINE void GLContextGet( GLClearStencil_t *dst ) +{ + gGL->glGetIntegerv ( GL_STENCIL_CLEAR_VALUE, &dst->s ); +} + +FORCEINLINE void GLContextGetDefault( GLClearStencil_t *dst ) +{ + dst->s = 0; +} + +//===========================================================================// + +// caching state object template. One of these is instantiated in the context per unique struct type above +template class GLState +{ + public: + inline GLState() + { + memset( &data, 0, sizeof(data) ); + Default(); + } + + FORCEINLINE void Flush() + { + // immediately blast out the state - it makes no sense to delta it or do anything fancy because shaderapi, dxabstract, and OpenGL itself does this for us (and OpenGL calls with multithreaded drivers are very cheap) + GLContextSet( &data ); + } + + // write: client src into cache + // common case is both false. dirty is calculated, context write is deferred. + FORCEINLINE void Write( const T *src ) + { + data = *src; + Flush(); + } + + // default: write default value to cache, optionally write through + inline void Default( bool noDefer=false ) + { + GLContextGetDefault( &data ); // read default values directly to our cache copy + Flush(); + } + + // read: sel = 0 for cache, 1 for context + inline void Read( T *dst, int sel ) + { + if (sel==0) + *dst = data; + else + GLContextGet( dst ); + } + + // check: verify that context equals cache, return true if mismatched or if illegal values seen + inline bool Check ( void ) + { + T temp; + bool result; + + GLContextGet( &temp ); + result = !(temp == data); + return result; + } + + FORCEINLINE const T &GetData() const { return data; } + + protected: + T data; +}; + +// caching state object template - with multiple values behind it that are indexed +template class GLStateArray +{ + public: + inline GLStateArray() + { + memset( &data, 0, sizeof(data) ); + Default(); + } + + // write cache->context if dirty or forced. + FORCEINLINE void FlushIndex( int index ) + { + // immediately blast out the state - it makes no sense to delta it or do anything fancy because shaderapi, dxabstract, and OpenGL itself does this for us (and OpenGL calls with multithreaded drivers are very cheap) + GLContextSetIndexed( &data[index], index ); + }; + + // write: client src into cache + // common case is both false. dirty is calculated, context write is deferred. + FORCEINLINE void WriteIndex( T *src, int index ) + { + data[index] = *src; + FlushIndex( index ); // dirty becomes false + }; + + // write all slots in the array + FORCEINLINE void Flush() + { + for( int i=0; i < COUNT; i++) + { + FlushIndex( i ); + } + } + + // default: write default value to cache, optionally write through + inline void DefaultIndex( int index ) + { + GLContextGetDefaultIndexed( &data[index], index ); // read default values directly to our cache copy + Flush(); + }; + + inline void Default( void ) + { + for( int i=0; i((reinterpret_cast(m_pRawBuf) + 65535) & (~65535)); + m_nSize = nSize; + m_nOfs = 0; + + gGL->glGenBuffersARB( 1, &m_nBufferObj ); + gGL->glBindBufferARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nBufferObj ); + + gGL->glBufferDataARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nSize, m_pBuf, GL_STREAM_COPY ); + + return true; + } + + void Deinit() + { + if ( !m_pRawBuf ) + return; + + BlockUntilNotBusy(); + + gGL->glBindBufferARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nBufferObj ); + + gGL->glBufferDataARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0, (void*)NULL, GL_STREAM_COPY ); + + gGL->glBindBufferARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0 ); + + gGL->glDeleteBuffersARB( 1, &m_nBufferObj ); + m_nBufferObj = 0; + + free( m_pRawBuf ); + m_pRawBuf = NULL; + m_pBuf = NULL; + + m_nSize = 0; + m_nOfs = 0; + } + + inline uint GetSize() const { return m_nSize; } + inline uint GetOfs() const { return m_nOfs; } + inline uint GetBytesRemaining() const { return m_nSize - m_nOfs; } + inline void *GetPtr() const { return m_pBuf; } + inline GLuint GetHandle() const { return m_nBufferObj; } + + void InsertFence() + { + if ( m_nSyncObj ) + { + gGL->glDeleteSync( m_nSyncObj ); + } + + m_nSyncObj = gGL->glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 ); + } + + void BlockUntilNotBusy() + { + if ( m_nSyncObj ) + { + gGL->glClientWaitSync( m_nSyncObj, GL_SYNC_FLUSH_COMMANDS_BIT, 3000000000000ULL ); + + gGL->glDeleteSync( m_nSyncObj ); + + m_nSyncObj = 0; + } + m_nOfs = 0; + } + + void Append( uint nSize ) + { + m_nOfs += nSize; + Assert( m_nOfs <= m_nSize ); + } + +private: + void *m_pRawBuf; + void *m_pBuf; + uint m_nSize; + uint m_nOfs; + + GLuint m_nBufferObj; + + GLsync m_nSyncObj; +}; + +//===========================================================================// + +class GLMContext +{ + public: + // set/check current context (perq for many other calls) + void MakeCurrent( bool bRenderThread = false ); + void ReleaseCurrent( bool bRenderThread = false ); + + // CheckCurrent has been removed (it no longer compiled on Linux). To minimize churn I'm leaving + // the inline NOP version. + // DO NOT change this to non-inlined. It's called all over the place from very hot codepaths. + FORCEINLINE void CheckCurrent( void ) { } + + void PopulateCaps( void ); // fill out later portions of renderer info record which need context queries + void DumpCaps( void ); // printf all the caps info (you can call this in release too) + const GLMRendererInfoFields& Caps( void ); // peek at the caps record + + // state cache/mirror + void SetDefaultStates( void ); + void ForceFlushStates(); + + void VerifyStates( void ); + + // textures + // Lock and Unlock reqs go directly to the tex object + CGLMTex *NewTex( GLMTexLayoutKey *key, const char *debugLabel=NULL ); + void DelTex( CGLMTex *tex ); + + // options for Blit (replacement for ResolveTex and BlitTex) + // pass NULL for dstTex if you want to target GL_BACK with the blit. You get y-flip with that, don't change the dstrect yourself. + void Blit2( CGLMTex *srcTex, GLMRect *srcRect, int srcFace, int srcMip, CGLMTex *dstTex, GLMRect *dstRect, int dstFace, int dstMip, uint filter ); + + // tex blit (via FBO blit) + void BlitTex( CGLMTex *srcTex, GLMRect *srcRect, int srcFace, int srcMip, CGLMTex *dstTex, GLMRect *dstRect, int dstFace, int dstMip, uint filter, bool useBlitFB = true ); + + // MSAA resolve - we do this in GLMContext because it has to do a bunch of FBO/blit gymnastics + void ResolveTex( CGLMTex *tex, bool forceDirty=false ); + + // texture pre-load (residency forcing) - normally done one-time but you can force it + void PreloadTex( CGLMTex *tex, bool force=false ); + + // samplers + FORCEINLINE void SetSamplerTex( int sampler, CGLMTex *tex ); + + FORCEINLINE void SetSamplerDirty( int sampler ); + FORCEINLINE void SetSamplerMinFilter( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerMagFilter( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerMipFilter( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerAddressU( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerAddressV( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerAddressW( int sampler, GLenum Value ); + FORCEINLINE void SetSamplerStates( int sampler, GLenum AddressU, GLenum AddressV, GLenum AddressW, GLenum minFilter, GLenum magFilter, GLenum mipFilter ); + FORCEINLINE void SetSamplerBorderColor( int sampler, DWORD Value ); + FORCEINLINE void SetSamplerMipMapLODBias( int sampler, DWORD Value ); + FORCEINLINE void SetSamplerMaxMipLevel( int sampler, DWORD Value ); + FORCEINLINE void SetSamplerMaxAnisotropy( int sampler, DWORD Value ); + FORCEINLINE void SetSamplerSRGBTexture( int sampler, DWORD Value ); + FORCEINLINE void SetShadowFilter( int sampler, DWORD Value ); + + // render targets (FBO's) + CGLMFBO *NewFBO( void ); + void DelFBO( CGLMFBO *fbo ); + + // programs + CGLMProgram *NewProgram( EGLMProgramType type, char *progString, const char *pShaderName ); + void DelProgram( CGLMProgram *pProg ); + void NullProgram( void ); // de-ac all shader state + + FORCEINLINE void SetVertexProgram( CGLMProgram *pProg ); + FORCEINLINE void SetFragmentProgram( CGLMProgram *pProg ); + FORCEINLINE void SetProgram( EGLMProgramType nProgType, CGLMProgram *pProg ) { m_drawingProgram[nProgType] = pProg; m_bDirtyPrograms = true; } + + void SetDrawingLang( EGLMProgramLang lang, bool immediate=false ); // choose ARB or GLSL. immediate=false defers lang change to top of frame + + void LinkShaderPair( CGLMProgram *vp, CGLMProgram *fp ); // ensure this combo has been linked and is in the GLSL pair cache + void ClearShaderPairCache( void ); // call this to shoot down all the linked pairs + void QueryShaderPair( int index, GLMShaderPairInfo *infoOut ); // this lets you query the shader pair cache for saving its state + + // buffers + // Lock and Unlock reqs go directly to the buffer object + CGLMBuffer *NewBuffer( EGLMBufferType type, uint size, uint options ); + void DelBuffer( CGLMBuffer *buff ); + + FORCEINLINE void SetIndexBuffer( CGLMBuffer *buff ) { BindIndexBufferToCtx( buff ); } + + // FIXME: Remove this, it's no longer used + FORCEINLINE void SetVertexAttributes( GLMVertexSetup *setup ) + { + // we now just latch the vert setup and then execute on it at flushdrawstatestime if shaders are enabled. + if ( setup ) + { + m_drawVertexSetup = *setup; + } + else + { + memset( &m_drawVertexSetup, 0, sizeof( m_drawVertexSetup ) ); + } + } + + // note, no API is exposed for setting a single attribute source. + // come prepared with a complete block of attributes to use. + + // Queries + CGLMQuery *NewQuery( GLMQueryParams *params ); + void DelQuery( CGLMQuery *query ); + + // "slot" means a vec4-sized thing + // these write into .env parameter space + FORCEINLINE void SetProgramParametersF( EGLMProgramType type, uint baseSlot, float *slotData, uint slotCount ); + FORCEINLINE void SetProgramParametersB( EGLMProgramType type, uint baseSlot, int *slotData, uint boolCount ); // take "BOOL" aka int + FORCEINLINE void SetProgramParametersI( EGLMProgramType type, uint baseSlot, int *slotData, uint slotCount ); // take int4s + + // state sync + // If lazyUnbinding is true, unbound samplers will not actually be unbound to the GL device. + FORCEINLINE void FlushDrawStates( uint nStartIndex, uint nEndIndex, uint nBaseVertex ); // pushes all drawing state - samplers, tex, programs, etc. + void FlushDrawStatesNoShaders(); + + // drawing + FORCEINLINE void DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ); + void DrawRangeElementsNonInline( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ); + + void CheckNative( void ); + + // clearing + void Clear( bool color, unsigned long colorValue, bool depth, float depthValue, bool stencil, unsigned int stencilValue, GLScissorBox_t *rect = NULL ); + + // display + //void SetVSyncEnable( bool vsyncOn ); + //void SetFullScreen( bool fsOn, int screenIndex ); // will be latched for next BeginFrame + //void ActivateFullScreen( bool fsOn, int screenIndex ); // will be called by BeginFrame + bool SetDisplayParams( GLMDisplayParams *params ); // either the first time setup, or a change to new setup + + void Present( CGLMTex *tex ); // somewhat hardwired for the time being + + // Called when IDirect3DDevice9::Reset() is called. + void Reset(); + + // writers for the state block inputs + + FORCEINLINE void WriteAlphaTestEnable( GLAlphaTestEnable_t *src ) { m_AlphaTestEnable.Write( src ); } + FORCEINLINE void WriteAlphaTestFunc( GLAlphaTestFunc_t *src ) { m_AlphaTestFunc.Write( src ); } + FORCEINLINE void WriteAlphaToCoverageEnable( GLAlphaToCoverageEnable_t *src ) { m_AlphaToCoverageEnable.Write( src ); } + FORCEINLINE void WriteCullFaceEnable( GLCullFaceEnable_t *src ) { m_CullFaceEnable.Write( src ); } + FORCEINLINE void WriteCullFrontFace( GLCullFrontFace_t *src ) { m_CullFrontFace.Write( src ); } + FORCEINLINE void WritePolygonMode( GLPolygonMode_t *src ) { m_PolygonMode.Write( src ); } + FORCEINLINE void WriteDepthBias( GLDepthBias_t *src ) { m_DepthBias.Write( src ); } + FORCEINLINE void WriteClipPlaneEnable( GLClipPlaneEnable_t *src, int which ) { m_ClipPlaneEnable.WriteIndex( src, which ); } + FORCEINLINE void WriteClipPlaneEquation( GLClipPlaneEquation_t *src, int which ) { m_ClipPlaneEquation.WriteIndex( src, which ); } + FORCEINLINE void WriteScissorEnable( GLScissorEnable_t *src ) { m_ScissorEnable.Write( src ); } + FORCEINLINE void WriteScissorBox( GLScissorBox_t *src ) { m_ScissorBox.Write( src ); } + FORCEINLINE void WriteViewportBox( GLViewportBox_t *src ) { m_ViewportBox.Write( src ); } + FORCEINLINE void WriteViewportDepthRange( GLViewportDepthRange_t *src ) { m_ViewportDepthRange.Write( src ); } + FORCEINLINE void WriteColorMaskSingle( GLColorMaskSingle_t *src ) { m_ColorMaskSingle.Write( src ); } + FORCEINLINE void WriteColorMaskMultiple( GLColorMaskMultiple_t *src, int which ) { m_ColorMaskMultiple.WriteIndex( src, which ); } + FORCEINLINE void WriteBlendEnable( GLBlendEnable_t *src ) { m_BlendEnable.Write( src ); } + FORCEINLINE void WriteBlendFactor( GLBlendFactor_t *src ) { m_BlendFactor.Write( src ); } + FORCEINLINE void WriteBlendEquation( GLBlendEquation_t *src ) { m_BlendEquation.Write( src ); } + FORCEINLINE void WriteBlendColor( GLBlendColor_t *src ) { m_BlendColor.Write( src ); } + + FORCEINLINE void WriteBlendEnableSRGB( GLBlendEnableSRGB_t *src ) + { + if (m_caps.m_hasGammaWrites) // only if caps allow do we actually push it through to the extension + { + m_BlendEnableSRGB.Write( src ); + } + else + { + m_FakeBlendEnableSRGB = src->enable != 0; + } + // note however that we're still tracking what this mode should be, so FlushDrawStates can look at it and adjust the pixel shader + // if fake SRGB mode is in place (m_caps.m_hasGammaWrites is false) + } + + FORCEINLINE void WriteDepthTestEnable( GLDepthTestEnable_t *src ) { m_DepthTestEnable.Write( src ); } + FORCEINLINE void WriteDepthFunc( GLDepthFunc_t *src ) { m_DepthFunc.Write( src ); } + FORCEINLINE void WriteDepthMask( GLDepthMask_t *src ) { m_DepthMask.Write( src ); } + FORCEINLINE void WriteStencilTestEnable( GLStencilTestEnable_t *src ) { m_StencilTestEnable.Write( src ); } + FORCEINLINE void WriteStencilFunc( GLStencilFunc_t *src ) { m_StencilFunc.Write( src ); } + FORCEINLINE void WriteStencilOp( GLStencilOp_t *src, int which ) { m_StencilOp.WriteIndex( src, which ); } + FORCEINLINE void WriteStencilWriteMask( GLStencilWriteMask_t *src ) { m_StencilWriteMask.Write( src ); } + FORCEINLINE void WriteClearColor( GLClearColor_t *src ) { m_ClearColor.Write( src ); } + FORCEINLINE void WriteClearDepth( GLClearDepth_t *src ) { m_ClearDepth.Write( src ); } + FORCEINLINE void WriteClearStencil( GLClearStencil_t *src ) { m_ClearStencil.Write( src ); } + + // debug stuff + void BeginFrame( void ); + void EndFrame( void ); + + // new interactive debug stuff +#if GLMDEBUG + void DebugDump( GLMDebugHookInfo *info, uint options, uint vertDumpMode ); + void DebugHook( GLMDebugHookInfo *info ); + void DebugPresent( void ); + void DebugClear( void ); +#endif + + FORCEINLINE void SetMaxUsedVertexShaderConstantsHint( uint nMaxConstants ); + + FORCEINLINE DWORD GetCurrentOwnerThreadId() const { return m_nCurOwnerThreadId; } + + protected: + friend class GLMgr; // only GLMgr can make GLMContext objects + friend class GLMRendererInfo; // only GLMgr can make GLMContext objects + friend class CGLMTex; // tex needs to be able to do binds + friend class CGLMFBO; // fbo needs to be able to do binds + friend class CGLMProgram; + friend class CGLMShaderPair; + friend class CGLMShaderPairCache; + friend class CGLMBuffer; + friend class CGLMBufferSpanManager; + friend class GLMTester; // tester class needs access back into GLMContext + + friend struct IDirect3D9; + friend struct IDirect3DDevice9; + friend struct IDirect3DQuery9; + + // methods------------------------------------------ + + // old GLMContext( GLint displayMask, GLint rendererID, PseudoNSGLContextPtr nsglShareCtx ); + GLMContext( IDirect3DDevice9 *pDevice, GLMDisplayParams *params ); + ~GLMContext(); + + FORCEINLINE GLuint FindSamplerObject( const GLMTexSamplingParams &desiredParams ); + + FORCEINLINE void SetBufAndVertexAttribPointer( uint nIndex, GLuint nGLName, GLuint stride, GLuint datatype, GLboolean normalized, GLuint nCompCount, const void *pBuf, uint nRevision ) + { + VertexAttribs_t &curAttribs = m_boundVertexAttribs[nIndex]; + if ( nGLName != m_nBoundGLBuffer[kGLMVertexBuffer] ) + { + m_nBoundGLBuffer[kGLMVertexBuffer] = nGLName; + gGL->glBindBufferARB( GL_ARRAY_BUFFER_ARB, nGLName ); + } + else if ( ( curAttribs.m_pPtr == pBuf ) && + ( curAttribs.m_revision == nRevision ) && + ( curAttribs.m_stride == stride ) && + ( curAttribs.m_datatype == datatype ) && + ( curAttribs.m_normalized == normalized ) && + ( curAttribs.m_nCompCount == nCompCount ) ) + { + return; + } + + curAttribs.m_nCompCount = nCompCount; + curAttribs.m_datatype = datatype; + curAttribs.m_normalized = normalized; + curAttribs.m_stride = stride; + curAttribs.m_pPtr = pBuf; + curAttribs.m_revision = nRevision; + + gGL->glVertexAttribPointer( nIndex, nCompCount, datatype, normalized, stride, pBuf ); + } + + struct CurAttribs_t + { + uint m_nTotalBufferRevision; + IDirect3DVertexDeclaration9 *m_pVertDecl; + D3DStreamDesc m_streams[ D3D_MAX_STREAMS ]; + uint64 m_vtxAttribMap[2]; + }; + + CurAttribs_t m_CurAttribs; + + FORCEINLINE void ClearCurAttribs() + { + m_CurAttribs.m_nTotalBufferRevision = 0; + m_CurAttribs.m_pVertDecl = NULL; + memset( m_CurAttribs.m_streams, 0, sizeof( m_CurAttribs.m_streams ) ); + m_CurAttribs.m_vtxAttribMap[0] = 0xBBBBBBBBBBBBBBBBULL; + m_CurAttribs.m_vtxAttribMap[1] = 0xBBBBBBBBBBBBBBBBULL; + } + + FORCEINLINE void ReleasedShader() { NullProgram(); } + + // textures + FORCEINLINE void SelectTMU( int tmu ) + { + if ( tmu != m_activeTexture ) + { + gGL->glActiveTexture( GL_TEXTURE0 + tmu ); + m_activeTexture = tmu; + } + } + + void BindTexToTMU( CGLMTex *tex, int tmu ); + + // render targets / FBO's + void BindFBOToCtx( CGLMFBO *fbo, GLenum bindPoint = GL_FRAMEBUFFER_EXT ); // you can also choose GL_READ_FRAMEBUFFER_EXT / GL_DRAW_FRAMEBUFFER_EXT + + // buffers + FORCEINLINE void BindGLBufferToCtx( GLenum nGLBufType, GLuint nGLName, bool bForce = false ) + { + Assert( ( nGLBufType == GL_ARRAY_BUFFER_ARB ) || ( nGLBufType == GL_ELEMENT_ARRAY_BUFFER_ARB ) ); + + const uint nIndex = ( nGLBufType == GL_ARRAY_BUFFER_ARB ) ? kGLMVertexBuffer : kGLMIndexBuffer; + if ( ( bForce ) || ( m_nBoundGLBuffer[nIndex] != nGLName ) ) + { + m_nBoundGLBuffer[nIndex] = nGLName; + gGL->glBindBufferARB( nGLBufType, nGLName ); + } + } + + void BindBufferToCtx( EGLMBufferType type, CGLMBuffer *buff, bool force = false ); // does not twiddle any enables. + + FORCEINLINE void BindIndexBufferToCtx( CGLMBuffer *buff ); + FORCEINLINE void BindVertexBufferToCtx( CGLMBuffer *buff ); + + CPinnedMemoryBuffer *GetCurPinnedMemoryBuffer( ) { return &m_PinnedMemoryBuffers[m_nCurPinnedMemoryBuffer]; } + + // members------------------------------------------ + + // context + DWORD m_nCurOwnerThreadId; + uint m_nThreadOwnershipReleaseCounter; + + bool m_bUseSamplerObjects; + bool m_bPreferMapBufferRange; + + IDirect3DDevice9 *m_pDevice; + GLMRendererInfoFields m_caps; + + bool m_displayParamsValid; // is there a param block copied in yet + GLMDisplayParams m_displayParams; // last known display config, either via constructor, or by SetDisplayParams... + +#ifdef OSX + CGLPixelFormatAttribute m_pixelFormatAttribs[100]; // more than enough + PseudoNSGLContextPtr m_nsctx; + CGLContextObj m_ctx; +#elif defined( USE_SDL ) + int m_pixelFormatAttribs[100]; // more than enough + PseudoNSGLContextPtr m_nsctx; + void * m_ctx; +#endif + bool m_oneCtxEnable; // true if we use the window's context directly instead of making a second one shared against it + + bool m_bUseBoneUniformBuffers; // if true, we use two uniform buffers for vertex shader constants vs. one + + // texture form table + CGLMTexLayoutTable *m_texLayoutTable; + + // context state mirrors + + GLState m_AlphaTestEnable; + + GLState m_AlphaTestFunc; + + GLState m_CullFaceEnable; + GLState m_CullFrontFace; + GLState m_PolygonMode; + + GLState m_DepthBias; + + GLStateArray m_ClipPlaneEnable; + GLStateArray m_ClipPlaneEquation; // dxabstract puts them directly into param slot 253(0) and 254(1) + + GLState m_ScissorEnable; + GLState m_ScissorBox; + + GLState m_AlphaToCoverageEnable; + + GLState m_ViewportBox; + GLState m_ViewportDepthRange; + + GLState m_ColorMaskSingle; + GLStateArray m_ColorMaskMultiple; // need an official constant for the color buffers limit + + GLState m_BlendEnable; + GLState m_BlendFactor; + GLState m_BlendEquation; + GLState m_BlendColor; + GLState m_BlendEnableSRGB; // write to this one to transmit intent to write SRGB encoded pixels to drawing FB + bool m_FakeBlendEnableSRGB; // writes to above will be shunted here if fake SRGB is in effect. + + GLState m_DepthTestEnable; + GLState m_DepthFunc; + GLState m_DepthMask; + + GLState m_StencilTestEnable; // global stencil test enable + GLState m_StencilFunc; // holds front and back stencil funcs + GLStateArray m_StencilOp; // indexed: 0=front 1=back + GLState m_StencilWriteMask; + + GLState m_ClearColor; + GLState m_ClearDepth; + GLState m_ClearStencil; + + // texture bindings and sampler setup + int m_activeTexture; // mirror for glActiveTexture + GLMTexSampler m_samplers[GLM_SAMPLER_COUNT]; + + uint8 m_nDirtySamplerFlags[GLM_SAMPLER_COUNT]; // 0 if the sampler is dirty, 1 if not + uint32 m_nNumDirtySamplers; // # of unique dirty sampler indices in m_nDirtySamplers + uint8 m_nDirtySamplers[GLM_SAMPLER_COUNT + 1]; // dirty sampler indices + + void MarkAllSamplersDirty(); + + struct SamplerHashEntry + { + GLuint m_samplerObject; + GLMTexSamplingParams m_params; + }; + + enum + { + cSamplerObjectHashBits = 9, cSamplerObjectHashSize = 1 << cSamplerObjectHashBits + }; + SamplerHashEntry m_samplerObjectHash[cSamplerObjectHashSize]; + uint m_nSamplerObjectHashNumEntries; + + // texture lock tracking - CGLMTex objects share usage of this + CUtlVector< GLMTexLockDesc > m_texLocks; + + // render target binding - check before draw + // similar to tex sampler mechanism, we track "bound" from "chosen for drawing" separately, + // so binding for creation/setup need not disrupt any notion of what will be used at draw time + + CGLMFBO *m_boundDrawFBO; // FBO on GL_DRAW_FRAMEBUFFER bind point + CGLMFBO *m_boundReadFBO; // FBO on GL_READ_FRAMEBUFFER bind point + // ^ both are set if you bind to GL_FRAMEBUFFER_EXT + + CGLMFBO *m_drawingFBO; // what FBO should be bound at draw time (to both read/draw bp's). + + CGLMFBO *m_blitReadFBO; + CGLMFBO *m_blitDrawFBO; // scratch FBO's for framebuffer blit + + CGLMFBO *m_scratchFBO[ kGLMScratchFBOCount ]; // general purpose FBO's for internal use + + CUtlVector< CGLMFBO* > m_fboTable; // each live FBO goes in the table + + // program bindings + EGLMProgramLang m_drawingLangAtFrameStart; // selector for start of frame (spills into m_drawingLang) + EGLMProgramLang m_drawingLang; // selector for which language we desire to draw with on the next batch + CGLMProgram *m_drawingProgram[ kGLMNumProgramTypes ]; + bool m_bDirtyPrograms; + + GLMProgramParamsF m_programParamsF[ kGLMNumProgramTypes ]; + GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + GLMProgramParamsI m_programParamsI[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + EGLMParamWriteMode m_paramWriteMode; + + CGLMProgram *m_pNullFragmentProgram; // write opaque black. Activate when caller asks for null FP + + CGLMProgram *m_preloadTexVertexProgram; // programs to help preload textures (dummies) + CGLMProgram *m_preload2DTexFragmentProgram; + CGLMProgram *m_preload3DTexFragmentProgram; + CGLMProgram *m_preloadCubeTexFragmentProgram; + + CGLMShaderPairCache *m_pairCache; // GLSL only + CGLMShaderPair *m_pBoundPair; // GLSL only + + FORCEINLINE void NewLinkedProgram() { ClearCurAttribs(); } + + //uint m_boundPairRevision; // GLSL only + //GLhandleARB m_boundPairProgram; // GLSL only + + // buffer bindings + GLuint m_nBoundGLBuffer[kGLMNumBufferTypes]; + + struct VertexAttribs_t + { + GLuint m_nCompCount; + GLenum m_datatype; + GLboolean m_normalized; + GLuint m_stride; + const void *m_pPtr; + uint m_revision; + }; + + VertexAttribs_t m_boundVertexAttribs[ kGLMVertexAttributeIndexMax ]; // tracked per attrib for dupe-set-absorb + uint m_lastKnownVertexAttribMask; // tracked for dupe-enable-absorb + int m_nNumSetVertexAttributes; + + // FIXME: Remove this, it's no longer used + GLMVertexSetup m_drawVertexSetup; + + EGLMAttribWriteMode m_attribWriteMode; + + bool m_slowCheckEnable; // turn this on or no native checking is done ("-glmassertslow" or "-glmsspewslow") + bool m_slowAssertEnable; // turn this on to assert on a non-native batch "-glmassertslow" + bool m_slowSpewEnable; // turn this on to log non-native batches to stdout "-glmspewslow" + bool m_checkglErrorsAfterEveryBatch; // turn this on to check for GL errors after each batch (slow) ("-glcheckerrors") + + // debug font texture + CGLMTex *m_debugFontTex; // might be NULL unless you call GenDebugFontTex + CGLMBuffer *m_debugFontIndices; // up to 1024 indices (256 chars times 4) + CGLMBuffer *m_debugFontVertices; // up to 1024 verts + + // batch/frame debugging support + int m_debugFrameIndex; // init to -1. Increment at BeginFrame + + int m_nMaxUsedVertexProgramConstantsHint; + + uint32 m_dwRenderThreadId; + volatile bool m_bIsThreading; + + uint m_nCurFrame; + uint m_nBatchCounter; + + enum { cNumPinnedMemoryBuffers = 4 }; + CPinnedMemoryBuffer m_PinnedMemoryBuffers[cNumPinnedMemoryBuffers]; + uint m_nCurPinnedMemoryBuffer; + + void SaveColorMaskAndSetToDefault(); + void RestoreSavedColorMask(); + GLColorMaskSingle_t m_SavedColorMask; + +#if GLMDEBUG + // interactive (DebugHook) debug support + + // using these you can implement frame advance, batch single step, and batch rewind (let it run til next frame and hold on prev batch #) + int m_holdFrameBegin; // -1 if no hold req'd, otherwise # of frame to hold at (at beginframe time) + int m_holdFrameEnd; // -1 if no hold req'd, otherwise # of frame to hold at (at endframe time) + + int m_holdBatch,m_holdBatchFrame; // -1 if no hold, else # of batch&frame to hold at (both must be set) + // these can be expired/cleared to -1 if the frame passes without a hit + // may be desirable to re-pause in that event, as user was expecting a hold to occur + + bool m_debugDelayEnable; // allow sleep delay + uint m_debugDelay; // sleep time per hook call in microseconds (for usleep()) + + // pre-draw global toggles / options + bool m_autoClearColor,m_autoClearDepth,m_autoClearStencil; + float m_autoClearColorValues[4]; + + // debug knobs + int m_selKnobIndex; + float m_selKnobMinValue,m_selKnobMaxValue,m_selKnobIncrement; +#endif + +#if GL_BATCH_PERF_ANALYSIS + uint m_nTotalVSUniformCalls; + uint m_nTotalVSUniformBoneCalls; + uint m_nTotalVSUniformsSet; + uint m_nTotalVSUniformsBoneSet; + uint m_nTotalPSUniformCalls; + uint m_nTotalPSUniformsSet; + + CFlushDrawStatesStats m_FlushStats; +#endif +}; + +FORCEINLINE void GLMContext::DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ) +{ +#if GL_ENABLE_INDEX_VERIFICATION + DrawRangeElementsNonInline( mode, start, end, count, type, indices, baseVertex, pIndexBuf ); +#else + +#if GLMDEBUG + GLM_FUNC; +#else + //tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %d-%d count:%d mode:%d type:%d", __FUNCTION__, start, end, count, mode, type ); +#endif + + ++m_nBatchCounter; + + SetIndexBuffer( pIndexBuf ); + + void *indicesActual = (void*)indices; + + if ( pIndexBuf->m_bPseudo ) + { + // you have to pass actual address, not offset + indicesActual = (void*)( (int)indicesActual + (int)pIndexBuf->m_pPseudoBuf ); + } + +#if GLMDEBUG + bool hasVP = m_drawingProgram[ kGLMVertexProgram ] != NULL; + bool hasFP = m_drawingProgram[ kGLMFragmentProgram ] != NULL; + + // init debug hook information + GLMDebugHookInfo info; + memset( &info, 0, sizeof(info) ); + info.m_caller = eDrawElements; + + // relay parameters we're operating under + info.m_drawMode = mode; + info.m_drawStart = start; + info.m_drawEnd = end; + info.m_drawCount = count; + info.m_drawType = type; + info.m_drawIndices = indices; + + do + { + // obey global options re pre-draw clear + if ( m_autoClearColor || m_autoClearDepth || m_autoClearStencil ) + { + GLMPRINTF(("-- DrawRangeElements auto clear" )); + this->DebugClear(); + } + + // always sync with editable shader text prior to draw +#if GLMDEBUG + //FIXME disengage this path if context is in GLSL mode.. + // it will need fixes to get the shader pair re-linked etc if edits happen anyway. + + if (m_drawingProgram[ kGLMVertexProgram ]) + { + m_drawingProgram[ kGLMVertexProgram ]->SyncWithEditable(); + } + else + { + AssertOnce(!"drawing with no vertex program bound"); + } + + + if (m_drawingProgram[ kGLMFragmentProgram ]) + { + m_drawingProgram[ kGLMFragmentProgram ]->SyncWithEditable(); + } + else + { + AssertOnce(!"drawing with no fragment program bound"); + } +#endif + // do the drawing + if (hasVP && hasFP) + { + gGL->glDrawRangeElementsBaseVertex( mode, start, end, count, type, indicesActual, baseVertex ); + + if ( m_slowCheckEnable ) + { + CheckNative(); + } + } + this->DebugHook( &info ); + + } while ( info.m_loop ); +#else + Assert( m_drawingLang == kGLMGLSL ); + + if ( m_pBoundPair ) + { + gGL->glDrawRangeElementsBaseVertex( mode, start, end, count, type, indicesActual, baseVertex ); + +#if GLMDEBUG + if ( m_slowCheckEnable ) + { + CheckNative(); + } +#endif + } +#endif + +#endif // GL_ENABLE_INDEX_VERIFICATION +} + +FORCEINLINE void GLMContext::SetVertexProgram( CGLMProgram *pProg ) +{ + m_drawingProgram[kGLMVertexProgram] = pProg; + m_bDirtyPrograms = true; +} + +FORCEINLINE void GLMContext::SetFragmentProgram( CGLMProgram *pProg ) +{ + m_drawingProgram[kGLMFragmentProgram] = pProg ? pProg : m_pNullFragmentProgram; + m_bDirtyPrograms = true; +} + +// "slot" means a vec4-sized thing +// these write into .env parameter space +FORCEINLINE void GLMContext::SetProgramParametersF( EGLMProgramType type, uint baseSlot, float *slotData, uint slotCount ) +{ +#if GLMDEBUG + GLM_FUNC; +#endif + + Assert( baseSlot < kGLMProgramParamFloat4Limit ); + Assert( baseSlot+slotCount <= kGLMProgramParamFloat4Limit ); + +#if GLMDEBUG + GLMPRINTF(("-S-GLMContext::SetProgramParametersF %s slots %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + slotCount - 1 )); + for( uint i=0; i DXABSTRACT_VS_FIRST_BONE_SLOT ) + { + if ( baseSlot < DXABSTRACT_VS_FIRST_BONE_SLOT ) + { + // The register set crosses between the constant buffers - should only happen at startup during init. + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, (int)baseSlot ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, (int)MIN( baseSlot + slotCount, DXABSTRACT_VS_FIRST_BONE_SLOT ) ); + baseSlot = DXABSTRACT_VS_FIRST_BONE_SLOT; + } + + int nNumActualBones = ( baseSlot + slotCount ) - DXABSTRACT_VS_FIRST_BONE_SLOT; + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone, nNumActualBones ); + } + else + { + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, (int)baseSlot ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, (int)(baseSlot + slotCount) ); + } + } + else + { + m_programParamsF[type].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[type].m_dirtySlotHighWaterNonBone, (int)(baseSlot + slotCount) ); + m_programParamsF[type].m_firstDirtySlotNonBone = MIN( m_programParamsF[type].m_firstDirtySlotNonBone, (int)baseSlot ); + } +} + +FORCEINLINE void GLMContext::SetProgramParametersB( EGLMProgramType type, uint baseSlot, int *slotData, uint boolCount ) +{ +#if GLMDEBUG + GLM_FUNC; +#endif + + Assert( m_drawingLang == kGLMGLSL ); + Assert( type==kGLMVertexProgram ); + + Assert( baseSlot < kGLMProgramParamBoolLimit ); + Assert( baseSlot+boolCount <= kGLMProgramParamBoolLimit ); + +#if GLMDEBUG + GLMPRINTF(("-S-GLMContext::SetProgramParametersB %s bools %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + boolCount - 1 )); + for( uint i=0; i m_programParamsB[type].m_dirtySlotCount) + m_programParamsB[type].m_dirtySlotCount = baseSlot+boolCount; +} + +FORCEINLINE void GLMContext::SetProgramParametersI( EGLMProgramType type, uint baseSlot, int *slotData, uint slotCount ) // groups of 4 ints... +{ +#if GLMDEBUG + GLM_FUNC; +#endif + + Assert( m_drawingLang == kGLMGLSL ); + Assert( type==kGLMVertexProgram ); + + Assert( baseSlot < kGLMProgramParamInt4Limit ); + Assert( baseSlot+slotCount <= kGLMProgramParamInt4Limit ); + +#if GLMDEBUG + GLMPRINTF(("-S-GLMContext::SetProgramParametersI %s slots %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + slotCount - 1 )); + for( uint i=0; i m_programParamsI[type].m_dirtySlotCount) + { + m_programParamsI[type].m_dirtySlotCount = baseSlot + slotCount; + } +} + +FORCEINLINE void GLMContext::SetSamplerDirty( int sampler ) +{ + Assert( sampler < GLM_SAMPLER_COUNT ); + m_nDirtySamplers[m_nNumDirtySamplers] = sampler; + m_nNumDirtySamplers += m_nDirtySamplerFlags[sampler]; + m_nDirtySamplerFlags[sampler] = 0; +} + +FORCEINLINE void GLMContext::SetSamplerTex( int sampler, CGLMTex *tex ) +{ + Assert( sampler < GLM_SAMPLER_COUNT ); + m_samplers[sampler].m_pBoundTex = tex; + if ( tex ) + { + if ( !gGL->m_bHave_GL_EXT_direct_state_access ) + { + if ( sampler != m_activeTexture ) + { + gGL->glActiveTexture( GL_TEXTURE0 + sampler ); + m_activeTexture = sampler; + } + + gGL->glBindTexture( tex->m_texGLTarget, tex->m_texName ); + } + else + { + gGL->glBindMultiTextureEXT( GL_TEXTURE0 + sampler, tex->m_texGLTarget, tex->m_texName ); + } + } + + if ( !m_bUseSamplerObjects ) + { + SetSamplerDirty( sampler ); + } +} + +FORCEINLINE void GLMContext::SetSamplerMinFilter( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_minFilter = Value; +} + +FORCEINLINE void GLMContext::SetSamplerMagFilter( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_magFilter = Value; +} + +FORCEINLINE void GLMContext::SetSamplerMipFilter( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_mipFilter = Value; +} + +FORCEINLINE void GLMContext::SetSamplerAddressU( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + m_samplers[sampler].m_samp.m_packed.m_addressU = Value; +} + +FORCEINLINE void GLMContext::SetSamplerAddressV( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + m_samplers[sampler].m_samp.m_packed.m_addressV = Value; +} + +FORCEINLINE void GLMContext::SetSamplerAddressW( int sampler, GLenum Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + m_samplers[sampler].m_samp.m_packed.m_addressW = Value; +} + +FORCEINLINE void GLMContext::SetSamplerStates( int sampler, GLenum AddressU, GLenum AddressV, GLenum AddressW, GLenum minFilter, GLenum magFilter, GLenum mipFilter ) +{ + Assert( AddressU < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + Assert( AddressV < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + Assert( AddressW < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) ); + Assert( minFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS ) ); + Assert( magFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS ) ); + Assert( mipFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS ) ); + + GLMTexSamplingParams ¶ms = m_samplers[sampler].m_samp; + params.m_packed.m_addressU = AddressU; + params.m_packed.m_addressV = AddressV; + params.m_packed.m_addressW = AddressW; + params.m_packed.m_minFilter = minFilter; + params.m_packed.m_magFilter = magFilter; + params.m_packed.m_mipFilter = mipFilter; +} + +FORCEINLINE void GLMContext::SetSamplerBorderColor( int sampler, DWORD Value ) +{ + m_samplers[sampler].m_samp.m_borderColor = Value; +} + +FORCEINLINE void GLMContext::SetSamplerMipMapLODBias( int sampler, DWORD Value ) +{ + // not currently supported +} + +FORCEINLINE void GLMContext::SetSamplerMaxMipLevel( int sampler, DWORD Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_minLOD = Value; +} + +FORCEINLINE void GLMContext::SetSamplerMaxAnisotropy( int sampler, DWORD Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_maxAniso = Value; +} + +FORCEINLINE void GLMContext::SetSamplerSRGBTexture( int sampler, DWORD Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_srgb = Value; +} + +FORCEINLINE void GLMContext::SetShadowFilter( int sampler, DWORD Value ) +{ + Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS ) ); + m_samplers[sampler].m_samp.m_packed.m_compareMode = Value; +} + +FORCEINLINE void GLMContext::BindIndexBufferToCtx( CGLMBuffer *buff ) +{ + GLMPRINTF(( "--- GLMContext::BindIndexBufferToCtx buff %p, GL name %d", buff, (buff) ? buff->m_nHandle : -1 )); + + Assert( !buff || ( buff->m_buffGLTarget == GL_ELEMENT_ARRAY_BUFFER_ARB ) ); + + GLuint nGLName = buff ? buff->m_nHandle : 0; + + if ( m_nBoundGLBuffer[ kGLMIndexBuffer] == nGLName ) + return; + + m_nBoundGLBuffer[ kGLMIndexBuffer] = nGLName; + gGL->glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, nGLName ); +} + +FORCEINLINE void GLMContext::BindVertexBufferToCtx( CGLMBuffer *buff ) +{ + GLMPRINTF(( "--- GLMContext::BindVertexBufferToCtx buff %p, GL name %d", buff, (buff) ? buff->m_nHandle : -1 )); + + Assert( !buff || ( buff->m_buffGLTarget == GL_ARRAY_BUFFER_ARB ) ); + + GLuint nGLName = buff ? buff->m_nHandle : 0; + + if ( m_nBoundGLBuffer[ kGLMVertexBuffer] == nGLName ) + return; + + m_nBoundGLBuffer[ kGLMVertexBuffer] = nGLName; + gGL->glBindBufferARB( GL_ARRAY_BUFFER_ARB, nGLName ); +} + +FORCEINLINE void GLMContext::SetMaxUsedVertexShaderConstantsHint( uint nMaxConstants ) +{ + static bool bUseMaxVertexShadeConstantHints = !CommandLine()->CheckParm("-disablemaxvertexshaderconstanthints"); + if ( bUseMaxVertexShadeConstantHints ) + { + m_nMaxUsedVertexProgramConstantsHint = nMaxConstants; + } +} + +struct GLMTestParams +{ + GLMContext *m_ctx; + int *m_testList; // -1 termed + + bool m_glErrToDebugger; + bool m_glErrToConsole; + + bool m_intlErrToDebugger; + bool m_intlErrToConsole; + + int m_frameCount; // how many frames to test. +}; + +class CShowPixelsParams +{ +public: + GLuint m_srcTexName; + int m_width,m_height; + bool m_vsyncEnable; + bool m_fsEnable; // want receiving view to be full screen. for now, just target the main screen. extend later. + bool m_useBlit; // use FBO blit - sending context says it is available. + bool m_noBlit; // the back buffer has already been populated by the caller (perhaps via direct MSAA resolve from multisampled RT tex) + bool m_onlySyncView; // react to full/windowed state change only, do not present bits +}; + +#define kMaxCrawlFrames 100 +#define kMaxCrawlText (kMaxCrawlFrames * 256) +class CStackCrawlParams +{ + public: + uint m_frameLimit; // input: max frames to retrieve + uint m_frameCount; // output: frames found + void *m_crawl[kMaxCrawlFrames]; // call site addresses + char *m_crawlNames[kMaxCrawlFrames]; // pointers into text following, one per decoded name + char m_crawlText[kMaxCrawlText]; +}; + +#endif // GLMGR_H diff --git a/sp/src/public/togl/linuxwin/glmgrbasics.h b/sp/src/public/togl/linuxwin/glmgrbasics.h new file mode 100644 index 00000000..1897ebca --- /dev/null +++ b/sp/src/public/togl/linuxwin/glmgrbasics.h @@ -0,0 +1,308 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgrbasics.h +// types, common headers, forward declarations, utilities +// +//=============================================================================== + +#ifndef GLMBASICS_H +#define GLMBASICS_H + +#pragma once + +#ifdef OSX + #include + #include + #include + #include + #include + #include + #include + #include +#elif defined(DX_TO_GL_ABSTRACTION) + #include + #include +#else + #error +#endif + +#include "tier0/platform.h" + +#include "bitmap/imageformat.h" +#include "bitvec.h" +#include "tier1/checksum_md5.h" +#include "tier1/utlvector.h" +#include "tier1/convar.h" + +#include + +#include "dxabstract_types.h" + +struct GLMRect; +typedef void *PseudoGLContextPtr; + +// types + + // 3-d integer box (used for texture lock/unlock etc) +struct GLMRegion +{ + int xmin,xmax; + int ymin,ymax; + int zmin,zmax; +}; + +struct GLMRect // follows GL convention - if coming from the D3D rect you will need to fiddle the Y's +{ + int xmin; // left + int ymin; // bottom + int xmax; // right + int ymax; // top +}; + +// macros + +//#define GLMassert(x) assert(x) + +// forward decls +class GLMgr; // singleton +class GLMContext; // GL context +class CGLMContextTester; // testing class +class CGLMTex; +class CGLMFBO; +class CGLMProgram; +class CGLMBuffer; + + +// utilities + +typedef enum +{ + // D3D codes + eD3D_DEVTYPE, + eD3D_FORMAT, + eD3D_RTYPE, + eD3D_USAGE, + eD3D_RSTATE, // render state + eD3D_SIO, // D3D shader bytecode + eD3D_VTXDECLUSAGE, + + // CGL codes + eCGL_RENDID, + + // OpenGL error codes + eGL_ERROR, + + // OpenGL enums + eGL_ENUM, + eGL_RENDERER + +} GLMThing_t; + +// these will look at the string to guess its flavor: <, >, ---, -M-, -S- +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const +#else + DLL_IMPORT const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const +#endif + +const char* GLMDecodeMask( GLMThing_t type, unsigned long value ); // decode a bitmask + +FORCEINLINE void GLMStop( void ) { DXABSTRACT_BREAK_ON_ERROR(); } + +void GLMEnableTrace( bool on ); + +//=============================================================================== +// output functions + +// expose these in release now +// Mimic PIX events so we can decorate debug spew +DLL_EXPORT void GLMBeginPIXEvent( const char *str ); +DLL_EXPORT void GLMEndPIXEvent( void ); + +class CScopedGLMPIXEvent +{ + CScopedGLMPIXEvent( const CScopedGLMPIXEvent & ); + CScopedGLMPIXEvent& operator= ( const CScopedGLMPIXEvent & ); +public: + inline CScopedGLMPIXEvent( const char *pName ) { GLMBeginPIXEvent( pName ); } + inline ~CScopedGLMPIXEvent() { GLMEndPIXEvent( ); } +}; + +#if GLMDEBUG + + +//=============================================================================== +// classes + +// helper class making function tracking easier to wire up + +class GLMFuncLogger +{ + public: + + // simple function log + GLMFuncLogger( const char *funcName ) + { + m_funcName = funcName; + m_earlyOut = false; + + GLMPrintf( ">%s", m_funcName ); + }; + + // more advanced version lets you pass args (i.e. called parameters or anything else of interest) + // no macro for this one, since no easy way to pass through the args as well as the funcname + GLMFuncLogger( const char *funcName, char *fmt, ... ) + { + m_funcName = funcName; + m_earlyOut = false; + + // this acts like GLMPrintf here + // all the indent policy is down in GLMPrintfVA + // which means we need to inject a ">" at the front of the format string to make this work... sigh. + + char modifiedFmt[2000]; + modifiedFmt[0] = '>'; + strcpy( modifiedFmt+1, fmt ); + + va_list vargs; + va_start(vargs, fmt); + GLMPrintfVA( modifiedFmt, vargs ); + va_end( vargs ); + } + + ~GLMFuncLogger( ) + { + if (m_earlyOut) + { + GLMPrintf( "<%s (early out)", m_funcName ); + } + else + { + GLMPrintf( "<%s", m_funcName ); + } + }; + + void EarlyOut( void ) + { + m_earlyOut = true; + }; + + const char *m_funcName; // set at construction time + bool m_earlyOut; +}; + +// handy macro to go with the function tracking class +#define GLM_FUNC GLMFuncLogger _logger_ ( __FUNCTION__ ) +#else +#define GLM_FUNC tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s", __FUNCTION__ ) +#endif + + +// class to keep an in-memory mirror of a file which may be getting edited during run +class CGLMFileMirror +{ +public: + CGLMFileMirror( char *fullpath ); // just associates mirror with file. if file exists it will be read. + //if non existent it will be created with size zero + ~CGLMFileMirror( ); + + bool HasData( void ); // see if data avail + void GetData( char **dataPtr, uint *dataSizePtr ); // read it out + void SetData( char *data, uint dataSize ); // put data in (and write it to disk) + bool PollForChanges( void ); // check disk copy. If different, read it back in and return true. + + void UpdateStatInfo( void ); // make sure stat info is current for our file + void ReadFile( void ); + void WriteFile( void ); + + void OpenInEditor( bool foreground=false ); // pass TRUE if you would like the editor to pop to foreground + + /// how about a "wait for change" method.. + + char *m_path; // fullpath to file + bool m_exists; + struct stat m_stat; // stat results for the file (last time checked) + + char *m_data; // content of file + uint m_size; // length of content + +}; + +// class based on the file mirror, that makes it easy to edit them outside the app. + +// it receives an initial block of text from the engine, and hashes it. ("orig") +// it munges it by duplicating all the text after the "!!" line, and appending it in commented form. ("munged") +// a mirror file is activated, using a filename based on the hash from the orig text. +// if there is already content on disk matching that filename, use that content *unless* the 'blitz' parameter is set. +// (i.e. engine is instructing this subsystem to wipe out any old/modified variants of the text) + + +class CGLMEditableTextItem +{ +public: + CGLMEditableTextItem( char *text, uint size, bool forceOverwrite, char *prefix, char *suffix = NULL ); // create a text blob from text source, optional filename suffix + ~CGLMEditableTextItem( ); + + bool HasData( void ); + bool PollForChanges( void ); // return true if stale i.e. you need to get a new edition + void GetCurrentText( char **textOut, uint *sizeOut ); // query for read access to the active blob (could be the original, could be external edited copy) + void OpenInEditor( bool foreground=false ); // call user attention to this text + + // internal methods + void GenHashOfOrigText( void ); + void GenBaseNameAndFullPath( char *prefix, char *suffix ); + void GenMungedText( bool fromMirror ); + + // members + // orig + uint m_origSize; + char *m_origText; // what was submitted + unsigned char m_origDigest[MD5_DIGEST_LENGTH]; // digest of what was submitted + + // munged + uint m_mungedSize; + char *m_mungedText; // re-processed edition, initial content submission to the file mirror + + // mirror + char *m_mirrorBaseName; // generated from the hash of the orig text, plus the label / prefix + char *m_mirrorFullPath; // base name + CGLMFileMirror *m_mirror; // file mirror itself. holds "official" copy for GetCurrentText to return. +}; + + +// debug font +extern unsigned char g_glmDebugFontMap[16384]; + +// class for cracking multi-part text blobs +// sections are demarcated by beginning-of-line markers submitted in a table by the caller + +struct GLMTextSection +{ + int m_markerIndex; // based on table of markers passed in to constructor + uint m_textOffset; // where is the text - offset + int m_textLength; // how big is the section +}; + +class CGLMTextSectioner +{ +public: + CGLMTextSectioner( char *text, int textSize, const char **markers ); // constructor finds all the sections + ~CGLMTextSectioner( ); + + int Count( void ); // how many sections found + void GetSection( int index, uint *offsetOut, uint *lengthOut, int *markerIndexOut ); + // find section, size, what marker + // note that more than one section can be marked similarly. + // so policy isn't made here, you walk the sections and decide what to do if there are dupes. + + //members + + //section table + CUtlVector< GLMTextSection > m_sectionTable; +}; + +void GLMGPUTimestampManagerInit(); +void GLMGPUTimestampManagerDeinit(); +void GLMGPUTimestampManagerTick(); + +#endif // GLMBASICS_H diff --git a/sp/src/public/togl/linuxwin/glmgrext.h b/sp/src/public/togl/linuxwin/glmgrext.h new file mode 100644 index 00000000..810d4055 --- /dev/null +++ b/sp/src/public/togl/linuxwin/glmgrext.h @@ -0,0 +1,93 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgrext.h +// helper file for extension testing and runtime importing of entry points +// +//=============================================================================== + +#pragma once + +#ifdef OSX +#include +#include +#elif defined(DX_TO_GL_ABSTRACTION) +#include +#include +#else +#error +#endif + +#ifndef GL_EXT_framebuffer_sRGB + #define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 + #define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif + +#ifndef ARB_texture_rg + #define GL_COMPRESSED_RED 0x8225 + #define GL_COMPRESSED_RG 0x8226 + #define GL_RG 0x8227 + #define GL_RG_INTEGER 0x8228 + #define GL_R8 0x8229 + #define GL_R16 0x822A + #define GL_RG8 0x822B + #define GL_RG16 0x822C + #define GL_R16F 0x822D + #define GL_R32F 0x822E + #define GL_RG16F 0x822F + #define GL_RG32F 0x8230 + #define GL_R8I 0x8231 + #define GL_R8UI 0x8232 + #define GL_R16I 0x8233 + #define GL_R16UI 0x8234 + #define GL_R32I 0x8235 + #define GL_R32UI 0x8236 + #define GL_RG8I 0x8237 + #define GL_RG8UI 0x8238 + #define GL_RG16I 0x8239 + #define GL_RG16UI 0x823A + #define GL_RG32I 0x823B + #define GL_RG32UI 0x823C +#endif + +#ifndef GL_EXT_bindable_uniform + #define GL_UNIFORM_BUFFER_EXT 0x8DEE +#endif + +// unpublished extension enums (thus the "X") + +// from EXT_framebuffer_multisample_blit_scaled.. +#define XGL_SCALED_RESOLVE_FASTEST_EXT 0x90BA +#define XGL_SCALED_RESOLVE_NICEST_EXT 0x90BB + +#ifndef GL_TEXTURE_MINIMIZE_STORAGE_APPLE +#define GL_TEXTURE_MINIMIZE_STORAGE_APPLE 0x85B6 +#endif + +#ifndef GL_ALL_COMPLETED_NV +#define GL_ALL_COMPLETED_NV 0x84F2 +#endif + +#ifndef GL_MAP_READ_BIT +#define GL_MAP_READ_BIT 0x0001 +#endif + +#ifndef GL_MAP_WRITE_BIT +#define GL_MAP_WRITE_BIT 0x0002 +#endif + +#ifndef GL_MAP_INVALIDATE_RANGE_BIT +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#endif + +#ifndef GL_MAP_INVALIDATE_BUFFER_BIT +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#endif + +#ifndef GL_MAP_FLUSH_EXPLICIT_BIT +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#endif + +#ifndef GL_MAP_UNSYNCHRONIZED_BIT +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#endif + diff --git a/sp/src/public/togl/osx/cglmbuffer.h b/sp/src/public/togl/osx/cglmbuffer.h new file mode 100644 index 00000000..0e40f474 --- /dev/null +++ b/sp/src/public/togl/osx/cglmbuffer.h @@ -0,0 +1,99 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmprogram.h +// GLMgr buffers (index / vertex) +// ... maybe add PBO later as well +//=============================================================================== + +#ifndef CGLMBUFFER_H +#define CGLMBUFFER_H + +#pragma once + +// ext links + +// http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt + +//=============================================================================== + +// tokens not in the SDK headers + +//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT +// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +//#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; + +enum EGLMBufferType +{ + kGLMVertexBuffer, + kGLMIndexBuffer, + kGLMUniformBuffer, // for bindable uniform + kGLMPixelBuffer, // for PBO + + kGLMNumBufferTypes +}; + + // pass this in "options" to constructor to make a dynamic buffer +#define GLMBufferOptionDynamic 0x00000001 + +struct GLMBuffLockParams +{ + uint m_offset; + uint m_size; + bool m_nonblocking; + bool m_discard; +}; + +class CGLMBuffer +{ + +public: + void Lock( GLMBuffLockParams *params, char **addressOut ); + void Unlock( void ); + +//protected: + friend class GLMContext; // only GLMContext can make CGLMBuffer objects + friend class GLMTester; + friend class IDirect3D9; + friend class IDirect3DDevice9; + + CGLMBuffer ( GLMContext *ctx, EGLMBufferType type, uint size, uint options ); + ~CGLMBuffer ( ); + + void SetModes ( bool asyncMap, bool explicitFlush, bool force = false ); + void FlushRange ( uint offset, uint size ); + + GLMContext *m_ctx; // link back to parent context + EGLMBufferType m_type; + uint m_size; + GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB + GLuint m_name; // name of this program in the context + uint m_revision; // bump anytime the size changes or buffer is orphaned + bool m_enableAsyncMap; // mirror of the buffer state + bool m_enableExplicitFlush; // mirror of the buffer state + + bool m_bound; // true if bound to context + bool m_mapped; // is it currently mapped + uint m_dirtyMinOffset; // when equal, range is empty + uint m_dirtyMaxOffset; + + float *m_lastMappedAddress; + + // --------------------- pseudo-VBO support below here (explicitly for dynamic index buffers) + bool m_pseudo; // true if the m_name is 0, and the backing is plain RAM + + // in pseudo mode, there is just one RAM buffer that acts as the backing. + // expectation is that this mode would only be used for dynamic indices. + // since indices have to be consumed (copied to command stream) prior to return from a drawing call, + // there's no need to do any fencing or multibuffering. orphaning in particular becomes a no-op. + + char *m_pseudoBuf; // storage for pseudo buffer +}; + + +#endif \ No newline at end of file diff --git a/sp/src/public/togl/osx/cglmfbo.h b/sp/src/public/togl/osx/cglmfbo.h new file mode 100644 index 00000000..ab889af2 --- /dev/null +++ b/sp/src/public/togl/osx/cglmfbo.h @@ -0,0 +1,91 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmfbo.h +// GLMgr FBO's (render targets) +// +//=============================================================================== + +#ifndef CGLMFBO_H +#define CGLMFBO_H + +#pragma once + +#include "togl/rendermechanism.h" + +// good FBO references / recaps +// http://www.songho.ca/opengl/gl_fbo.html +// http://www.gamedev.net/reference/articles/article2331.asp + +// ext links + +// http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt +// http://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt + +//=============================================================================== + +// tokens not in the SDK headers + +#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT + #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; + +// implicitly 16 maximum color attachments possible +enum EGLMFBOAttachment { + kAttColor0, kAttColor1, kAttColor2, kAttColor3, + kAttColor4, kAttColor5, kAttColor6, kAttColor7, + kAttColor8, kAttColor9, kAttColor10, kAttColor11, + kAttColor12, kAttColor13, kAttColor14, kAttColor15, + kAttDepth, kAttStencil, kAttDepthStencil, + kAttCount +}; + +struct GLMFBOTexAttachParams +{ + CGLMTex *m_tex; + int m_face; // keep zero if not cube map + int m_mip; // keep zero if notmip mapped + int m_zslice; // keep zero if not a 3D tex +}; + +class CGLMFBO +{ + +public: + +protected: + friend class GLMContext; // only GLMContext can make CGLMFBO objects + friend class GLMTester; + friend class CGLMTex; + + friend class IDirect3D9; + friend class IDirect3DDevice9; + + CGLMFBO( GLMContext *ctx ); + ~CGLMFBO( ); + + void TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); + void TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); + // you can also pass GL_READ_FRAMEBUFFER_EXT or GL_DRAW_FRAMEBUFFER_EXT to selectively bind the receiving FBO to one or the other. + + void TexScrub( CGLMTex *tex ); + // search and destroy any attachment for the named texture + + bool IsReady( void ); // aka FBO completeness check - ready to draw + + GLMContext *m_ctx; // link back to parent context + + GLuint m_name; // name of this FBO in the context + + GLMFBOTexAttachParams m_attach[ kAttCount ]; // indexed by EGLMFBOAttachment + + int m_sizeX,m_sizeY; +}; + + +#endif diff --git a/sp/src/public/togl/osx/cglmprogram.h b/sp/src/public/togl/osx/cglmprogram.h new file mode 100644 index 00000000..8d702c42 --- /dev/null +++ b/sp/src/public/togl/osx/cglmprogram.h @@ -0,0 +1,291 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// cglmprogram.h +// GLMgr programs (ARBVP/ARBfp) +// +//=============================================================================== + +#ifndef CGLMPROGRAM_H +#define CGLMPROGRAM_H + +#include + +#pragma once + +// good ARB program references +// http://petewarden.com/notes/archives/2005/05/fragment_progra_2.html +// http://petewarden.com/notes/archives/2005/06/fragment_progra_3.html + +// ext links + +// http://www.opengl.org/registry/specs/ARB/vertex_program.txt +// http://www.opengl.org/registry/specs/ARB/fragment_program.txt +// http://www.opengl.org/registry/specs/EXT/gpu_program_parameters.txt + + +//=============================================================================== + +// tokens not in the SDK headers + +//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT +// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 +//#endif + +//=============================================================================== + +// forward declarations + +class GLMContext; +class CGLMShaderPair; +class CGLMShaderPairCache; + +// CGLMProgram can contain two flavors of the same program, one in assembler, one in GLSL. +// these flavors are pretty different in terms of the API's that are used to activate them - +// for example, assembler programs can just get bound to the context, whereas GLSL programs +// have to be linked. To some extent we try to hide that detail inside GLM. + +// for now, make CGLMProgram a container, it does not set policy or hold a preference as to which +// flavor you want to use. GLMContext has to handle that. + +enum EGLMProgramType +{ + kGLMVertexProgram, + kGLMFragmentProgram, + + kGLMNumProgramTypes +}; + +enum EGLMProgramLang +{ + kGLMARB, + kGLMGLSL, + + kGLMNumProgramLangs +}; + +struct GLMShaderDesc +{ + union + { + GLuint arb; // ARB program object name + GLhandleARB glsl; // GLSL shader object handle (void*) + } m_object; + + // these can change if shader text is edited + bool m_textPresent; // is this flavor(lang) of text present in the buffer? + int m_textOffset; // where is it + int m_textLength; // how big + + bool m_compiled; // has this text been through a compile attempt + bool m_valid; // and if so, was the compile successful + + int m_slowMark; // has it been flagged during a non native draw batch before. increment every time it's slow. + + int m_highWater; // vount of vec4's in the major uniform array ("vc" on vs, "pc" on ps) + // written by dxabstract.... gross! +}; + +GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target +GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target + +class CGLMProgram +{ +public: + friend class CGLMShaderPairCache; + friend class CGLMShaderPair; + friend class GLMContext; // only GLMContext can make CGLMProgram objects + friend class GLMTester; + friend class IDirect3D9; + friend class IDirect3DDevice9; + + //=============================== + + // constructor is very light, it just makes one empty program object per flavor. + CGLMProgram( GLMContext *ctx, EGLMProgramType type ); + ~CGLMProgram( ); + + void SetProgramText ( char *text ); // import text to GLM object - invalidate any prev compiled program + + bool CompileActiveSources ( void ); // compile only the flavors that were provided. + bool Compile ( EGLMProgramLang lang ); + bool CheckValidity ( EGLMProgramLang lang ); + + void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that + + void GetLabelIndexCombo ( char *labelOut, int labelOutMaxChars, int *indexOut, int *comboOut ); + void GetComboIndexNameString ( char *stringOut, int stringOutMaxChars ); // mmmmmmmm-nnnnnnnn-filename + +#if GLMDEBUG + bool PollForChanges( void ); // check mirror for changes. + void ReloadStringFromEditable( void ); // populate m_string from editable item (react to change) + bool SyncWithEditable( void ); +#endif + + //=============================== + + // common stuff + + GLMContext *m_ctx; // link back to parent context + + EGLMProgramType m_type; // vertex or pixel + + uint m_serial; // serial number for hashing + + char *m_text; // copy of text passed into constructor. Can change if editable shaders is enabled. + // note - it can contain multiple flavors, so use CGLMTextSectioner to scan it and locate them +#if GLMDEBUG + CGLMEditableTextItem *m_editable; // editable text item for debugging +#endif + + GLMShaderDesc m_descs[ kGLMNumProgramLangs ]; + + uint m_samplerMask; // (1< m_layoutMap; +}; + +//=============================================================================== + +// a sampler specifies desired state for drawing on a given sampler index +// this is the combination of a texture choice and a set of sampler parameters +// see http://msdn.microsoft.com/en-us/library/bb172602(VS.85).aspx + + +struct GLMTexSamplingParams +{ + GLenum m_addressModes[3]; // S, T, R + GLfloat m_borderColor[4]; // R,G,B,A + + GLenum m_magFilter; + GLenum m_minFilter; + + GLfloat m_mipmapBias; + GLint m_minMipLevel; + GLint m_maxMipLevel; + GLint m_maxAniso; + GLenum m_compareMode; // only used for depth and stencil type textures + bool m_srgb; // srgb texture read... +}; + +struct GLMTexLockParams +{ + // input params which identify the slice of interest + CGLMTex *m_tex; + int m_face; + int m_mip; + + // identifies the region of the slice + GLMRegion m_region; + + // tells GLM to force re-read of the texels back from GL + // i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale" + bool m_readback; +}; + +struct GLMTexLockDesc +{ + GLMTexLockParams m_req; // form of the lock request + + bool m_active; // set true at lock time. cleared at unlock time. + + int m_sliceIndex; // which slice in the layout + int m_sliceBaseOffset; // where is that in the texture data + int m_sliceRegionOffset; // offset to the start (lowest address corner) of the region requested +}; + +//=============================================================================== + +#define GLM_SAMPLER_COUNT 16 + +typedef CBitVec CTexBindMask; + +enum EGLMTexSliceFlag +{ + kSliceValid = 0x01, // slice has been teximage'd in whole at least once - set to 0 initially + kSliceStorageValid = 0x02, // if backing store is available, this slice's data is a valid copy - set to 0 initially + kSliceLocked = 0x04, // are one or more locks outstanding on this slice + kSliceFullyDirty = 0x08, // does the slice need to be fully downloaded at unlock time (disregard dirty rects) +}; + +class CGLMTex +{ + +public: + + void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut ); + void Unlock( GLMTexLockParams *params ); + +protected: + friend class GLMContext; // only GLMContext can make CGLMTex objects + friend class GLMTester; + friend class CGLMFBO; + + friend class IDirect3DDevice9; + friend class IDirect3DBaseTexture9; + friend class IDirect3DTexture9; + friend class IDirect3DSurface9; + friend class IDirect3DCubeTexture9; + friend class IDirect3DVolumeTexture9; + + CGLMTex( GLMContext *ctx, GLMTexLayout *layout, GLMTexSamplingParams *sampling, char *debugLabel = NULL ); + ~CGLMTex( ); + + int CalcSliceIndex( int face, int mip ); + void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut ); + + void ApplySamplingParams( GLMTexSamplingParams *params, bool noCheck=FALSE ); + + void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true ); + void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false ); + // last param lets us send NULL data ptr (only legal with uncompressed formats, beware) + // this helps out ResetSRGB. + + void ResetSRGB( bool srgb, bool noDataWrite ); + // re-specify texture format to match desired sRGB form + // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's + + GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout) + int m_minActiveMip;//index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. + int m_maxActiveMip;//index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. + + GLMTexSamplingParams m_sampling; // mirror of sampling params currently embodied in the texture + // (consult this at draw time, in order to know if changes need to be made) + + GLMContext *m_ctx; // link back to parent context + + GLuint m_texName; // name of this texture in the context + bool m_texClientStorage; // was CS selecetd for texture + bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet + + GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero) + bool m_rboDirty; // has RBO been drawn on - i.e. needs to be blitted back to texture if texture is going to be sampled from + + CTexBindMask m_bindPoints; // true for each place in the parent ctx where currently + // bound (indexed via EGLMTexCtxBindingIndex) + + int m_rtAttachCount; // how many RT's have this texture attached somewhere + + char *m_backing; // backing storage if available + + int m_lockCount; // lock reqs are stored in the GLMContext for tracking + + CUtlVector m_sliceFlags; + + char *m_debugLabel; // strdup() of debugLabel passed in, or NULL +}; + + +#endif diff --git a/sp/src/public/togl/osx/dxabstract.h b/sp/src/public/togl/osx/dxabstract.h new file mode 100644 index 00000000..682676c7 --- /dev/null +++ b/sp/src/public/togl/osx/dxabstract.h @@ -0,0 +1,804 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// +// +//================================================================================================== + +#ifndef DXABSTRACT_H +#define DXABSTRACT_H +#ifdef _WIN32 +#pragma once +#endif + +#include "togl/rendermechanism.h" + +#include "materialsystem/ishader.h" + +// Uncomment this on Windows if you want to compile the Windows GL version. +// #undef USE_ACTUAL_DX + +#ifdef USE_ACTUAL_DX + +#ifndef WIN32 +#error sorry man +#endif +#ifdef _X360 +#include "d3d9.h" +#include "d3dx9.h" +#else +#include +#include "../../dx9sdk/include/d3d9.h" +#include "../../dx9sdk/include/d3dx9.h" +#endif +typedef HWND VD3DHWND; + +#else + +#ifdef WIN32 +#error Gl on win32? +#endif + +#include "tier0/platform.h" + +#ifndef DX_TO_GL_ABSTRACTION +#define DX_TO_GL_ABSTRACTION +#endif + +#include "bitmap/imageformat.h" +#include "togl/rendermechanism.h" + +#ifdef OSX +extern "C" void Debugger(void); +#endif + +// turn this on to get refcount logging from IUnknown +#define IUNKNOWN_ALLOC_SPEW 0 +#define IUNKNOWN_ALLOC_SPEW_MARK_ALL 0 + + +// ------------------------------------------------------------------------------------------------------------------------------ // +// DEFINES +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef void* VD3DHWND; +typedef void* VD3DHANDLE; + + +TOGL_INTERFACE void toglGetClientRect( VD3DHWND hWnd, RECT *destRect ); + +struct TOGL_CLASS IUnknown +{ + int m_refcount[2]; + bool m_mark; + + IUnknown( void ) + { + m_refcount[0] = 1; + m_refcount[1] = 0; + m_mark = (IUNKNOWN_ALLOC_SPEW_MARK_ALL != 0); // either all are marked, or only the ones that have SetMark(true) called on them + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUnew (%08x) refc -> (%d,%d) ",this,m_refcount[0],m_refcount[1])); + } + #endif + }; + + virtual ~IUnknown( void ) + { + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUdel (%08x) ",this )); + } + #endif + }; + + void AddRef( int which=0, char *comment = NULL ) + { + Assert( which >= 0 ); + Assert( which < 2 ); + m_refcount[which]++; + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IUAddRef (%08x,%d) refc -> (%d,%d) [%s]",this,which,m_refcount[0],m_refcount[1],comment?comment:"...")) ; + if (!comment) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + } + #endif + }; + + ULONG __stdcall Release( int which=0, char *comment = NULL ) + { + Assert( which >= 0 ); + Assert( which < 2 ); + + //int oldrefcs[2] = { m_refcount[0], m_refcount[1] }; + bool deleting = false; + + m_refcount[which]--; + if ( (!m_refcount[0]) && (!m_refcount[1]) ) + { + deleting = true; + } + + #if IUNKNOWN_ALLOC_SPEW + if (m_mark) + { + GLMPRINTF(("-A- IURelease (%08x,%d) refc -> (%d,%d) [%s] %s",this,which,m_refcount[0],m_refcount[1],comment?comment:"...",deleting?"->DELETING":"")); + if (!comment) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + } + #endif + + if (deleting) + { + if (m_mark) + { + GLMPRINTF(("")) ; // place to hang a breakpoint + } + delete this; + return 0; + } + else + { + return m_refcount[0]; + } + }; + + void SetMark( bool markValue, char *comment=NULL ) + { + #if IUNKNOWN_ALLOC_SPEW + if (!m_mark && markValue) // leading edge detect + { + // print the same thing that the constructor would have printed if it had been marked from the beginning + // i.e. it's anticipated that callers asking for marking will do so right at create time + GLMPRINTF(("-A- IUSetMark (%08x) refc -> (%d,%d) (%s) ",this,m_refcount[0],m_refcount[1],comment?comment:"...")); + } + #endif + + m_mark = markValue; + } +}; + + +// ------------------------------------------------------------------------------------------------------------------------------ // +// INTERFACES +// ------------------------------------------------------------------------------------------------------------------------------ // + +struct TOGL_CLASS IDirect3DResource9 : public IUnknown +{ + IDirect3DDevice9 *m_device; // parent device + D3DRESOURCETYPE m_restype; + + DWORD SetPriority(DWORD PriorityNew); +}; + +struct TOGL_CLASS IDirect3DBaseTexture9 : public IDirect3DResource9 // "A Texture.." +{ + D3DSURFACE_DESC m_descZero; // desc of top level. + CGLMTex *m_tex; // a CGLMTex can represent all forms of tex + int m_srgbFlipCount; + + virtual ~IDirect3DBaseTexture9(); + D3DRESOURCETYPE GetType(); + DWORD GetLevelCount(); + HRESULT GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DTexture9 : public IDirect3DBaseTexture9 // "Texture 2D" +{ + IDirect3DSurface9 *m_surfZero; // surf of top level. + + virtual ~IDirect3DTexture9(); + + HRESULT LockRect(UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); + HRESULT UnlockRect(UINT Level); + HRESULT GetSurfaceLevel(UINT Level,IDirect3DSurface9** ppSurfaceLevel); +}; + +struct TOGL_CLASS IDirect3DCubeTexture9 : public IDirect3DBaseTexture9 // "Texture Cube Map" +{ + IDirect3DSurface9 *m_surfZero[6]; // surfs of top level. + + virtual ~IDirect3DCubeTexture9(); + + HRESULT GetCubeMapSurface(D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface); + HRESULT GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DVolumeTexture9 : public IDirect3DBaseTexture9 // "Texture 3D" +{ + IDirect3DSurface9 *m_surfZero; // surf of top level. + D3DVOLUME_DESC m_volDescZero; // volume desc top level + + virtual ~IDirect3DVolumeTexture9(); + + HRESULT LockBox(UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags); + HRESULT UnlockBox(UINT Level); + HRESULT GetLevelDesc( UINT level, D3DVOLUME_DESC *pDesc ); +}; + + +// for the moment, a "D3D surface" is modeled as a GLM tex, a face, and a mip. +// no Create method, these are filled in by the various create surface methods. + +struct TOGL_CLASS IDirect3DSurface9 : public IDirect3DResource9 +{ + virtual ~IDirect3DSurface9(); + + HRESULT LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); + HRESULT UnlockRect(); + HRESULT GetDesc(D3DSURFACE_DESC *pDesc); + + D3DSURFACE_DESC m_desc; + CGLMTex *m_tex; + int m_face; + int m_mip; +}; + + + +struct TOGL_CLASS IDirect3D9 : public IUnknown +{ +public: + virtual ~IDirect3D9(); + + UINT GetAdapterCount(); //cheese: returns 1 + + HRESULT GetDeviceCaps (UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps); + HRESULT GetAdapterIdentifier (UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier); + HRESULT CheckDeviceFormat (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat); + UINT GetAdapterModeCount (UINT Adapter,D3DFORMAT Format); + HRESULT EnumAdapterModes (UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode); + HRESULT CheckDeviceType (UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed); + HRESULT GetAdapterDisplayMode (UINT Adapter,D3DDISPLAYMODE* pMode); + HRESULT CheckDepthStencilMatch (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat); + HRESULT CheckDeviceMultiSampleType (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels); + + HRESULT CreateDevice (UINT Adapter,D3DDEVTYPE DeviceType,VD3DHWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface); +}; + +struct TOGL_CLASS IDirect3DSwapChain9 : public IUnknown +{ +}; + + + + // typedef enum D3DDECLUSAGE + // { + // D3DDECLUSAGE_POSITION = 0, + // D3DDECLUSAGE_BLENDWEIGHT = 1, + // D3DDECLUSAGE_BLENDINDICES = 2, + // D3DDECLUSAGE_NORMAL = 3, + // D3DDECLUSAGE_PSIZE = 4, + // D3DDECLUSAGE_TEXCOORD = 5, + // D3DDECLUSAGE_TANGENT = 6, + // D3DDECLUSAGE_BINORMAL = 7, + // D3DDECLUSAGE_TESSFACTOR = 8, + // D3DDECLUSAGE_POSITIONT = 9, + // D3DDECLUSAGE_COLOR = 10, + // D3DDECLUSAGE_FOG = 11, + // D3DDECLUSAGE_DEPTH = 12, + // D3DDECLUSAGE_SAMPLE = 13, + // } D3DDECLUSAGE, *LPD3DDECLUSAGE; + // Constants + // + // D3DDECLUSAGE_POSITION + // Position data ranging from (-1,-1) to (1,1). Use D3DDECLUSAGE_POSITION with + // a usage index of 0 to specify untransformed position for fixed function + // vertex processing and the n-patch tessellator. Use D3DDECLUSAGE_POSITION + // with a usage index of 1 to specify untransformed position in the fixed + // function vertex shader for vertex tweening. + // + // D3DDECLUSAGE_BLENDWEIGHT + // Blending weight data. Use D3DDECLUSAGE_BLENDWEIGHT with a usage index of 0 + // to specify the blend weights used in indexed and nonindexed vertex + // blending. + // + // D3DDECLUSAGE_BLENDINDICES + // Blending indices data. Use D3DDECLUSAGE_BLENDINDICES with a usage index of + // 0 to specify matrix indices for indexed paletted skinning. + // + // D3DDECLUSAGE_NORMAL + // Vertex normal data. Use D3DDECLUSAGE_NORMAL with a usage index of 0 to + // specify vertex normals for fixed function vertex processing and the n-patch + // tessellator. Use D3DDECLUSAGE_NORMAL with a usage index of 1 to specify + // vertex normals for fixed function vertex processing for vertex tweening. + // + // D3DDECLUSAGE_PSIZE + // Point size data. Use D3DDECLUSAGE_PSIZE with a usage index of 0 to specify + // the point-size attribute used by the setup engine of the rasterizer to + // expand a point into a quad for the point-sprite functionality. + // + // D3DDECLUSAGE_TEXCOORD + // Texture coordinate data. Use D3DDECLUSAGE_TEXCOORD, n to specify texture + // coordinates in fixed function vertex processing and in pixel shaders prior + // to ps_3_0. These can be used to pass user defined data. + // + // D3DDECLUSAGE_TANGENT + // Vertex tangent data. + // + // D3DDECLUSAGE_BINORMAL + // Vertex binormal data. + // + // D3DDECLUSAGE_TESSFACTOR + // Single positive floating point value. Use D3DDECLUSAGE_TESSFACTOR with a + // usage index of 0 to specify a tessellation factor used in the tessellation + // unit to control the rate of tessellation. For more information about the + // data type, see D3DDECLTYPE_FLOAT1. + // + // D3DDECLUSAGE_POSITIONT + // Vertex data contains transformed position data ranging from (0,0) to + // (viewport width, viewport height). Use D3DDECLUSAGE_POSITIONT with a usage + // index of 0 to specify transformed position. When a declaration containing + // this is set, the pipeline does not perform vertex processing. + // + // D3DDECLUSAGE_COLOR + // Vertex data contains diffuse or specular color. Use D3DDECLUSAGE_COLOR with + // a usage index of 0 to specify the diffuse color in the fixed function + // vertex shader and pixel shaders prior to ps_3_0. Use D3DDECLUSAGE_COLOR + // with a usage index of 1 to specify the specular color in the fixed function + // vertex shader and pixel shaders prior to ps_3_0. + // + // D3DDECLUSAGE_FOG + // Vertex data contains fog data. Use D3DDECLUSAGE_FOG with a usage index of 0 + // to specify a fog blend value used after pixel shading finishes. This + // applies to pixel shaders prior to version ps_3_0. + // + // D3DDECLUSAGE_DEPTH + // Vertex data contains depth data. + // + // D3DDECLUSAGE_SAMPLE + // Vertex data contains sampler data. Use D3DDECLUSAGE_SAMPLE with a usage + // index of 0 to specify the displacement value to look up. It can be used + // only with D3DDECLUSAGE_LOOKUPPRESAMPLED or D3DDECLUSAGE_LOOKUP. + + //note the form of the list terminator.. + + // #define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0} + // typedef struct _D3DVERTEXELEMENT9 + // { + // WORD Stream; // Stream index + // WORD Offset; // Offset in the stream in bytes + // BYTE Type; // Data type + // BYTE Method; // Processing method + // BYTE Usage; // Semantics + // BYTE UsageIndex; // Semantic index + // } D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; + +#define MAX_D3DVERTEXELEMENTS 16 + +struct TOGL_CLASS IDirect3DVertexDeclaration9 : public IUnknown +{ +//public: + uint m_elemCount; + D3DVERTEXELEMENT9_GL m_elements[ MAX_D3DVERTEXELEMENTS ]; + + virtual ~IDirect3DVertexDeclaration9(); +}; + +struct TOGL_CLASS IDirect3DQuery9 : public IDirect3DResource9 //was IUnknown +{ +//public: + D3DQUERYTYPE m_type; // D3DQUERYTYPE_OCCLUSION or D3DQUERYTYPE_EVENT + GLMContext *m_ctx; + CGLMQuery *m_query; + + virtual ~IDirect3DQuery9(); + + HRESULT Issue(DWORD dwIssueFlags); + HRESULT GetData(void* pData,DWORD dwSize,DWORD dwGetDataFlags); +}; + +struct TOGL_CLASS IDirect3DVertexBuffer9 : public IDirect3DResource9 //was IUnknown +{ +//public: + GLMContext *m_ctx; + CGLMBuffer *m_vtxBuffer; + D3DVERTEXBUFFER_DESC m_vtxDesc; // to satisfy GetDesc + + virtual ~IDirect3DVertexBuffer9(); + HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); + HRESULT Unlock(); + HRESULT UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); + +}; + +struct TOGL_CLASS IDirect3DIndexBuffer9 : public IDirect3DResource9 //was IUnknown +{ +//public: + GLMContext *m_ctx; + CGLMBuffer *m_idxBuffer; + D3DINDEXBUFFER_DESC m_idxDesc; // to satisfy GetDesc + + virtual ~IDirect3DIndexBuffer9(); + + HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); + HRESULT Unlock(); + HRESULT UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); + HRESULT GetDesc(D3DINDEXBUFFER_DESC *pDesc); +}; + +struct TOGL_CLASS IDirect3DPixelShader9 : public IDirect3DResource9 //was IUnknown +{ +//public: + CGLMProgram *m_pixProgram; + uint m_pixHighWater; // count of active constant slots referenced by shader. + uint m_pixSamplerMask; // (1< m_stack; + int m_stackTop; // top of stack is at the highest index, this is that index. push increases, pop decreases. + + HRESULT Create( void ); + + D3DXMATRIX* GetTop(); + void Push(); + void Pop(); + void LoadIdentity(); + void LoadMatrix( const D3DXMATRIX *pMat ); + void MultMatrix( const D3DXMATRIX *pMat ); + void MultMatrixLocal( const D3DXMATRIX *pMat ); + HRESULT ScaleLocal(FLOAT x, FLOAT y, FLOAT z); + + // Left multiply the current matrix with the computed rotation + // matrix, counterclockwise about the given axis with the given angle. + // (rotation is about the local origin of the object) + HRESULT RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle); + + // Left multiply the current matrix with the computed translation + // matrix. (transformation is about the local origin of the object) + HRESULT TranslateLocal(FLOAT x, FLOAT y, FLOAT z); +}; +typedef ID3DXMatrixStack* LPD3DXMATRIXSTACK; + +struct TOGL_CLASS IDirect3DDevice9 : public IUnknown +{ +public: + // members + + IDirect3DDevice9Params m_params; // mirror of the creation inputs + + // D3D flavor stuff + IDirect3DSurface9 *m_rtSurfaces[16]; // current color RT surfaces. [0] is initially == m_defaultColorSurface + IDirect3DSurface9 *m_dsSurface; // current DS RT surface. can be changed! + + IDirect3DSurface9 *m_defaultColorSurface; // default color surface. + IDirect3DSurface9 *m_defaultDepthStencilSurface; // queried by GetDepthStencilSurface. + + IDirect3DVertexDeclaration9 *m_vertDecl; // Set by SetVertexDeclaration... + D3DStreamDesc m_streams[ D3D_MAX_STREAMS ]; // Set by SetStreamSource.. + D3DIndexDesc m_indices; // Set by SetIndices.. + + IDirect3DVertexShader9 *m_vertexShader; // Set by SetVertexShader... + IDirect3DPixelShader9 *m_pixelShader; // Set by SetPixelShader... + + IDirect3DBaseTexture9 *m_textures[16]; // set by SetTexture... NULL if stage inactive + D3DSamplerDesc m_samplers[16]; // set by SetSamplerState.. + // GLM flavor stuff + GLMContext *m_ctx; + CGLMFBO *m_drawableFBO; // this FBO should have all the attachments set to match m_rtSurfaces and m_dsSurface. + + // GL state + struct + { + // render state buckets + GLAlphaTestEnable_t m_AlphaTestEnable; + GLAlphaTestFunc_t m_AlphaTestFunc; + + GLAlphaToCoverageEnable_t m_AlphaToCoverageEnable; + + GLDepthTestEnable_t m_DepthTestEnable; + GLDepthMask_t m_DepthMask; + GLDepthFunc_t m_DepthFunc; + + GLClipPlaneEnable_t m_ClipPlaneEnable[kGLMUserClipPlanes]; + GLClipPlaneEquation_t m_ClipPlaneEquation[kGLMUserClipPlanes]; + + GLColorMaskSingle_t m_ColorMaskSingle; + GLColorMaskMultiple_t m_ColorMaskMultiple; + + GLCullFaceEnable_t m_CullFaceEnable; + GLCullFrontFace_t m_CullFrontFace; + GLPolygonMode_t m_PolygonMode; + GLDepthBias_t m_DepthBias; + GLScissorEnable_t m_ScissorEnable; + GLScissorBox_t m_ScissorBox; + GLViewportBox_t m_ViewportBox; + GLViewportDepthRange_t m_ViewportDepthRange; + + GLBlendEnable_t m_BlendEnable; + GLBlendFactor_t m_BlendFactor; + GLBlendEquation_t m_BlendEquation; + GLBlendColor_t m_BlendColor; + GLBlendEnableSRGB_t m_BlendEnableSRGB; + + GLStencilTestEnable_t m_StencilTestEnable; + GLStencilFunc_t m_StencilFunc; + GLStencilOp_t m_StencilOp; + GLStencilWriteMask_t m_StencilWriteMask; + + GLClearColor_t m_ClearColor; + GLClearDepth_t m_ClearDepth; + GLClearStencil_t m_ClearStencil; + + bool m_FogEnable; // not really pushed to GL, just latched here + + // samplers + GLMTexSamplingParams m_samplers[ 16 ]; + + // bindings...hmmm... + + // dirty-bits + uint m_stateDirtyMask; // covers the state blocks, indexed by 1<m_nCurOwnerThreadId; } + +}; + +struct ID3DXInclude +{ + virtual HRESULT Open(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) = 0; + virtual HRESULT Close(LPCVOID pData) = 0; +}; +typedef ID3DXInclude* LPD3DXINCLUDE; + + +struct TOGL_CLASS ID3DXBuffer : public IUnknown +{ + void* GetBufferPointer(); + DWORD GetBufferSize(); +}; + +typedef ID3DXBuffer* LPD3DXBUFFER; + +class TOGL_CLASS ID3DXConstantTable : public IUnknown +{ +}; +typedef ID3DXConstantTable* LPD3DXCONSTANTTABLE; + + + +// ------------------------------------------------------------------------------------------------------------------------------ // +// D3DX stuff. +// ------------------------------------------------------------------------------------------------------------------------------ // + +TOGL_INTERFACE const char* D3DXGetPixelShaderProfile( IDirect3DDevice9 *pDevice ); + + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); +TOGL_INTERFACE D3DXVECTOR3* D3DXVec3TransformCoord( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack); +TOGL_INTERFACE void D3DXMatrixIdentity( D3DXMATRIX * ); + +TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Subtract( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + return pOut; +} + +TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Cross( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + D3DXVECTOR3 v; + + v.x = pV1->y * pV2->z - pV1->z * pV2->y; + v.y = pV1->z * pV2->x - pV1->x * pV2->z; + v.z = pV1->x * pV2->y - pV1->y * pV2->x; + + *pOut = v; + return pOut; +} + +TOGL_INTERFACE D3DXINLINE FLOAT D3DXVec3Dot( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; +} + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP); + +TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM ); + + +TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z ); + +// Build an ortho projection matrix. (right-handed) +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf ); + +// Transform a plane by a matrix. The vector (a,b,c) must be normal. +// M should be the inverse transpose of the transformation desired. +TOGL_INTERFACE D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM ); + +TOGL_INTERFACE IDirect3D9 *Direct3DCreate9(UINT SDKVersion); + +TOGL_INTERFACE void D3DPERF_SetOptions( DWORD dwOptions ); + +TOGL_INTERFACE HRESULT D3DXCompileShader( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + + +#endif // USE_ACTUAL_DX + +// fake D3D usage constant for SRGB tex creation +#define D3DUSAGE_TEXTURE_SRGB (0x80000000L) + +#endif // DXABSTRACT_H diff --git a/sp/src/public/togl/osx/dxabstract_types.h b/sp/src/public/togl/osx/dxabstract_types.h new file mode 100644 index 00000000..7df586cd --- /dev/null +++ b/sp/src/public/togl/osx/dxabstract_types.h @@ -0,0 +1,1710 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// dxabstract_types.h +// +//================================================================================================== +#ifndef DXABSTRACT_TYPES_H +#define DXABSTRACT_TYPES_H + +#pragma once + +#if GL_BATCH_PERF_ANALYSIS + class simple_bitmap; +#endif + +struct IUnknown; +struct IDirect3D9; +struct IDirect3DDevice9; +struct IDirect3DResource9; +struct IDirect3DBaseTexture9; +struct IDirect3DTexture9; +struct IDirect3DCubeTexture9; +struct IDirect3DVolumeTexture9; +struct IDirect3DSurface9; +struct IDirect3DVertexDeclaration9; +struct IDirect3DQuery9; +struct IDirect3DVertexBuffer9; +struct IDirect3DIndexBuffer9; +struct IDirect3DPixelShader9; +struct IDirect3DVertexShader9; +struct IDirect3DDevice9Params; + +class GLMContext; +struct GLMRect; +struct GLMShaderPairInfo; +class CGLMBuffer; +class CGLMQuery; +class CGLMTex; +class CGLMProgram; +class CGLMFBO; + +#ifdef TOGL_DLL_EXPORT + #define TOGL_INTERFACE DLL_EXPORT + #define TOGL_OVERLOAD DLL_GLOBAL_EXPORT + #define TOGL_CLASS DLL_CLASS_EXPORT + #define TOGL_GLOBAL DLL_GLOBAL_EXPORT +#else + #define TOGL_INTERFACE DLL_IMPORT + #define TOGL_OVERLOAD DLL_GLOBAL_IMPORT + #define TOGL_CLASS DLL_CLASS_IMPORT + #define TOGL_GLOBAL DLL_GLOBAL_IMPORT +#endif + +#define TOGLMETHODCALLTYPE __stdcall +//#define TOGLMETHODCALLTYPE + +#define DXABSTRACT_BREAK_ON_ERROR() DebuggerBreak() + +typedef void* VD3DHWND; +typedef void* VD3DHANDLE; + +#define MAKEFOURCC(ch0, ch1, ch2, ch3) ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) + +// +// +// Stuff that would be in windows.h +// +// +#if !defined(_WINNT_) + + typedef int INT; + typedef unsigned long ULONG; + typedef long LONG; + typedef float FLOAT; + typedef unsigned short WORD; + typedef long long LONGLONG; + typedef unsigned int UINT; + typedef long HRESULT; + typedef unsigned char BYTE; + #define CONST const + + #if defined(POSIX) + typedef size_t ULONG_PTR; + #else + typedef unsigned long ULONG_PTR; + #endif + + typedef ULONG_PTR SIZE_T; + + typedef const char* LPCSTR; + typedef char* LPSTR; +#ifndef OSX + typedef unsigned int DWORD; + typedef DWORD* LPDWORD; +#endif + + + #define ZeroMemory RtlZeroMemory + #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length)) + + typedef union _LARGE_INTEGER + { + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + LONGLONG QuadPart; + } LARGE_INTEGER; + + typedef struct _GUID + { + bool operator==( const struct _GUID &other ) const; + + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; + } GUID; + + typedef struct _RECT + { + int left; + int top; + int right; + int bottom; + } RECT; + + typedef struct tagPOINT + { + LONG x; + LONG y; + } POINT, *PPOINT, *LPPOINT; + + typedef struct _MEMORYSTATUS + { + DWORD dwLength; + SIZE_T dwTotalPhys; + } MEMORYSTATUS, *LPMEMORYSTATUS; + + typedef DWORD COLORREF; + #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) + + #define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + + +// Mac header files like to define these +#ifdef S_FALSE +#undef S_FALSE +#endif +#ifdef S_OK +#undef S_OK +#endif +#ifdef E_FAIL +#undef E_FAIL +#endif +#ifdef E_OUTOFMEMORY +#undef E_OUTOFMEMORY +#endif +#ifdef FAILED +#undef FAILED +#endif +#ifdef SUCCEEDED +#undef SUCCEEDED +#endif + + #define S_FALSE ((HRESULT)0x00000001L) + #define S_OK 0 + #define E_FAIL ((HRESULT)0x80004005L) + #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) + + #define FAILED(hr) ((HRESULT)(hr) < 0) + #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) + + struct RGNDATA + { + }; + + typedef const void* LPCVOID; +#endif + +//----------------------------------------------------------------------------- + +typedef enum _D3DFORMAT D3DFORMAT; + +#define D3DSI_OPCODE_MASK 0x0000FFFF +#define D3DSP_TEXTURETYPE_MASK 0x78000000 + +#define D3DUSAGE_AUTOGENMIPMAP 0x00000400L +#define D3DSP_DCL_USAGE_MASK 0x0000000f + +#define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000 +#define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16 + + +/* Flags to construct D3DRS_COLORWRITEENABLE */ +#define D3DCOLORWRITEENABLE_RED (1L<<0) +#define D3DCOLORWRITEENABLE_GREEN (1L<<1) +#define D3DCOLORWRITEENABLE_BLUE (1L<<2) +#define D3DCOLORWRITEENABLE_ALPHA (1L<<3) + +#define D3DSGR_NO_CALIBRATION 0x00000000L + +#define D3DXINLINE inline + +#define D3D_SDK_VERSION 32 + +#define _FACD3D 0x876 +#define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) + +#define D3DERR_NOTFOUND MAKE_D3DHRESULT(2150) +#define D3DERR_DEVICELOST MAKE_D3DHRESULT(2152) +#define D3DERR_NOTAVAILABLE MAKE_D3DHRESULT(2154) +#define D3DERR_DEVICENOTRESET MAKE_D3DHRESULT(2153) +#define D3DERR_INVALIDCALL MAKE_D3DHRESULT(2156) +#define D3DERR_DRIVERINTERNALERROR MAKE_D3DHRESULT(2087) +#define D3DERR_OUTOFVIDEOMEMORY MAKE_D3DHRESULT(380) +#define D3D_OK S_OK + +#define D3DPRESENT_RATE_DEFAULT 0x00000000 + +// +// DevCaps +// +// we need to see who in Source land is interested in these values, as dxabstract is currently reporting zero for the whole Caps word +#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ +#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ +#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ +#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */ +#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */ +#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */ +#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */ +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */ +#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */ +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ +#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */ +#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */ +#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */ + +// +// PrimitiveMiscCaps +// +#define D3DPMISCCAPS_MASKZ 0x00000002L +#define D3DPMISCCAPS_CULLNONE 0x00000010L +#define D3DPMISCCAPS_CULLCW 0x00000020L +#define D3DPMISCCAPS_CULLCCW 0x00000040L +#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L +#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */ +#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */ +#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */ +#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */ +#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */ +#define D3DPMISCCAPS_PERSTAGECONSTANT 0x00008000L /* Device supports per-stage constants */ +#define D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS 0x00040000L /* Device supports different bit depths for MRT */ +#define D3DPMISCCAPS_FOGVERTEXCLAMPED 0x00100000L /* Device clamps fog blend factor per vertex */ + +// Flags field for Issue +#define D3DISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled". +#define D3DISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginng of a query. + + +#define D3DPRESENT_INTERVAL_ONE 0x00000001L +#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L + +/* + * Options for clearing + */ +#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ +#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ +#define D3DCLEAR_STENCIL 0x00000004l /* Clear stencil planes */ + + +#define D3DENUM_WHQL_LEVEL 0x00000002L + + + + +#define D3DPTEXTURECAPS_NOPROJECTEDBUMPENV 0x00200000L /* Device does not support projected bump env lookup operation + in programmable and fixed function pixel shaders */ +#define D3DDEVCAPS2_STREAMOFFSET 0x00000001L /* Device supports offsets in streams. Must be set by DX9 drivers */ + +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ + +#define D3DCREATE_PUREDEVICE 0x00000010L +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0x00000020L +#define D3DCREATE_HARDWARE_VERTEXPROCESSING 0x00000040L +#define D3DCREATE_FPU_PRESERVE 0x00000002L +#define D3DPRASTERCAPS_FOGRANGE 0x00010000L +#define D3DPRASTERCAPS_FOGTABLE 0x00000100L +#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L +#define D3DPRASTERCAPS_WFOG 0x00100000L +#define D3DPRASTERCAPS_ZFOG 0x00200000L +#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L +#define D3DPRASTERCAPS_WBUFFER 0x00040000L +#define D3DPRASTERCAPS_ZTEST 0x00000010L + +// +// Caps2 +// +#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L +#define D3DPRASTERCAPS_SCISSORTEST 0x01000000L +#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */ +#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */ +#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */ +#define D3DCREATE_MULTITHREADED 0x00000004L +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L +#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L +#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */ +#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */ +#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L +#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */ +#define D3DTEXOPCAPS_ADD 0x00000040L +#define D3DTEXOPCAPS_MODULATE2X 0x00000010L +#define D3DPRASTERCAPS_DEPTHBIAS 0x04000000L +#define D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS 0x02000000L +#define D3DVTXPCAPS_TEXGEN_SPHEREMAP 0x00000100L /* device supports D3DTSS_TCI_SPHEREMAP */ +#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L + +// The following usages are valid only for querying CheckDeviceFormat +#define D3DUSAGE_QUERY_SRGBREAD (0x00010000L) +#define D3DUSAGE_QUERY_FILTER (0x00020000L) +#define D3DUSAGE_QUERY_SRGBWRITE (0x00040000L) +#define D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING (0x00080000L) +#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) + +/* Usages for Vertex/Index buffers */ +#define D3DUSAGE_WRITEONLY (0x00000008L) +#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) +#define D3DUSAGE_DONOTCLIP (0x00000020L) +#define D3DUSAGE_POINTS (0x00000040L) +#define D3DUSAGE_RTPATCHES (0x00000080L) +#define D3DUSAGE_NPATCHES (0x00000100L) + + +// Flags field for GetData +#define D3DGETDATA_FLUSH (1 << 0) // Tells the runtime to flush if the query is outstanding. + +#define D3DFVF_XYZ 0x002 + + +#define D3DTA_SELECTMASK 0x0000000f // mask for arg selector +#define D3DTA_DIFFUSE 0x00000000 // select diffuse color (read only) +#define D3DTA_CURRENT 0x00000001 // select stage destination register (read/write) +#define D3DTA_TEXTURE 0x00000002 // select texture color (read only) +#define D3DTA_TFACTOR 0x00000003 // select D3DRS_TEXTUREFACTOR (read only) +#define D3DTA_SPECULAR 0x00000004 // select specular color (read only) +#define D3DTA_TEMP 0x00000005 // select temporary register color (read/write) +#define D3DTA_CONSTANT 0x00000006 // select texture stage constant +#define D3DTA_COMPLEMENT 0x00000010 // take 1.0 - x (read modifier) +#define D3DTA_ALPHAREPLICATE 0x00000020 // replicate alpha to color components (read modifier) + + +#define D3DUSAGE_RENDERTARGET (0x00000001L) +#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) +#define D3DUSAGE_QUERY_FILTER (0x00020000L) +#define D3DUSAGE_DEPTHSTENCIL (0x00000002L) +#define D3DUSAGE_WRITEONLY (0x00000008L) +#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) +#define D3DUSAGE_DYNAMIC (0x00000200L) + +#define D3DSI_INSTLENGTH_MASK 0x0F000000 +#define D3DSI_INSTLENGTH_SHIFT 24 +#define D3DSP_TEXTURETYPE_SHIFT 27 +#define D3DSP_REGTYPE_SHIFT 28 +#define D3DSP_REGTYPE_SHIFT2 8 +#define D3DSP_REGTYPE_MASK 0x70000000 +#define D3DSP_REGTYPE_MASK2 0x00001800 + +#define D3DSP_REGNUM_MASK 0x000007FF + +#define D3DSP_DSTMOD_SHIFT 20 +#define D3DSP_DSTMOD_MASK 0x00F00000 +#define D3DSPDM_MSAMPCENTROID (4<>8)&0xFF) +#define D3DSHADER_VERSION_MINOR(_Version) (((_Version)>>0)&0xFF) + +#define D3DSHADER_ADDRESSMODE_SHIFT 13 +#define D3DSHADER_ADDRESSMODE_MASK (1 << D3DSHADER_ADDRESSMODE_SHIFT) + +#define D3DPS_END() 0x0000FFFF + +// ps_2_0 texld controls +#define D3DSI_TEXLD_PROJECT (0x01 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) +#define D3DSI_TEXLD_BIAS (0x02 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) + + +// destination parameter write mask +#define D3DSP_WRITEMASK_0 0x00010000 // Component 0 (X;Red) +#define D3DSP_WRITEMASK_1 0x00020000 // Component 1 (Y;Green) +#define D3DSP_WRITEMASK_2 0x00040000 // Component 2 (Z;Blue) +#define D3DSP_WRITEMASK_3 0x00080000 // Component 3 (W;Alpha) +#define D3DSP_WRITEMASK_ALL 0x000F0000 // All Components + +#define D3DVS_SWIZZLE_SHIFT 16 +#define D3DVS_SWIZZLE_MASK 0x00FF0000 + +// The following bits define where to take component X from: + +#define D3DVS_X_X (0 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_Y (1 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_Z (2 << D3DVS_SWIZZLE_SHIFT) +#define D3DVS_X_W (3 << D3DVS_SWIZZLE_SHIFT) + +// The following bits define where to take component Y from: + +#define D3DVS_Y_X (0 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_Y (1 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_Z (2 << (D3DVS_SWIZZLE_SHIFT + 2)) +#define D3DVS_Y_W (3 << (D3DVS_SWIZZLE_SHIFT + 2)) + +// The following bits define where to take component Z from: + +#define D3DVS_Z_X (0 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_Y (1 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_Z (2 << (D3DVS_SWIZZLE_SHIFT + 4)) +#define D3DVS_Z_W (3 << (D3DVS_SWIZZLE_SHIFT + 4)) + +// The following bits define where to take component W from: + +#define D3DVS_W_X (0 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_Y (1 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_Z (2 << (D3DVS_SWIZZLE_SHIFT + 6)) +#define D3DVS_W_W (3 << (D3DVS_SWIZZLE_SHIFT + 6)) + +// source parameter modifiers +#define D3DSP_SRCMOD_SHIFT 24 +#define D3DSP_SRCMOD_MASK 0x0F000000 + +// ------------------------------------------------------------------------------------------------------------------------------ // +// ENUMS +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef enum _D3DSHADER_PARAM_SRCMOD_TYPE +{ + D3DSPSM_NONE = 0<= 2.0 + + + D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 + D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) + D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) + D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) + D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) + D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) + D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) + D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) + D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values + D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. +} D3DDECLTYPE; + +typedef enum _D3DDECLMETHOD +{ + D3DDECLMETHOD_DEFAULT = 0, + D3DDECLMETHOD_PARTIALU, + D3DDECLMETHOD_PARTIALV, + D3DDECLMETHOD_CROSSUV, // Normal + D3DDECLMETHOD_UV, + D3DDECLMETHOD_LOOKUP, // Lookup a displacement map + D3DDECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map +} D3DDECLMETHOD; + +typedef enum _D3DDECLUSAGE +{ + D3DDECLUSAGE_POSITION = 0, + D3DDECLUSAGE_BLENDWEIGHT = 1, + D3DDECLUSAGE_BLENDINDICES = 2, + D3DDECLUSAGE_NORMAL = 3, + D3DDECLUSAGE_PSIZE = 4, + D3DDECLUSAGE_TEXCOORD = 5, + D3DDECLUSAGE_TANGENT = 6, + D3DDECLUSAGE_BINORMAL = 7, + D3DDECLUSAGE_TESSFACTOR = 8, + D3DDECLUSAGE_PLUGH = 9, // mystery value + D3DDECLUSAGE_COLOR = 10, + D3DDECLUSAGE_FOG = 11, + D3DDECLUSAGE_DEPTH = 12, + D3DDECLUSAGE_SAMPLE = 13, +} D3DDECLUSAGE; + +typedef enum _D3DPRIMITIVETYPE +{ + D3DPT_POINTLIST = 1, + D3DPT_LINELIST = 2, + D3DPT_TRIANGLELIST = 4, + D3DPT_TRIANGLESTRIP = 5, + D3DPT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DPRIMITIVETYPE; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// STRUCTURES +// ------------------------------------------------------------------------------------------------------------------------------ // + +typedef struct TOGL_CLASS D3DXPLANE +{ + float& operator[]( int i ); + bool operator==( const D3DXPLANE &o ); + bool operator!=( const D3DXPLANE &o ); + operator float*(); + operator const float*() const; + + float a, b, c, d; +} D3DXPLANE; + +typedef enum _D3DVERTEXBLENDFLAGS +{ + D3DVBF_DISABLE = 0, // Disable vertex blending + D3DVBF_1WEIGHTS = 1, // 2 matrix blending + D3DVBF_2WEIGHTS = 2, // 3 matrix blending + D3DVBF_3WEIGHTS = 3, // 4 matrix blending + D3DVBF_TWEENING = 255, // blending using D3DRS_TWEENFACTOR + D3DVBF_0WEIGHTS = 256, // one matrix is used with weight 1.0 + D3DVBF_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} D3DVERTEXBLENDFLAGS; + +typedef struct _D3DINDEXBUFFER_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + UINT Size; +} D3DINDEXBUFFER_DESC; + +typedef struct _D3DVERTEXELEMENT9 +{ + WORD Stream; // Stream index + WORD Offset; // Offset in the stream in bytes + BYTE Type; // Data type + BYTE Method; // Processing method + BYTE Usage; // Semantics + BYTE UsageIndex; // Semantic index +} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; + + +#define MAX_DEVICE_IDENTIFIER_STRING 512 +typedef struct _D3DADAPTER_IDENTIFIER9 +{ + char Driver[MAX_DEVICE_IDENTIFIER_STRING]; + char Description[MAX_DEVICE_IDENTIFIER_STRING]; + char DeviceName[32]; /* Device name for GDI (ex. \\.\DISPLAY1) */ + + LARGE_INTEGER DriverVersion; /* Defined for 32 bit components */ + + DWORD VendorId; + DWORD DeviceId; + DWORD SubSysId; + DWORD Revision; + DWORD VideoMemory; + +} D3DADAPTER_IDENTIFIER9; + +typedef struct _D3DCOLORVALUE +{ + float r; + float g; + float b; + float a; +} D3DCOLORVALUE; + +typedef struct _D3DMATERIAL9 +{ + D3DCOLORVALUE Diffuse; /* Diffuse color RGBA */ + D3DCOLORVALUE Ambient; /* Ambient color RGB */ + D3DCOLORVALUE Specular; /* Specular 'shininess' */ + D3DCOLORVALUE Emissive; /* Emissive color RGB */ + float Power; /* Sharpness if specular highlight */ +} D3DMATERIAL9; + +typedef struct _D3DVOLUME_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + + UINT Width; + UINT Height; + UINT Depth; +} D3DVOLUME_DESC; + +typedef struct _D3DVIEWPORT9 +{ + DWORD X; + DWORD Y; /* Viewport Top left */ + DWORD Width; + DWORD Height; /* Viewport Dimensions */ + float MinZ; /* Min/max of clip Volume */ + float MaxZ; +} D3DVIEWPORT9; + +typedef struct _D3DPSHADERCAPS2_0 +{ + DWORD Caps; + INT DynamicFlowControlDepth; + INT NumTemps; + INT StaticFlowControlDepth; + INT NumInstructionSlots; +} D3DPSHADERCAPS2_0; + +typedef struct _D3DCAPS9 +{ + /* Device Info */ + D3DDEVTYPE DeviceType; + + /* Caps from DX7 Draw */ + DWORD Caps; + DWORD Caps2; + + /* Cursor Caps */ + DWORD CursorCaps; + + /* 3D Device Caps */ + DWORD DevCaps; + + DWORD PrimitiveMiscCaps; + DWORD RasterCaps; + DWORD TextureCaps; + DWORD TextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DTexture9's + + DWORD MaxTextureWidth, MaxTextureHeight; + DWORD MaxVolumeExtent; + + DWORD MaxTextureAspectRatio; + DWORD MaxAnisotropy; + + DWORD TextureOpCaps; + DWORD MaxTextureBlendStages; + DWORD MaxSimultaneousTextures; + + DWORD VertexProcessingCaps; + DWORD MaxActiveLights; + DWORD MaxUserClipPlanes; + DWORD MaxVertexBlendMatrices; + DWORD MaxVertexBlendMatrixIndex; + + DWORD MaxPrimitiveCount; // max number of primitives per DrawPrimitive call + DWORD MaxStreams; + + DWORD VertexShaderVersion; + DWORD MaxVertexShaderConst; // number of vertex shader constant registers + + DWORD PixelShaderVersion; + + // Here are the DX9 specific ones + DWORD DevCaps2; + D3DPSHADERCAPS2_0 PS20Caps; + + DWORD NumSimultaneousRTs; // Will be at least 1 + DWORD MaxVertexShader30InstructionSlots; + DWORD MaxPixelShader30InstructionSlots; + + // only on Posix/GL + DWORD FakeSRGBWrite; // 1 for parts which can't support SRGB writes due to driver issues - 0 for others + DWORD MixedSizeTargets; // 1 for parts which can mix attachment sizes (RT's color vs depth) + DWORD CanDoSRGBReadFromRTs; // 0 when we're on Leopard, 1 when on Snow Leopard +} D3DCAPS9; + +typedef struct _D3DDISPLAYMODE +{ + UINT Width; + UINT Height; + UINT RefreshRate; + D3DFORMAT Format; +} D3DDISPLAYMODE; + +typedef struct _D3DGAMMARAMP +{ + WORD red [256]; + WORD green[256]; + WORD blue [256]; +} D3DGAMMARAMP; + + +/* Resize Optional Parameters */ +typedef struct _D3DPRESENT_PARAMETERS_ +{ + UINT BackBufferWidth; + UINT BackBufferHeight; + D3DFORMAT BackBufferFormat; + UINT BackBufferCount; + + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + + D3DSWAPEFFECT SwapEffect; + VD3DHWND hDeviceWindow; + BOOL Windowed; + BOOL EnableAutoDepthStencil; + D3DFORMAT AutoDepthStencilFormat; + DWORD Flags; + + /* FullScreen_RefreshRateInHz must be zero for Windowed mode */ + UINT FullScreen_RefreshRateInHz; + UINT PresentationInterval; +} D3DPRESENT_PARAMETERS; + +typedef struct _D3DDEVICE_CREATION_PARAMETERS +{ + UINT AdapterOrdinal; + D3DDEVTYPE DeviceType; + VD3DHWND hFocusWindow; + DWORD BehaviorFlags; +} D3DDEVICE_CREATION_PARAMETERS; + +/* Structures for LockBox */ +typedef struct _D3DBOX +{ + UINT Left; + UINT Top; + UINT Right; + UINT Bottom; + UINT Front; + UINT Back; +} D3DBOX; + +typedef struct _D3DLOCKED_BOX +{ + INT RowPitch; + INT SlicePitch; + void* pBits; +} D3DLOCKED_BOX; + +typedef struct _D3DSURFACE_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + UINT Width; + UINT Height; +} D3DSURFACE_DESC; + + +typedef struct _D3DLOCKED_RECT +{ + INT Pitch; + void* pBits; +} D3DLOCKED_RECT; + + +typedef struct _D3DRASTER_STATUS +{ + BOOL InVBlank; + UINT ScanLine; +} D3DRASTER_STATUS; + +typedef enum _D3DLIGHTTYPE +{ + D3DLIGHT_POINT = 1, + D3DLIGHT_SPOT = 2, + D3DLIGHT_DIRECTIONAL = 3, + D3DLIGHT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DLIGHTTYPE; + +typedef struct TOGL_CLASS _D3DVECTOR +{ + float x; + float y; + float z; +} D3DVECTOR; + +class TOGL_CLASS D3DXVECTOR2 +{ +public: + operator FLOAT* (); + operator CONST FLOAT* () const; + + float x,y; +}; + +class TOGL_CLASS D3DXVECTOR3 : public D3DVECTOR +{ +public: + D3DXVECTOR3() {} + D3DXVECTOR3( float a, float b, float c ); + operator FLOAT* (); + operator CONST FLOAT* () const; +}; + +typedef enum _D3DXINCLUDE_TYPE +{ + D3DXINC_LOCAL, + + // force 32-bit size enum + D3DXINC_FORCE_DWORD = 0x7fffffff + +} D3DXINCLUDE_TYPE; + +typedef struct _D3DLIGHT9 +{ + D3DLIGHTTYPE Type; /* Type of light source */ + D3DCOLORVALUE Diffuse; /* Diffuse color of light */ + D3DCOLORVALUE Specular; /* Specular color of light */ + D3DCOLORVALUE Ambient; /* Ambient color of light */ + D3DVECTOR Position; /* Position in world space */ + D3DVECTOR Direction; /* Direction in world space */ + float Range; /* Cutoff range */ + float Falloff; /* Falloff */ + float Attenuation0; /* Constant attenuation */ + float Attenuation1; /* Linear attenuation */ + float Attenuation2; /* Quadratic attenuation */ + float Theta; /* Inner angle of spotlight cone */ + float Phi; /* Outer angle of spotlight cone */ +} D3DLIGHT9; + +class TOGL_CLASS D3DXVECTOR4 +{ +public: + D3DXVECTOR4() {} + D3DXVECTOR4( float a, float b, float c, float d ); + + float x,y,z,w; +}; + +//---------------------------------------------------------------------------- +// D3DXMACRO: +// ---------- +// Preprocessor macro definition. The application pass in a NULL-terminated +// array of this structure to various D3DX APIs. This enables the application +// to #define tokens at runtime, before the file is parsed. +//---------------------------------------------------------------------------- + +typedef struct _D3DXMACRO +{ + LPCSTR Name; + LPCSTR Definition; + +} D3DXMACRO, *LPD3DXMACRO; + +// ------------------------------------------------------------------------------------------------------------------------------ // +// ------------------------------------------------------------------------------------------------------------------------------ // +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +// +// Also look for any functions marked with "**** FIXED FUNCTION STUFF" +// +// It's only laying around here so we don't have to chop up the shader system a lot to strip out the fixed function code paths. +// ------------------------------------------------------------------------------------------------------------------------------ // +// ------------------------------------------------------------------------------------------------------------------------------ // + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTRANSFORMSTATETYPE +{ + D3DTS_VIEW = 2, + D3DTS_PROJECTION = 3, + D3DTS_TEXTURE0 = 16, + D3DTS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTRANSFORMSTATETYPE; + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTEXTUREOP +{ + // Control + D3DTOP_DISABLE = 1, // disables stage + D3DTOP_SELECTARG1 = 2, // the default + D3DTOP_SELECTARG2 = 3, + + // Modulate + D3DTOP_MODULATE = 4, // multiply args together + D3DTOP_MODULATE2X = 5, // multiply and 1 bit + D3DTOP_MODULATE4X = 6, // multiply and 2 bits + + // Add + D3DTOP_ADD = 7, // add arguments together + D3DTOP_ADDSIGNED = 8, // add with -0.5 bias + D3DTOP_ADDSIGNED2X = 9, // as above but left 1 bit + D3DTOP_SUBTRACT = 10, // Arg1 - Arg2, with no saturation + D3DTOP_ADDSMOOTH = 11, // add 2 args, subtract product + // Arg1 + Arg2 - Arg1*Arg2 + // = Arg1 + (1-Arg1)*Arg2 + + // Linear alpha blend: Arg1*(Alpha) + Arg2*(1-Alpha) + D3DTOP_BLENDDIFFUSEALPHA = 12, // iterated alpha + D3DTOP_BLENDTEXTUREALPHA = 13, // texture alpha + D3DTOP_BLENDFACTORALPHA = 14, // alpha from D3DRS_TEXTUREFACTOR + + // Linear alpha blend with pre-multiplied arg1 input: Arg1 + Arg2*(1-Alpha) + D3DTOP_BLENDTEXTUREALPHAPM = 15, // texture alpha + D3DTOP_BLENDCURRENTALPHA = 16, // by alpha of current color + + // Specular mapping + D3DTOP_PREMODULATE = 17, // modulate with next texture before use + D3DTOP_MODULATEALPHA_ADDCOLOR = 18, // Arg1.RGB + Arg1.A*Arg2.RGB + // COLOROP only + D3DTOP_MODULATECOLOR_ADDALPHA = 19, // Arg1.RGB*Arg2.RGB + Arg1.A + // COLOROP only + D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20, // (1-Arg1.A)*Arg2.RGB + Arg1.RGB + // COLOROP only + D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21, // (1-Arg1.RGB)*Arg2.RGB + Arg1.A + // COLOROP only + + // Bump mapping + D3DTOP_BUMPENVMAP = 22, // per pixel env map perturbation + D3DTOP_BUMPENVMAPLUMINANCE = 23, // with luminance channel + + // This can do either diffuse or specular bump mapping with correct input. + // Performs the function (Arg1.R*Arg2.R + Arg1.G*Arg2.G + Arg1.B*Arg2.B) + // where each component has been scaled and offset to make it signed. + // The result is replicated into all four (including alpha) channels. + // This is a valid COLOROP only. + D3DTOP_DOTPRODUCT3 = 24, + + // Triadic ops + D3DTOP_MULTIPLYADD = 25, // Arg0 + Arg1*Arg2 + D3DTOP_LERP = 26, // (Arg0)*Arg1 + (1-Arg0)*Arg2 + + D3DTOP_FORCE_DWORD = 0x7fffffff, +} D3DTEXTUREOP; + +// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. +typedef enum _D3DTEXTURESTAGESTATETYPE +{ + D3DTSS_COLOROP = 1, /* D3DTEXTUREOP - per-stage blending controls for color channels */ + D3DTSS_COLORARG1 = 2, /* D3DTA_* (texture arg) */ + D3DTSS_COLORARG2 = 3, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAOP = 4, /* D3DTEXTUREOP - per-stage blending controls for alpha channel */ + D3DTSS_ALPHAARG1 = 5, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAARG2 = 6, /* D3DTA_* (texture arg) */ + D3DTSS_BUMPENVMAT00 = 7, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT01 = 8, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT10 = 9, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT11 = 10, /* float (bump mapping matrix) */ + D3DTSS_TEXCOORDINDEX = 11, /* identifies which set of texture coordinates index this texture */ + D3DTSS_BUMPENVLOFFSET = 23, /* float offset for bump map luminance */ + D3DTSS_TEXTURETRANSFORMFLAGS = 24, /* D3DTEXTURETRANSFORMFLAGS controls texture transform */ + D3DTSS_COLORARG0 = 26, /* D3DTA_* third arg for triadic ops */ + D3DTSS_RESULTARG = 28, /* D3DTA_* arg for result (CURRENT or TEMP) */ + + + D3DTSS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTEXTURESTAGESTATETYPE; + +//===========================================================================// + +enum GLMVertexAttributeIndex +{ + kGLMGenericAttr00 = 0, + kGLMGenericAttr01, + kGLMGenericAttr02, + kGLMGenericAttr03, + kGLMGenericAttr04, + kGLMGenericAttr05, + kGLMGenericAttr06, + kGLMGenericAttr07, + kGLMGenericAttr08, + kGLMGenericAttr09, + kGLMGenericAttr10, + kGLMGenericAttr11, + kGLMGenericAttr12, + kGLMGenericAttr13, + kGLMGenericAttr14, + kGLMGenericAttr15, + + kGLMVertexAttributeIndexMax // ideally < 32 +}; + +struct GLMVertexAttributeDesc // all the info you need to do vertex setup for one attribute +{ + CGLMBuffer *m_buffer; // NULL allowed in which case m_offset is the full 32-bit pointer.. so you can draw from plain RAM if desired + GLuint m_datasize; // comp count of the attribute (1-4) + GLenum m_datatype; // data type of the attribute (GL_FLOAT, GL_UNSIGNED_BYTE, etc) + GLuint m_stride; + GLuint m_offset; // net offset to attribute 'zero' within the buffer. + GLboolean m_normalized; // apply to any fixed point data that needs normalizing, esp color bytes + + // may need a seed value at some point to be able to disambiguate re-lifed buffers holding same pointer + // simpler alternative is to do shoot-down inside the vertex/index buffer free calls. + // I'd rather not have to have each attribute fiddling a ref count on the buffer to which it refers.. + +#define EQ(fff) ( (src.fff) == (fff) ) + // test in decreasing order of likelihood of difference, but do not include the buffer revision as caller is not supplying it.. + bool operator==(const GLMVertexAttributeDesc& src) const { return EQ(m_buffer) && EQ(m_offset) && EQ(m_stride) && EQ(m_datatype) && EQ(m_normalized) && EQ(m_datasize); } +#undef EQ + + uint m_bufferRevision; // only set in GLM context's copy, to disambiguate references that are same offset / same buffer but cross an orphan event +}; + + +#define MAX_D3DVERTEXELEMENTS 16 + +struct D3DVERTEXELEMENT9_GL +{ + // fields right out of the original decl element (copied) + D3DVERTEXELEMENT9 m_dxdecl; // d3d info + // WORD Stream; // Stream index + // WORD Offset; // Offset in the stream in bytes + // BYTE Type; // Data type + // BYTE Method; // Processing method + // BYTE Usage; // Semantics + // BYTE UsageIndex; // Semantic index + + GLMVertexAttributeDesc m_gldecl; + // CGLMBuffer *m_buffer; // late-dropped from selected stream desc (left NULL, will replace with stream source buffer at sync time) + // GLuint m_datasize; // component count (1,2,3,4) of the attrib + // GLenum m_datatype; // data type of the attribute (GL_FLOAT et al) + // GLuint m_stride; // late-dropped from stream desc + // GLuint m_offset; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. + // GLuint m_normalized; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. +}; + +struct IDirect3DDevice9Params +{ + UINT m_adapter; + D3DDEVTYPE m_deviceType; + VD3DHWND m_focusWindow; + DWORD m_behaviorFlags; + D3DPRESENT_PARAMETERS m_presentationParameters; +}; + +#define D3D_MAX_STREAMS 4 +struct D3DStreamDesc +{ + IDirect3DVertexBuffer9 *m_vtxBuffer; + uint m_offset; + uint m_stride; +}; + +struct D3DIndexDesc +{ + IDirect3DIndexBuffer9 *m_idxBuffer; +}; + +// we latch sampler values until draw time and then convert them all to GL form +// note these are similar in name to the fields of a GLMTexSamplingParams but contents are not +// particularly in the texture filtering area + +struct D3DSamplerDesc +{ + D3DTEXTUREADDRESS m_addressModes[3]; // D3DTEXTUREADDRESS modes for S,T,R + DWORD m_borderColor; // DWORD bordercolor + D3DTEXTUREFILTERTYPE m_magFilter; // mag filter + D3DTEXTUREFILTERTYPE m_minFilter; // min filter + D3DTEXTUREFILTERTYPE m_mipFilter; // mip filter + float m_mipmapBias; // float: mipmap bias + DWORD m_maxMipLevel; // DWORD 0..(n-1) LOD index of largest map to use (0 == largest) + DWORD m_maxAniso; // D3DSAMP_MAXANISOTROPY max aniso + DWORD m_srgb; // D3DSAMP_SRGBTEXTURE 0 = no SRGB sampling + DWORD m_shadowFilter; // D3DSAMP_SHADOWFILTER +}; + +// Tracking and naming sampler dimensions +#define SAMPLER_TYPE_2D 0 +#define SAMPLER_TYPE_CUBE 1 +#define SAMPLER_TYPE_3D 2 +#define SAMPLER_TYPE_UNUSED 3 + +#endif // DXABSTRACT_TYPES_H diff --git a/sp/src/public/togl/osx/glentrypoints.h b/sp/src/public/togl/osx/glentrypoints.h new file mode 100644 index 00000000..1ae4423c --- /dev/null +++ b/sp/src/public/togl/osx/glentrypoints.h @@ -0,0 +1,329 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glentrypoints.h +// +//=============================================================================== + +#ifndef GLENTRYPOINTS_H +#define GLENTRYPOINTS_H + +#pragma once + +#ifdef DX_TO_GL_ABSTRACTION + +#include "tier0/platform.h" +#include "tier0/dynfunction.h" +#include "tier0/vprof_telemetry.h" +#include "interface.h" + +#include "togl/rendermechanism.h" + +#ifndef APIENTRY +#define APIENTRY +#endif + +#ifndef CALLBACK +#define CALLBACK +#endif + + +void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback=NULL); + +#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME +class CGLExecuteHelperBase +{ +public: + inline void StartCall(const char *pName); + inline void StopCall(const char *pName); +#if GL_TRACK_API_TIME + TmU64 m_nStartTime; +#endif +}; + +template < class FunctionType, typename Result > +class CGLExecuteHelper : public CGLExecuteHelperBase +{ +public: + inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } + + inline operator Result() const { return m_Result; } + inline operator char*() const { return (char*)m_Result; } + + FunctionType m_pFn; + + Result m_Result; +}; + +template < class FunctionType> +class CGLExecuteHelper : public CGLExecuteHelperBase +{ +public: + inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } + template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } + + FunctionType m_pFn; +}; +#endif + +template < class FunctionType, typename Result > +class CDynamicFunctionOpenGLBase +{ +public: + // Construct with a NULL function pointer. You must manually call + // Lookup() before you can call a dynamic function through this interface. + CDynamicFunctionOpenGLBase() : m_pFn(NULL) {} + + // Construct and do a lookup right away. You will need to make sure that + // the lookup actually succeeded, as the gl library might have failed to load + // or (fn) might not exist in it. + CDynamicFunctionOpenGLBase(const char *fn, FunctionType fallback=NULL) : m_pFn(NULL) + { + Lookup(fn, fallback); + } + + // Construct and do a lookup right away. See comments in Lookup() about what (okay) does. + CDynamicFunctionOpenGLBase(const char *fn, bool &okay, FunctionType fallback=NULL) : m_pFn(NULL) + { + Lookup(fn, okay, fallback); + } + + // Load library if necessary, look up symbol. Returns true and sets + // m_pFn on successful lookup, returns false otherwise. If the + // function pointer is already looked up, this return true immediately. + // Use Reset() first if you want to look up the symbol again. + // This function will return false immediately unless (okay) is true. + // This allows you to chain lookups like this: + // bool okay = true; + // x.Lookup(lib, "x", okay); + // y.Lookup(lib, "y", okay); + // z.Lookup(lib, "z", okay); + // if (okay) { printf("All functions were loaded successfully!\n"); } + // If you supply a fallback, it'll be used if the lookup fails (and if + // non-NULL, means this will always return (okay)). + bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) + { + if (!okay) + return false; + else if (this->m_pFn == NULL) + { + this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, false, (void *) fallback); + this->SetFuncName( fn ); + } + return okay; + } + + // Load library if necessary, look up symbol. Returns true and sets + // m_pFn on successful lookup, returns false otherwise. If the + // function pointer is already looked up, this return true immediately. + // Use Reset() first if you want to look up the symbol again. + // This function will return false immediately unless (okay) is true. + // If you supply a fallback, it'll be used if the lookup fails (and if + // non-NULL, means this will always return true). + bool Lookup(const char *fn, FunctionType fallback=NULL) + { + bool okay = true; + return Lookup(fn, okay, fallback); + } + + // Invalidates the current lookup. Makes the function pointer NULL. You + // will need to call Lookup() before you can call a dynamic function + // through this interface again. + void Reset() { m_pFn = NULL; } + + // Force this to be a specific function pointer. + void Force(FunctionType ptr) { m_pFn = ptr; } + + // Retrieve the actual function pointer. + FunctionType Pointer() const { return m_pFn; } + +#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME + #if GL_TELEMETRY_ZONES + #define GL_FUNC_NAME m_szName + #else + #define GL_FUNC_NAME "" + #endif + + inline CGLExecuteHelper operator() () const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME ); } + + template + inline CGLExecuteHelper operator() (T a) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a); } + + template + inline CGLExecuteHelper operator() (T a, U b) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c ) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i); } + + template + inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i, C j) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i, j); } +#else + operator FunctionType() const { return m_pFn; } +#endif + + // Can be used to verify that we have an actual function looked up and + // ready to call: if (!MyDynFunc) { printf("Function not found!\n"); } + operator bool () const { return m_pFn != NULL; } + bool operator !() const { return m_pFn == NULL; } + +protected: + FunctionType m_pFn; + +#if GL_TELEMETRY_ZONES + char m_szName[32]; + inline void SetFuncName(const char *pFn) { V_strncpy( m_szName, pFn, sizeof( m_szName ) ); } +#else + inline void SetFuncName(const char *pFn) { (void)pFn; } +#endif +}; + +// This works a lot like CDynamicFunctionMustInit, but we use SDL_GL_GetProcAddress(). +template < const bool bRequired, class FunctionType, typename Result > +class CDynamicFunctionOpenGL : public CDynamicFunctionOpenGLBase< FunctionType, Result > +{ +private: // forbid default constructor. + CDynamicFunctionOpenGL() {} + +public: + CDynamicFunctionOpenGL(const char *fn, FunctionType fallback=NULL) + { + bool okay = true; + Lookup(fn, okay, fallback); + this->SetFuncName( fn ); + } + + CDynamicFunctionOpenGL(const char *fn, bool &okay, FunctionType fallback=NULL) + { + Lookup(fn, okay, fallback); + this->SetFuncName( fn ); + } + + // Please note this is not virtual. + // !!! FIXME: we might want to fall back and try "EXT" or "ARB" versions in some case. + bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) + { + if (this->m_pFn == NULL) + { + this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, bRequired, (void *) fallback); + this->SetFuncName( fn ); + } + return okay; + } +}; + + +// This provides all the entry points for a given OpenGL context. +// ENTRY POINTS ARE ONLY VALID FOR THE CONTEXT THAT WAS CURRENT WHEN +// YOU LOOKED THEM UP. 99% of the time, this is not a problem, but +// that 1% is really hard to track down. Always access the GL +// through this class! +class COpenGLEntryPoints +{ +public: + // The GL context you are looking up entry points for must be current when you construct this object! + COpenGLEntryPoints(); + + uint64 m_nTotalGLCycles, m_nTotalGLCalls; + + int m_nOpenGLVersionMajor; // if GL_VERSION is 2.1.0, this will be set to 2. + int m_nOpenGLVersionMinor; // if GL_VERSION is 2.1.0, this will be set to 1. + int m_nOpenGLVersionPatch; // if GL_VERSION is 2.1.0, this will be set to 0. + bool m_bHave_OpenGL; + + #define GL_EXT(x,glmajor,glminor) bool m_bHave_##x; + #define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn; + #define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn; + #include "togl/glfuncs.inl" + #undef GL_FUNC_VOID + #undef GL_FUNC + #undef GL_EXT +}; + +// This will be set to the current OpenGL context's entry points. +extern COpenGLEntryPoints *gGL; +typedef void * (*GL_GetProcAddressCallbackFunc_t)(const char *, bool &, const bool, void *); + +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); + DLL_EXPORT void ToGLDisconnectLibraries(); + DLL_EXPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); +#else + DLL_IMPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); + DLL_IMPORT void ToGLDisconnectLibraries(); + DLL_IMPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); +#endif + +#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME +inline void CGLExecuteHelperBase::StartCall(const char *pName) +{ + (void)pName; + +#if GL_TELEMETRY_ZONES + tmEnter( TELEMETRY_LEVEL3, TMZF_NONE, pName ); +#endif + +#if GL_TRACK_API_TIME + m_nStartTime = tmFastTime(); +#endif +} + +inline void CGLExecuteHelperBase::StopCall(const char *pName) +{ +#if GL_TRACK_API_TIME + uint64 nTotalCycles = tmFastTime() - m_nStartTime; +#endif + +#if GL_TELEMETRY_ZONES + tmLeave( TELEMETRY_LEVEL3 ); +#endif + +#if GL_TRACK_API_TIME + //double flMilliseconds = g_Telemetry.flRDTSCToMilliSeconds * nTotalCycles; + if (gGL) + { + gGL->m_nTotalGLCycles += nTotalCycles; + gGL->m_nTotalGLCalls++; + } +#endif +} +#endif + +#endif // DX_TO_GL_ABSTRACTION + +#endif // GLENTRYPOINTS_H diff --git a/sp/src/public/togl/osx/glfuncs.h b/sp/src/public/togl/osx/glfuncs.h new file mode 100644 index 00000000..484786c6 --- /dev/null +++ b/sp/src/public/togl/osx/glfuncs.h @@ -0,0 +1,184 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// !!! FIXME: Some of these aren't base OpenGL...pick out the extensions. +// !!! FIXME: Also, look up these -1, -1 versions numbers. +GL_FUNC(OpenGL,true,GLenum,glGetError,(void),()) +GL_FUNC_VOID(OpenGL,true,glActiveTexture,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glAlphaFunc,(GLenum a,GLclampf b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glAttachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBegin,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glBindAttribLocationARB,(GLhandleARB a,GLuint b,const GLcharARB *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glBindBufferARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindProgramARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBindTexture,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBlendColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glBlendEquation,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glBlendFunc,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glBufferDataARB,(GLenum a,GLsizeiptrARB b,const GLvoid *c,GLenum d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glClear,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glClearColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glClearDepth,(GLclampd a),(a)) +GL_FUNC_VOID(OpenGL,true,glClearStencil,(GLint a),(a)) +GL_FUNC_VOID(OpenGL,true,glClipPlane,(GLenum a,const GLdouble *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glColorMask,(GLboolean a,GLboolean b,GLboolean c,GLboolean d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glCompileShaderARB,(GLhandleARB a),(a)) +GL_FUNC_VOID(OpenGL,true,glCompressedTexImage2D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLint f,GLsizei g,const GLvoid *h),(a,b,c,d,e,f,g,h)) +GL_FUNC_VOID(OpenGL,true,glCompressedTexImage3D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLsizei h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC(OpenGL,true,GLhandleARB,glCreateProgramObjectARB,(void),()) +GL_FUNC(OpenGL,true,GLhandleARB,glCreateShaderObjectARB,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteBuffersARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteObjectARB,(GLhandleARB a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteProgramsARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteQueriesARB,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDeleteShader,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glDeleteTextures,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDepthFunc,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDepthMask,(GLboolean a),(a)) +GL_FUNC_VOID(OpenGL,true,glDepthRange,(GLclampd a,GLclampd b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDetachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glDisable,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDisableVertexAttribArray,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawArrays,(GLenum a,GLint b,GLsizei c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glDrawBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawRangeElements,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glEnable,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glEnableVertexAttribArray,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glEnd,(void),()) +GL_FUNC_VOID(OpenGL,true,glFinish,(void),()) +GL_FUNC_VOID(OpenGL,true,glFlush,(void),()) +GL_FUNC_VOID(OpenGL,true,glFrontFace,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glGenBuffersARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenProgramsARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenQueriesARB,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGenTextures,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetBooleanv,(GLenum a,GLboolean *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetCompressedTexImage,(GLenum a,GLint b,GLvoid *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGetDoublev,(GLenum a,GLdouble *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetFloatv,(GLenum a,GLfloat *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetInfoLogARB,(GLhandleARB a,GLsizei b,GLsizei *c,GLcharARB *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glGetIntegerv,(GLenum a,GLint *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glGetObjectParameterivARB,(GLhandleARB a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glGetProgramivARB,(GLenum a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC(OpenGL,true,const GLubyte *,glGetString,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glGetTexImage,(GLenum a,GLint b,GLenum c,GLenum d,GLvoid *e),(a,b,c,d,e)) +GL_FUNC(OpenGL,true,GLint,glGetUniformLocationARB,(GLhandleARB a,const GLcharARB *b),(a,b)) +GL_FUNC(OpenGL,true,GLboolean,glIsEnabled,(GLenum a),(a)) +GL_FUNC(OpenGL,true,GLboolean,glIsTexture,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glLinkProgramARB,(GLhandleARB a),(a)) +GL_FUNC(OpenGL,true,GLvoid*,glMapBufferARB,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glOrtho,(GLdouble a,GLdouble b,GLdouble c,GLdouble d,GLdouble e,GLdouble f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glPixelStorei,(GLenum a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPolygonMode,(GLenum a,GLenum b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPolygonOffset,(GLfloat a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPopAttrib,(void),()) +GL_FUNC_VOID(OpenGL,true,glProgramStringARB,(GLenum a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glPushAttrib,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glReadBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glScissor,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glShaderSourceARB,(GLhandleARB a,GLsizei b,const GLcharARB **c,const GLint *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glStencilFunc,(GLenum a,GLint b,GLuint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glStencilMask,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glStencilOp,(GLenum a,GLenum b,GLenum c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexCoord2f,(GLfloat a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glTexImage2D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLint f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC_VOID(OpenGL,true,glTexImage3D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLenum h,GLenum i,const GLvoid *j),(a,b,c,d,e,f,g,h,i,j)) +GL_FUNC_VOID(OpenGL,true,glTexParameterfv,(GLenum a,GLenum b,const GLfloat *c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexParameteri,(GLenum a,GLenum b,GLint c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glTexSubImage2D,(GLenum a,GLint b,GLint c,GLint d,GLsizei e,GLsizei f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) +GL_FUNC_VOID(OpenGL,true,glUniform1f,(GLint a,GLfloat b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform1i,(GLint a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform1iARB,(GLint a,GLint b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glUniform4fv,(GLint a,GLsizei b,const GLfloat *c),(a,b,c)) +GL_FUNC(OpenGL,true,GLboolean,glUnmapBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glUseProgram,(GLuint a),(a)) +GL_FUNC_VOID(OpenGL,true,glVertex3f,(GLfloat a,GLfloat b,GLfloat c),(a,b,c)) +GL_FUNC_VOID(OpenGL,true,glVertexAttribPointer,(GLuint a,GLint b,GLenum c,GLboolean d,GLsizei e,const GLvoid *f),(a,b,c,d,e,f)) +GL_FUNC_VOID(OpenGL,true,glViewport,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glEnableClientState,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDisableClientState,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glClientActiveTexture,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glVertexPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glTexCoordPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glProgramEnvParameters4fvEXT,(GLenum a,GLuint b,GLsizei c,const GLfloat *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glColor4sv,(const GLshort *a),(a)) +GL_FUNC_VOID(OpenGL,true,glStencilOpSeparate,(GLenum a,GLenum b,GLenum c,GLenum d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glStencilFuncSeparate,(GLenum a,GLenum b,GLint c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glGetTexLevelParameteriv,(GLenum a,GLint b,GLenum c,GLint *d),(a,b,c,d)) +GL_FUNC_VOID(OpenGL,true,glColor4f,(GLfloat a,GLfloat b,GLfloat c,GLfloat d),(a,b,c,d)) +GL_EXT(GL_EXT_framebuffer_object,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindFramebufferEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindRenderbufferEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC(GL_EXT_framebuffer_object,false,GLenum,glCheckFramebufferStatusEXT,(GLenum a),(a)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteRenderbuffersEXT,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferRenderbufferEXT,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture2DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture3DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenFramebuffersEXT,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenRenderbuffersEXT,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteFramebuffersEXT,(GLsizei a,const GLuint *b),(a,b)) +GL_EXT(GL_EXT_framebuffer_blit,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_blit,false,glBlitFramebufferEXT,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) +GL_EXT(GL_EXT_framebuffer_multisample,-1,-1) +GL_FUNC_VOID(GL_EXT_framebuffer_multisample,false,glRenderbufferStorageMultisampleEXT,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) +GL_EXT(GL_APPLE_fence,-1,-1) +GL_FUNC(GL_APPLE_fence,false,GLboolean,glTestFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glSetFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glFinishFenceAPPLE,(GLuint a),(a)) +GL_FUNC_VOID(GL_APPLE_fence,false,glDeleteFencesAPPLE,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_APPLE_fence,false,glGenFencesAPPLE,(GLsizei a,GLuint *b),(a,b)) +GL_EXT(GL_NV_fence,-1,-1) +GL_FUNC(GL_NV_fence,false,GLboolean,glTestFenceNV,(GLuint a),(a)) +GL_FUNC_VOID(GL_NV_fence,false,glSetFenceNV,(GLuint a,GLenum b),(a,b)) +GL_FUNC_VOID(GL_NV_fence,false,glFinishFenceNV,(GLuint a),(a)) +GL_FUNC_VOID(GL_NV_fence,false,glDeleteFencesNV,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_NV_fence,false,glGenFencesNV,(GLsizei a,GLuint *b),(a,b)) +GL_EXT(GL_ARB_sync,3,2) +#ifdef HAVE_GL_ARB_SYNC +GL_FUNC_VOID(GL_ARB_sync,false,glGetSynciv,(GLsync a, GLenum b, GLsizei c, GLsizei *d, GLint *e),(a,b,c,d,e)) +GL_FUNC(GL_ARB_sync,false,GLenum,glClientWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_sync,false,glWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_sync,false,glDeleteSync,(GLsync a),(a)) +GL_FUNC(GL_ARB_sync,false,GLsync,glFenceSync,(GLenum a, GLbitfield b),(a,b)) +#endif +GL_EXT(GL_EXT_draw_buffers2,-1,-1) +GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glColorMaskIndexedEXT,(GLuint a,GLboolean b,GLboolean c,GLboolean d,GLboolean e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glEnableIndexedEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glDisableIndexedEXT,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glGetBooleanIndexedvEXT,(GLenum a,GLuint b,GLboolean *c),(a,b,c)) +GL_EXT(GL_EXT_bindable_uniform,-1,-1) +GL_FUNC_VOID(GL_EXT_bindable_uniform,false,glUniformBufferEXT,(GLuint a,GLint b,GLuint c),(a,b,c)) +GL_EXT(GL_APPLE_flush_buffer_range,-1,-1) +GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glBufferParameteriAPPLE,(GLenum a,GLenum b,GLint c),(a,b,c)) +GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glFlushMappedBufferRangeAPPLE,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) +GL_EXT(GL_ARB_map_buffer_range,-1,-1) +GL_FUNC(GL_ARB_map_buffer_range,false,void*,glMapBufferRange,(GLenum a,GLintptr b,GLsizeiptr c,GLbitfield d),(a,b,c,d)) +GL_FUNC_VOID(GL_ARB_map_buffer_range,false,glFlushMappedBufferRange,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) +GL_EXT(GL_ARB_occlusion_query,-1,-1) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glBeginQueryARB,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glEndQueryARB,(GLenum a),(a)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectivARB,(GLuint a,GLenum b,GLint *c),(a,b,c)) +GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectuivARB,(GLuint a,GLenum b,GLuint *c),(a,b,c)) +GL_EXT(GL_APPLE_texture_range,-1,-1) +GL_FUNC_VOID(GL_APPLE_texture_range,false,glTextureRangeAPPLE,(GLenum a,GLsizei b,void *c),(a,b,c)) +GL_FUNC_VOID(GL_APPLE_texture_range,false,glGetTexParameterPointervAPPLE,(GLenum a,GLenum b,void* *c),(a,b,c)) +GL_EXT(GL_APPLE_client_storage,-1,-1) +GL_EXT(GL_ARB_uniform_buffer,-1,-1) +GL_EXT(GL_ARB_vertex_array_bgra,-1,-1) +GL_EXT(GL_EXT_vertex_array_bgra,-1,-1) +GL_EXT(GL_ARB_framebuffer_object,3,0) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindFramebuffer,(GLenum a,GLuint b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindRenderbuffer,(GLenum a,GLuint b),(a,b)) +GL_FUNC(GL_ARB_framebuffer_object,false,GLenum,glCheckFramebufferStatus,(GLenum a),(a)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteRenderbuffers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferRenderbuffer,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture2D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture3D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenFramebuffers,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenRenderbuffers,(GLsizei a,GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteFramebuffers,(GLsizei a,const GLuint *b),(a,b)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBlitFramebuffer,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) +GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glRenderbufferStorageMultisample,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) +GL_EXT(GL_GREMEDY_string_marker,-1,-1) +GL_FUNC_VOID(GL_GREMEDY_string_marker,false,glStringMarkerGREMEDY,(GLsizei a,const void *b),(a,b)) +GL_FUNC_VOID(OpenGL,true,glPushClientAttrib,(GLbitfield a),(a)) +GL_FUNC_VOID(OpenGL,true,glPopClientAttrib,(void),()) + diff --git a/sp/src/public/togl/osx/glmdebug.h b/sp/src/public/togl/osx/glmdebug.h new file mode 100644 index 00000000..5981677d --- /dev/null +++ b/sp/src/public/togl/osx/glmdebug.h @@ -0,0 +1,157 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef GLMDEBUG_H +#define GLMDEBUG_H + +#include "tier0/platform.h" +#include + +// include this anywhere you need to be able to compile-out code related specifically to GLM debugging. + +// we expect DEBUG to be driven by the build system so you can include this header anywhere. +// when we come out, GLMDEBUG will be defined to a value - 0, 1, or 2 +// 0 means no GLM debugging is possible +// 1 means it's possible and resulted from being a debug build +// 2 means it's possible and resulted from being manually forced on for a release build + +#ifdef POSIX + #ifndef GLMDEBUG + #ifdef DEBUG + #define GLMDEBUG 1 // normally 1 here, testing + #else + // #define GLMDEBUG 2 // don't check this in enabled.. + #endif + + #ifndef GLMDEBUG + #define GLMDEBUG 0 + #endif + #endif +#else + #ifndef GLMDEBUG + #define GLMDEBUG 0 + #endif +#endif + + +//=============================================================================== +// debug channels + +enum EGLMDebugChannel +{ + ePrintf, + eDebugger, + eGLProfiler +}; + +#if GLMDEBUG + // make all these prototypes disappear in non GLMDEBUG + void GLMDebugInitialize( bool forceReinit=false ); + + bool GLMDetectOGLP( void ); + bool GLMDetectGDB( void ); + uint GLMDetectAvailableChannels( void ); + + uint GLMDebugChannelMask( uint *newValue = NULL ); + // note that GDB and OGLP can both come and go during run - forceCheck will allow that to be detected. + // mask returned is in form of 1< < + eComment, // 3 one off messages --- + eMatrixData, // 4 matrix data -M- + eShaderData, // 5 shader data (params) -S- + eFrameBufData, // 6 FBO data (attachments) -F- + eDXStuff, // 7 dxabstract spew -X- + eAllocations, // 8 tracking allocs and frees -A- + eSlowness, // 9 slow things happening (srgb flips..) -Z- + eDefaultFlavor, // not specified (no marker) + eFlavorCount +}; +uint GLMDebugFlavorMask( uint *newValue = NULL ); + +// make all these prototypes disappear in non GLMDEBUG +#if GLMDEBUG + // these are unconditional outputs, they don't interrogate the string + void GLMStringOut( const char *string ); + void GLMStringOutIndented( const char *string, int indentColumns ); + + #ifdef TOGL_DLL_EXPORT + // these will look at the string to guess its flavor: <, >, ---, -M-, -S- + DLL_EXPORT void GLMPrintfVA( const char *fmt, va_list vargs ); + DLL_EXPORT void GLMPrintf( const char *fmt, ... ); + #else + DLL_IMPORT void GLMPrintfVA( const char *fmt, va_list vargs ); + DLL_IMPORT void GLMPrintf( const char *fmt, ... ); + #endif + + // these take an explicit flavor with a default value + void GLMPrintStr( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor ); + + #define GLMPRINTTEXT_NUMBEREDLINES 0x80000000 + void GLMPrintText( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor, uint options=0 ); // indent each newline + + int GLMIncIndent( int indentDelta ); + int GLMGetIndent( void ); + void GLMSetIndent( int indent ); + +#endif + +// helpful macro if you are in a position to call GLM functions directly (i.e. you live in materialsystem / shaderapidx9) +#if GLMDEBUG + #define GLMPRINTF(args) GLMPrintf args + #define GLMPRINTSTR(args) GLMPrintStr args + #define GLMPRINTTEXT(args) GLMPrintText args +#else + #define GLMPRINTF(args) + #define GLMPRINTSTR(args) + #define GLMPRINTTEXT(args) +#endif + + +//=============================================================================== +// knob twiddling +#ifdef TOGL_DLL_EXPORT + DLL_EXPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value + DLL_EXPORT float GLMKnobToggle( char *knobname ); +#else + DLL_IMPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value + DLL_IMPORT float GLMKnobToggle( char *knobname ); +#endif + +//=============================================================================== +// other stuff + +#if GLMDEBUG +void GLMTriggerDebuggerBreak(); +inline void GLMDebugger( void ) +{ + if (GLMDebugChannelMask() & (1< +#include +#include +#include +#include +#include + +typedef uint32_t CGDirectDisplayID; +typedef uint32_t CGOpenGLDisplayMask; +typedef double CGRefreshRate; + +//#include +#elif defined(LINUX) +#include "tier0/platform.h" +#include +#include +#else +#error +#endif + +typedef void _PseudoNSGLContext; // aka NSOpenGLContext +typedef _PseudoNSGLContext *PseudoNSGLContextPtr; + +struct GLMDisplayModeInfoFields +{ + uint m_modePixelWidth; + uint m_modePixelHeight; + uint m_modeRefreshHz; + // are we even going to talk about bit depth... not yet +}; + +struct GLMDisplayInfoFields +{ +#ifdef OSX + CGDirectDisplayID m_cgDisplayID; + CGOpenGLDisplayMask m_glDisplayMask; // result of CGDisplayIDToOpenGLDisplayMask on the cg_displayID. +#endif + uint m_displayPixelWidth; + uint m_displayPixelHeight; +}; + +struct GLMRendererInfoFields +{ + /*properties of interest and their desired values. + + kCGLRPFullScreen = 54, true + kCGLRPAccelerated = 73, true + kCGLRPWindow = 80, true + + kCGLRPRendererID = 70, informational + kCGLRPDisplayMask = 84, informational + kCGLRPBufferModes = 100, informational + kCGLRPColorModes = 103, informational + kCGLRPAccumModes = 104, informational + kCGLRPDepthModes = 105, informational + kCGLRPStencilModes = 106, informational + kCGLRPMaxAuxBuffers = 107, informational + kCGLRPMaxSampleBuffers = 108, informational + kCGLRPMaxSamples = 109, informational + kCGLRPSampleModes = 110, informational + kCGLRPSampleAlpha = 111, informational + kCGLRPVideoMemory = 120, informational + kCGLRPTextureMemory = 121, informational + kCGLRPRendererCount = 128 number of renderers in the CGLRendererInfoObj under examination + + kCGLRPOffScreen = 53, D/C + kCGLRPRobust = 75, FALSE or D/C - aka we're asking for no-fallback + kCGLRPBackingStore = 76, D/C + kCGLRPMPSafe = 78, D/C + kCGLRPMultiScreen = 81, D/C + kCGLRPCompliant = 83, D/C + */ + + + //--------------------------- info we have from CGL renderer queries, IOKit, Gestalt + //--------------------------- these are set up in the displayDB by CocoaMgr + GLint m_fullscreen; + GLint m_accelerated; + GLint m_windowed; + + GLint m_rendererID; + GLint m_displayMask; + GLint m_bufferModes; + GLint m_colorModes; + GLint m_accumModes; + GLint m_depthModes; + GLint m_stencilModes; + + GLint m_maxAuxBuffers; + GLint m_maxSampleBuffers; + GLint m_maxSamples; + GLint m_sampleModes; + GLint m_sampleAlpha; + + GLint m_vidMemory; + GLint m_texMemory; + + uint m_pciVendorID; + uint m_pciDeviceID; + char m_pciModelString[64]; + char m_driverInfoString[64]; + + //--------------------------- OS version related - set up by CocoaMgr + + // OS version found + uint m_osComboVersion; // 0x00XXYYZZ : XX major, YY minor, ZZ minor minor : 10.6.3 --> 0x000A0603. 10.5.8 --> 0x000A0508. + + //--------------------------- shorthands - also set up by CocoaMgr - driven by vendorid / deviceid + + bool m_ati; + bool m_atiR5xx; + bool m_atiR6xx; + bool m_atiR7xx; + bool m_atiR8xx; + bool m_atiNewer; + + bool m_intel; + bool m_intel95x; + bool m_intel3100; + bool m_intelNewer; + + bool m_nv; + bool m_nvG7x; + bool m_nvG8x; + bool m_nvNewer; + + //--------------------------- context query results - left blank in the display DB - but valid in a GLMContext (call ctx->Caps() to get a const ref) + + // booleans + bool m_hasGammaWrites; // aka glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT) / glEnable(GL_FRAMEBUFFER_SRGB_EXT) + bool m_hasMixedAttachmentSizes; // aka ARB_fbo in 10.6.3 - test for min OS vers, then exported ext string + bool m_hasBGRA; // aka GL_BGRA vertex attribs in 10.6.3 - - test for min OS vers, then exported ext string + bool m_hasNewFullscreenMode; // aka 10.6.x "big window" fullscreen mode + bool m_hasNativeClipVertexMode; // aka GLSL gl_ClipVertex does not fall back to SW- OS version and folklore-based + bool m_hasOcclusionQuery; // occlusion query: do you speak it ?! + bool m_hasFramebufferBlit; // framebuffer blit: know what I'm sayin?! + bool m_hasPerfPackage1; // means new MTGL, fast OQ, fast uniform upload, NV can resolve flipped (late summer 2010 post 10.6.4 update) + + // counts + int m_maxAniso; // aniso limit - context query + + // other exts + bool m_hasBindableUniforms; + bool m_hasUniformBuffers; + + // runtime options that aren't negotiable once set + bool m_hasDualShaders; // must supply CLI arg "-glmdualshaders" or we go GLSL only + + //--------------------------- " can'ts " - specific problems that need to be worked around + + bool m_cantBlitReliably; // Intel chipsets have problems blitting sRGB sometimes + bool m_cantAttachSRGB; // NV G8x on 10.5.8 can't have srgb tex on FBO color - separate issue from hasGammaWrites + bool m_cantResolveFlipped; // happens on NV in 10.6.4 and prior - console variable "gl_can_resolve_flipped" can overrule + bool m_cantResolveScaled; // happens everywhere per GL spec but may be relaxed some day - console variable "gl_can_resolve_scaled" can overrule + bool m_costlyGammaFlips; // this means that sRGB sampling state affects shader code gen, resulting in state-dependent code regen + + + //--------------------------- " bads " - known bad drivers + bool m_badDriver1064NV; // this is the bad NVIDIA driver on 10.6.4 - stutter, tex corruption, black screen issues +}; + + + +#endif diff --git a/sp/src/public/togl/osx/glmdisplaydb.h b/sp/src/public/togl/osx/glmdisplaydb.h new file mode 100644 index 00000000..4588aff3 --- /dev/null +++ b/sp/src/public/togl/osx/glmdisplaydb.h @@ -0,0 +1,115 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef GLMDISPLAYDB_H +#define GLMDISPLAYDB_H + +#include "tier1/utlvector.h" + +//=============================================================================== + +// modes, displays, and renderers +// think of renderers as being at the top of a tree. +// each renderer has displays hanging off of it. +// each display has modes hanging off of it. +// the tree is populated on demand and then queried as needed. + +//=============================================================================== + +// GLMDisplayModeInfoFields is in glmdisplay.h + +class GLMDisplayMode +{ +public: + GLMDisplayModeInfoFields m_info; + + GLMDisplayMode( uint width, uint height, uint refreshHz ); + GLMDisplayMode() { }; + ~GLMDisplayMode( void ); + + + void Init( uint width, uint height, uint refreshHz ); + void Dump( int which ); +}; + +//=============================================================================== + +// GLMDisplayInfoFields is in glmdisplay.h + +class GLMDisplayInfo +{ +public: + GLMDisplayInfoFields m_info; + CUtlVector< GLMDisplayMode* > *m_modes; // starts out NULL, set by PopulateModes + + GLMDisplayInfo( void ); + ~GLMDisplayInfo( void ); + + void PopulateModes( void ); + + void Dump( int which ); +}; + +//=============================================================================== + +// GLMRendererInfoFields is in glmdisplay.h + +class GLMRendererInfo +{ +public: + GLMRendererInfoFields m_info; + GLMDisplayInfo *m_display; // starts out NULL, set by PopulateDisplays + + GLMRendererInfo ( GLMRendererInfoFields *info ); + ~GLMRendererInfo ( void ); + + void PopulateDisplays(); + void Dump( int which ); +}; + +//=============================================================================== + +// this is just a tuple describing fake adapters which are really renderer/display pairings. +// dxabstract bridges the gap between the d3d adapter-centric world and the GL renderer+display world. +// this makes it straightforward to handle cases like two video cards with two displays on one, and one on the other - +// you get three fake adapters which represent each useful screen. + +// the constraint that dxa will have to follow though, is that if the user wants to change their +// display selection for full screen, they would only be able to pick on that has the same underlying renderer. +// can't change fakeAdapter from one to another with different GL renderer under it. Screen hop but no card hop. + +struct GLMFakeAdapter +{ + int m_rendererIndex; + int m_displayIndex; +}; + +class GLMDisplayDB +{ +public: + CUtlVector< GLMRendererInfo* > *m_renderers; // starts out NULL, set by PopulateRenderers + + CUtlVector< GLMFakeAdapter > m_fakeAdapters; + + GLMDisplayDB ( void ); + ~GLMDisplayDB ( void ); + + virtual void PopulateRenderers( void ); + virtual void PopulateFakeAdapters( uint realRendererIndex ); // fake adapters = one real adapter times however many displays are on it + virtual void Populate( void ); + + // The info-get functions return false on success. + virtual int GetFakeAdapterCount( void ); + virtual bool GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut ); + + virtual int GetRendererCount( void ); + virtual bool GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut ); + + virtual int GetDisplayCount( int rendererIndex ); + virtual bool GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut ); + + virtual int GetModeCount( int rendererIndex, int displayIndex ); + virtual bool GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut ); + + virtual void Dump( void ); +}; + +#endif // GLMDISPLAYDB_H diff --git a/sp/src/public/togl/osx/glmgr.h b/sp/src/public/togl/osx/glmgr.h new file mode 100644 index 00000000..1e951ca9 --- /dev/null +++ b/sp/src/public/togl/osx/glmgr.h @@ -0,0 +1,1088 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgr.h +// singleton class, common basis for managing GL contexts +// responsible for tracking adapters and contexts +// +//=============================================================================== + +#ifndef GLMGR_H +#define GLMGR_H + +#pragma once + +#undef HAVE_GL_ARB_SYNC +#ifdef LINUX +#define HAVE_GL_ARB_SYNC 1 +#endif + +#include "glentrypoints.h" +#include "glmdebug.h" +#include "glmdisplay.h" +#include "glmgrext.h" +#include "glmgrbasics.h" +#include "cglmtex.h" +#include "cglmfbo.h" +#include "cglmprogram.h" +#include "cglmbuffer.h" +#include "cglmquery.h" + +#include "tier0/vprof_telemetry.h" +#include "materialsystem/ishader.h" +#include "dxabstract_types.h" + + +#ifdef LINUX +#define Debugger DebuggerBreak +#undef CurrentTime + +// prevent some conflicts in SDL headers... +#undef M_PI +#include +#ifndef _STDINT_H_ +#define _STDINT_H_ 1 +#endif + +#include "SDL/SDL.h" +#endif + +//=============================================================================== +// glue to call out to Obj-C land (these are in glmgrcocoa.mm) +#ifdef OSX +PseudoNSGLContextPtr GetCurrentNSGLContext( ); +CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx ); +#endif + +#include "tier0/dynfunction.h" + +//=============================================================================== + +// parrot the D3D present parameters, more or less... "adapter" translates into "active display index" per the m_activeDisplayCount below. +class GLMDisplayParams +{ + public: + + // presumption, these indices are in sync with the current display DB that GLMgr has handy + //int m_rendererIndex; // index of renderer (-1 if root context) + //int m_displayIndex; // index of display in renderer - for FS + //int m_modeIndex; // index of mode in display - for FS + + void *m_focusWindow; // (VD3DHWND aka WindowRef) - what window does this context display into + + bool m_fsEnable; // fullscreen on or not + bool m_vsyncEnable; // vsync on or not + + // height and width have to match the display mode info if full screen. + + uint m_backBufferWidth; // pixel width (aka screen h-resolution if full screen) + uint m_backBufferHeight; // pixel height (aka screen v-resolution if full screen) + D3DFORMAT m_backBufferFormat; // pixel format + uint m_multiSampleCount; // 0 means no MSAA, 2 means 2x MSAA, etc + // uint m_multiSampleQuality; // no MSAA quality control yet + + bool m_enableAutoDepthStencil; // generally set to 'TRUE' per CShaderDeviceDx8::SetPresentParameters + D3DFORMAT m_autoDepthStencilFormat; + + uint m_fsRefreshHz; // if full screen, this refresh rate (likely 0 for LCD's) + + //uint m_rootRendererID; // only used if m_rendererIndex is -1. + //uint m_rootDisplayMask; // only used if m_rendererIndex is -1. + + bool m_mtgl; // enable multi threaded GL driver +}; + +//=============================================================================== + +class GLMgr +{ +public: + + //=========================================================================== + // class methods - singleton + static void NewGLMgr( void ); // instantiate singleton.. + static GLMgr *aGLMgr( void ); // return singleton.. + static void DelGLMgr( void ); // tear down singleton.. + + //=========================================================================== + // plain methods + + #if 0 // turned all these off while new approach is coded + void RefreshDisplayDB( void ); // blow away old display DB, make a new one + GLMDisplayDB *GetDisplayDB( void ); // get a ptr to the one GLMgr keeps. only valid til next refresh. + + // eligible renderers will be ranked by desirability starting at index 0 within the db + // within each renderer, eligible displays will be ranked some kind of desirability (area? dist from menu bar?) + // within each display, eligible modes will be ranked by descending areas + + // calls supplying indices are implicitly making reference to the current DB + bool CaptureDisplay( int rendIndex, int displayIndex, bool captureAll ); // capture one display or all displays + void ReleaseDisplays( void ); // release all captures + + int GetDisplayMode( int rendIndex, int displayIndex ); // retrieve current display res (returns modeIndex) + void SetDisplayMode( GLMDisplayParams *params ); // set the display res (only useful for FS) + #endif + + GLMContext *NewContext( GLMDisplayParams *params ); // this will have to change + void DelContext( GLMContext *context ); + + // with usage of CGLMacro.h we could dispense with the "current context" thing + // and just declare a member variable of GLMContext, allowing each glXXX call to be routed directly + // to the correct context + void SetCurrentContext( GLMContext *context ); // make current in calling thread only + GLMContext *GetCurrentContext( void ); + +protected: + friend class GLMContext; + + GLMgr(); + ~GLMgr(); +}; + + +//===========================================================================// + +// helper function to do enable or disable in one step +inline void glSetEnable( GLenum which, bool enable ) +{ + if (enable) + gGL->glEnable(which); + else + gGL->glDisable(which); +} + +// helper function for int vs enum clarity +inline void glGetEnumv( GLenum which, GLenum *dst ) +{ + gGL->glGetIntegerv( which, (int*)dst ); +} + +//===========================================================================// +// +// types to support the GLMContext +// +//===========================================================================// + +// Each state set/get path we are providing caching for, needs its own struct and a comparison operator. +// we also provide an enum of how many such types there are, handy for building dirty masks etc. + +// shorthand macros +#define EQ(fff) ( (src.fff) == (fff) ) + +//rasterizer +struct GLAlphaTestEnable_t { GLint enable; bool operator==(const GLAlphaTestEnable_t& src) const { return EQ(enable); } }; +struct GLAlphaTestFunc_t { GLenum func; GLclampf ref; bool operator==(const GLAlphaTestFunc_t& src) const { return EQ(func) && EQ(ref); } }; +struct GLCullFaceEnable_t { GLint enable; bool operator==(const GLCullFaceEnable_t& src) const { return EQ(enable); } }; +struct GLCullFrontFace_t { GLenum value; bool operator==(const GLCullFrontFace_t& src) const { return EQ(value); } }; +struct GLPolygonMode_t { GLenum values[2]; bool operator==(const GLPolygonMode_t& src) const { return EQ(values[0]) && EQ(values[1]); } }; +struct GLDepthBias_t { GLfloat factor; GLfloat units; bool operator==(const GLDepthBias_t& src) const { return EQ(factor) && EQ(units); } }; +struct GLScissorEnable_t { GLint enable; bool operator==(const GLScissorEnable_t& src) const { return EQ(enable); } }; +struct GLScissorBox_t { GLint x,y; GLsizei width, height; bool operator==(const GLScissorBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; +struct GLAlphaToCoverageEnable_t{ GLint enable; bool operator==(const GLAlphaToCoverageEnable_t& src) const { return EQ(enable); } }; +struct GLViewportBox_t { GLint x,y; GLsizei width, height; bool operator==(const GLViewportBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; +struct GLViewportDepthRange_t { GLdouble near,far; bool operator==(const GLViewportDepthRange_t& src) const { return EQ(near) && EQ(far); } }; +struct GLClipPlaneEnable_t { GLint enable; bool operator==(const GLClipPlaneEnable_t& src) const { return EQ(enable); } }; +struct GLClipPlaneEquation_t { GLfloat x,y,z,w; bool operator==(const GLClipPlaneEquation_t& src) const { return EQ(x) && EQ(y) && EQ(z) && EQ(w); } }; + +//blend +struct GLColorMaskSingle_t { char r,g,b,a; bool operator==(const GLColorMaskSingle_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLColorMaskMultiple_t { char r,g,b,a; bool operator==(const GLColorMaskMultiple_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLBlendEnable_t { GLint enable; bool operator==(const GLBlendEnable_t& src) const { return EQ(enable); } }; +struct GLBlendFactor_t { GLenum srcfactor,dstfactor; bool operator==(const GLBlendFactor_t& src) const { return EQ(srcfactor) && EQ(dstfactor); } }; +struct GLBlendEquation_t { GLenum equation; bool operator==(const GLBlendEquation_t& src) const { return EQ(equation); } }; +struct GLBlendColor_t { GLfloat r,g,b,a; bool operator==(const GLBlendColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLBlendEnableSRGB_t { GLint enable; bool operator==(const GLBlendEnableSRGB_t& src) const { return EQ(enable); } }; + +//depth +struct GLDepthTestEnable_t { GLint enable; bool operator==(const GLDepthTestEnable_t& src) const { return EQ(enable); } }; +struct GLDepthFunc_t { GLenum func; bool operator==(const GLDepthFunc_t& src) const { return EQ(func); } }; +struct GLDepthMask_t { char mask; bool operator==(const GLDepthMask_t& src) const { return EQ(mask); } }; + +//stencil +struct GLStencilTestEnable_t { GLint enable; bool operator==(const GLStencilTestEnable_t& src) const { return EQ(enable); } }; +struct GLStencilFunc_t { GLenum frontfunc, backfunc; GLint ref; GLuint mask; bool operator==(const GLStencilFunc_t& src) const { return EQ(frontfunc) && EQ(backfunc) && EQ(ref) && EQ(mask); } }; +struct GLStencilOp_t { GLenum sfail; GLenum dpfail; GLenum dppass; bool operator==(const GLStencilOp_t& src) const { return EQ(sfail) && EQ(dpfail) && EQ(dppass); } }; +struct GLStencilWriteMask_t { GLint mask; bool operator==(const GLStencilWriteMask_t& src) const { return EQ(mask); } }; + +//clearing +struct GLClearColor_t { GLfloat r,g,b,a; bool operator==(const GLClearColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; +struct GLClearDepth_t { GLdouble d; bool operator==(const GLClearDepth_t& src) const { return EQ(d); } }; +struct GLClearStencil_t { GLint s; bool operator==(const GLClearStencil_t& src) const { return EQ(s); } }; + +#undef EQ + +enum EGLMStateBlockType +{ + kGLAlphaTestEnable, + kGLAlphaTestFunc, + + kGLCullFaceEnable, + kGLCullFrontFace, + + kGLPolygonMode, + + kGLDepthBias, + + kGLScissorEnable, + kGLScissorBox, + + kGLViewportBox, + kGLViewportDepthRange, + + kGLClipPlaneEnable, + kGLClipPlaneEquation, + + kGLColorMaskSingle, + kGLColorMaskMultiple, + + kGLBlendEnable, + kGLBlendFactor, + kGLBlendEquation, + kGLBlendColor, + kGLBlendEnableSRGB, + + kGLDepthTestEnable, + kGLDepthFunc, + kGLDepthMask, + + kGLStencilTestEnable, + kGLStencilFunc, + kGLStencilOp, + kGLStencilWriteMask, + + kGLClearColor, + kGLClearDepth, + kGLClearStencil, + + kGLAlphaToCoverageEnable, + + kGLMStateBlockLimit +}; + +//===========================================================================// + +// templated functions representing GL R/W bottlenecks +// one set of set/get/getdefault is instantiated for each of the GL*** types above. + +// use these from the non array state objects +template void GLContextSet( T *src ); +template void GLContextGet( T *dst ); +template void GLContextGetDefault( T *dst ); + +// use these from the array state objects +template void GLContextSetIndexed( T *src, int index ); +template void GLContextGetIndexed( T *dst, int index ); +template void GLContextGetDefaultIndexed( T *dst, int index ); + +//===========================================================================// + +// caching state object template. One of these is instantiated in the context per unique struct type above +template class GLState +{ + public: + + GLState() + { + dirty = false; + memset( &data, 0, sizeof(data) ); + }; + + // write: client src into cache + // common case is both false. dirty is calculated, context write is deferred. + void Write( T *src, bool noCompare=false, bool noDefer=false ) + { + if (noCompare) + { + dirty = true; + } + else + { + // only == is implemented, so test for equal and negate + // note, you only set dirty if mismatch, you never clear it until flush + if ( !(data == *src) ) + { + dirty = true; + } + } + + data = *src; + + if (noDefer) + { + Flush( true ); // dirty becomes false + } + }; + + // write cache->context if dirty or forced. + void Flush( bool noDefer=false ) + { + if (dirty || noDefer) + { + GLContextSet( &data ); + GLMCheckError(); + // good place for some error checking here + dirty = false; + } + }; + + // default: write default value to cache, optionally write through + void Default( bool noDefer=false ) + { + GLContextGetDefault( &data ); // read default values directly to our cache copy + dirty = true; + Flush(noDefer); + }; + + // read: sel = 0 for cache, 1 for context + void Read( T *dst, int sel ) + { + if (sel==0) + { + *dst = data; + } + else + { + GLContextGet( dst ); + GLMCheckError(); + } + }; + + // check: verify that context equals cache, return true if mismatched or if illegal values seen + bool Check ( void ) + { + T temp; + bool result; + + GLContextGet( &temp ); + GLMCheckError(); + result = !(temp == data); + return result; + }; + + protected: + T data; + bool dirty; +}; + +// caching state object template - with multiple values behind it that are indexed +template class GLStateArray +{ + public: + + GLStateArray() + { + memset( &dirty, 0, sizeof(dirty) ); + memset( &data, 0, sizeof(data) ); + }; + + // write: client src into cache + // common case is both false. dirty is calculated, context write is deferred. + void WriteIndex( T *src, int index, bool noCompare=false, bool noDefer=false ) + { + if (noCompare) + { + dirty[index] = true; + } + else + { + // only == is implemented, so test for equal and negate + // note, you only set dirty if mismatch, you never clear it until flush + if (! (data[index] == *src) ) + { + dirty[index] = true; + } + } + + data[index] = *src; + + if (noDefer) + { + FlushIndex( index, true ); // dirty becomes false + } + }; + + // write cache->context if dirty or forced. + void FlushIndex( int index, bool noDefer=false ) + { + if (dirty[index] || noDefer) + { + GLContextSetIndexed( &data[index], index ); + GLMCheckError(); + dirty[index] = false; + } + }; + + // write all slots in the array + void Flush( bool noDefer=false ) + { + for( int i=0; i m_AlphaTestEnable; + + GLState m_AlphaTestFunc; + + GLState m_CullFaceEnable; + GLState m_CullFrontFace; + GLState m_PolygonMode; + + GLState m_DepthBias; + + GLStateArray m_ClipPlaneEnable; + GLStateArray m_ClipPlaneEquation; // dxabstract puts them directly into param slot 253(0) and 254(1) + + GLState m_ScissorEnable; + GLState m_ScissorBox; + + GLState m_AlphaToCoverageEnable; + + GLState m_ViewportBox; + GLState m_ViewportDepthRange; + + GLState m_ColorMaskSingle; + GLStateArray m_ColorMaskMultiple; // need an official constant for the color buffers limit + + GLState m_BlendEnable; + GLState m_BlendFactor; + GLState m_BlendEquation; + GLState m_BlendColor; + GLState m_BlendEnableSRGB; // write to this one to transmit intent to write SRGB encoded pixels to drawing FB + bool m_FakeBlendEnableSRGB; // writes to above will be shunted here if fake SRGB is in effect. + + GLState m_DepthTestEnable; + GLState m_DepthFunc; + GLState m_DepthMask; + + GLState m_StencilTestEnable; // global stencil test enable + GLState m_StencilFunc; // holds front and back stencil funcs + GLStateArray m_StencilOp; // indexed: 0=front 1=back + GLState m_StencilWriteMask; + + GLState m_ClearColor; + GLState m_ClearDepth; + GLState m_ClearStencil; + + // texture bindings and sampler setup + int m_activeTexture; // mirror for glActiveTexture + GLMTexSampler m_samplers[GLM_SAMPLER_COUNT]; + + // texture lock tracking - CGLMTex objects share usage of this + CUtlVector< GLMTexLockDesc > m_texLocks; + + // render target binding - check before draw + // similar to tex sampler mechanism, we track "bound" from "chosen for drawing" separately, + // so binding for creation/setup need not disrupt any notion of what will be used at draw time + + CGLMFBO *m_boundDrawFBO; // FBO on GL_DRAW_FRAMEBUFFER bind point + CGLMFBO *m_boundReadFBO; // FBO on GL_READ_FRAMEBUFFER bind point + // ^ both are set if you bind to GL_FRAMEBUFFER_EXT + + CGLMFBO *m_drawingFBO; // what FBO should be bound at draw time (to both read/draw bp's). + + CGLMFBO *m_blitReadFBO; + CGLMFBO *m_blitDrawFBO; // scratch FBO's for framebuffer blit + + CGLMFBO *m_scratchFBO[ kGLMScratchFBOCount ]; // general purpose FBO's for internal use + + CUtlVector< CGLMFBO* > m_fboTable; // each live FBO goes in the table + + // program bindings + EGLMProgramLang m_drawingLangAtFrameStart; // selector for start of frame (spills into m_drawingLang) + EGLMProgramLang m_drawingLang; // selector for which language we desire to draw with on the next batch + CGLMProgram *m_drawingProgram[ kGLMNumProgramTypes ]; + + GLMProgramParamsF m_programParamsF[ kGLMNumProgramTypes ]; + GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + GLMProgramParamsI m_programParamsI[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + EGLMParamWriteMode m_paramWriteMode; + + CGLMProgram *m_nullFragmentProgram; // write opaque black. Activate when caller asks for null FP + + CGLMProgram *m_preloadTexVertexProgram; // programs to help preload textures (dummies) + CGLMProgram *m_preload2DTexFragmentProgram; + CGLMProgram *m_preload3DTexFragmentProgram; + CGLMProgram *m_preloadCubeTexFragmentProgram; + + CGLMProgram *m_boundProgram[ kGLMNumProgramTypes ]; + + CGLMShaderPairCache *m_pairCache; // GLSL only + CGLMShaderPair *m_boundPair; // GLSL only + uint m_boundPairRevision; // GLSL only + GLhandleARB m_boundPairProgram; // GLSL only + + // buffer bindings + CGLMBuffer *m_lastKnownBufferBinds[ kGLMNumBufferTypes ]; // tracked per bind point for dupe-bind-absorb + GLMVertexAttributeDesc m_lastKnownVertexAttribs[ kGLMVertexAttributeIndexMax ]; // tracked per attrib for dupe-set-absorb + uint m_lastKnownVertexAttribMask; // tracked for dupe-enable-absorb + + CGLMBuffer *m_drawIndexBuffer; // ... ? do we need dupe tracking for index buffer setup? ? + + GLMVertexSetup m_drawVertexSetup; + + EGLMAttribWriteMode m_attribWriteMode; + + bool m_slowCheckEnable; // turn this on or no native checking is done ("-glmassertslow" or "-glmsspewslow") + bool m_slowAssertEnable; // turn this on to assert on a non-native batch "-glmassertslow" + bool m_slowSpewEnable; // turn this on to log non-native batches to stdout "-glmspewslow" + + // debug font texture + CGLMTex *m_debugFontTex; // might be NULL unless you call GenDebugFontTex + CGLMBuffer *m_debugFontIndices; // up to 1024 indices (256 chars times 4) + CGLMBuffer *m_debugFontVertices; // up to 1024 verts + + // batch/frame debugging support + int m_debugFrameIndex; // init to -1. Increment at BeginFrame + int m_debugBatchIndex; // init to -1. Increment at any draw call + +#if GLMDEBUG + // interactive (DebugHook) debug support + + // using these you can implement frame advance, batch single step, and batch rewind (let it run til next frame and hold on prev batch #) + int m_holdFrameBegin; // -1 if no hold req'd, otherwise # of frame to hold at (at beginframe time) + int m_holdFrameEnd; // -1 if no hold req'd, otherwise # of frame to hold at (at endframe time) + + int m_holdBatch,m_holdBatchFrame; // -1 if no hold, else # of batch&frame to hold at (both must be set) + // these can be expired/cleared to -1 if the frame passes without a hit + // may be desirable to re-pause in that event, as user was expecting a hold to occur + + bool m_debugDelayEnable; // allow sleep delay + uint m_debugDelay; // sleep time per hook call in microseconds (for usleep()) + + // pre-draw global toggles / options + bool m_autoClearColor,m_autoClearDepth,m_autoClearStencil; + float m_autoClearColorValues[4]; + + // debug knobs + int m_selKnobIndex; + float m_selKnobMinValue,m_selKnobMaxValue,m_selKnobIncrement; +#endif + +}; + +struct GLMTestParams +{ + GLMContext *m_ctx; + int *m_testList; // -1 termed + + bool m_glErrToDebugger; + bool m_glErrToConsole; + + bool m_intlErrToDebugger; + bool m_intlErrToConsole; + + int m_frameCount; // how many frames to test. +}; + +class GLMTester +{ + public: + + GLMTester(GLMTestParams *params); + ~GLMTester(); + + + // optionally callable by test routines to get basic drawables wired up + void StdSetup( void ); + void StdCleanup( void ); + + // callable by test routines to clear the frame or present it + void Clear( void ); + void Present( int seed ); + + // error reporting + void CheckGLError( char *comment ); // obey m_params setting for console / debugger response + void InternalError( int errcode, char *comment ); // if errcode!=0, obey m_params setting for console / debugger response + + void RunTests(); + + void RunOneTest( int testindex ); + + // test routines themselves + void Test0(); + void Test1(); + void Test2(); + void Test3(); + + GLMTestParams m_params; // copy of caller's params, do not mutate... + + // std-setup stuff + int m_drawWidth, m_drawHeight; + CGLMFBO *m_drawFBO; + CGLMTex *m_drawColorTex; + CGLMTex *m_drawDepthTex; +}; + +class CShowPixelsParams +{ +public: + GLuint m_srcTexName; + int m_width,m_height; + bool m_vsyncEnable; + bool m_fsEnable; // want receiving view to be full screen. for now, just target the main screen. extend later. + bool m_useBlit; // use FBO blit - sending context says it is available. + bool m_noBlit; // the back buffer has already been populated by the caller (perhaps via direct MSAA resolve from multisampled RT tex) + bool m_onlySyncView; // react to full/windowed state change only, do not present bits +}; + + +#define kMaxCrawlFrames 100 +#define kMaxCrawlText (kMaxCrawlFrames * 256) +class CStackCrawlParams +{ + public: + uint m_frameLimit; // input: max frames to retrieve + uint m_frameCount; // output: frames found + void *m_crawl[kMaxCrawlFrames]; // call site addresses + char *m_crawlNames[kMaxCrawlFrames]; // pointers into text following, one per decoded name + char m_crawlText[kMaxCrawlText]; +}; + +#endif diff --git a/sp/src/public/togl/osx/glmgrbasics.h b/sp/src/public/togl/osx/glmgrbasics.h new file mode 100644 index 00000000..559bc10f --- /dev/null +++ b/sp/src/public/togl/osx/glmgrbasics.h @@ -0,0 +1,299 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgrbasics.h +// types, common headers, forward declarations, utilities +// +//=============================================================================== + +#ifndef GLMBASICS_H +#define GLMBASICS_H + +#pragma once + +#ifdef OSX +#include +#include +#include +#include +#include +#include +#include +//#include +#elif defined(LINUX) +#include +#include +#else +#error +#endif + +#include "tier0/platform.h" + +#include "bitmap/imageformat.h" +#include "bitvec.h" +#include "tier1/checksum_md5.h" +#include "tier1/utlvector.h" +#include "tier1/convar.h" + +#include + +#include "dxabstract_types.h" + +// types +struct GLMRect; +typedef void *PseudoGLContextPtr; + + + // 3-d integer box (used for texture lock/unlock etc) +struct GLMRegion +{ + int xmin,xmax; + int ymin,ymax; + int zmin,zmax; +}; + +struct GLMRect // follows GL convention - if coming from the D3D rect you will need to fiddle the Y's +{ + int xmin; // left + int ymin; // bottom + int xmax; // right + int ymax; // top +}; + +// macros + +//#define GLMassert(x) assert(x) + +// forward decls +class GLMgr; // singleton +class GLMContext; // GL context +class CGLMContextTester; // testing class +class CGLMTex; +class CGLMFBO; +class CGLMProgram; +class CGLMBuffer; + + +// utilities + +typedef enum +{ + // D3D codes + eD3D_DEVTYPE, + eD3D_FORMAT, + eD3D_RTYPE, + eD3D_USAGE, + eD3D_RSTATE, // render state + eD3D_SIO, // D3D shader bytecode + eD3D_VTXDECLUSAGE, + + // CGL codes + eCGL_RENDID, + + // OpenGL error codes + eGL_ERROR, + + // OpenGL enums + eGL_ENUM, + eGL_RENDERER + +} GLMThing_t; + +const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const +const char* GLMDecodeMask( GLMThing_t type, unsigned long value ); // decode a bitmask + +void GLMStop( void ); // aka Debugger() +void GLMCheckError( bool noStop = false, bool noLog= false ); +void GLMEnableTrace( bool on ); + +// expose these in release now +// Mimic PIX events so we can decorate debug spew +void GLMBeginPIXEvent( const char *str ); +void GLMEndPIXEvent( void ); + +//=============================================================================== +// knob twiddling +float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value +float GLMKnobToggle( char *knobname ); + +//=============================================================================== +// other stuff + +// helpers for CGLSetOption - no op if no profiler +void GLMProfilerClearTrace( void ); +void GLMProfilerEnableTrace( bool enable ); + +// helpers for CGLSetParameter - no op if no profiler +void GLMProfilerDumpState( void ); + + +//=============================================================================== +// classes + +// helper class making function tracking easier to wire up +#if GLMDEBUG +class GLMFuncLogger +{ + public: + + // simple function log + GLMFuncLogger( const char *funcName ) + { + m_funcName = funcName; + m_earlyOut = false; + + GLMPrintf( ">%s", m_funcName ); + }; + + // more advanced version lets you pass args (i.e. called parameters or anything else of interest) + // no macro for this one, since no easy way to pass through the args as well as the funcname + GLMFuncLogger( const char *funcName, char *fmt, ... ) + { + m_funcName = funcName; + m_earlyOut = false; + + // this acts like GLMPrintf here + // all the indent policy is down in GLMPrintfVA + // which means we need to inject a ">" at the front of the format string to make this work... sigh. + + char modifiedFmt[2000]; + modifiedFmt[0] = '>'; + strcpy( modifiedFmt+1, fmt ); + + va_list vargs; + va_start(vargs, fmt); + GLMPrintfVA( modifiedFmt, vargs ); + va_end( vargs ); + } + + ~GLMFuncLogger( ) + { + if (m_earlyOut) + { + GLMPrintf( "<%s (early out)", m_funcName ); + } + else + { + GLMPrintf( "<%s", m_funcName ); + } + }; + + void EarlyOut( void ) + { + m_earlyOut = true; + }; + + const char *m_funcName; // set at construction time + bool m_earlyOut; +}; + +// handy macro to go with the function tracking class +#define GLM_FUNC GLMFuncLogger _logger_ ( __FUNCTION__ ) +#else +#define GLM_FUNC +#endif + + +// class to keep an in-memory mirror of a file which may be getting edited during run +class CGLMFileMirror +{ +public: + CGLMFileMirror( char *fullpath ); // just associates mirror with file. if file exists it will be read. + //if non existent it will be created with size zero + ~CGLMFileMirror( ); + + bool HasData( void ); // see if data avail + void GetData( char **dataPtr, uint *dataSizePtr ); // read it out + void SetData( char *data, uint dataSize ); // put data in (and write it to disk) + bool PollForChanges( void ); // check disk copy. If different, read it back in and return true. + + void UpdateStatInfo( void ); // make sure stat info is current for our file + void ReadFile( void ); + void WriteFile( void ); + + void OpenInEditor( bool foreground=false ); // pass TRUE if you would like the editor to pop to foreground + + /// how about a "wait for change" method.. + + char *m_path; // fullpath to file + bool m_exists; + struct stat m_stat; // stat results for the file (last time checked) + + char *m_data; // content of file + uint m_size; // length of content + +}; + +// class based on the file mirror, that makes it easy to edit them outside the app. + +// it receives an initial block of text from the engine, and hashes it. ("orig") +// it munges it by duplicating all the text after the "!!" line, and appending it in commented form. ("munged") +// a mirror file is activated, using a filename based on the hash from the orig text. +// if there is already content on disk matching that filename, use that content *unless* the 'blitz' parameter is set. +// (i.e. engine is instructing this subsystem to wipe out any old/modified variants of the text) + + +class CGLMEditableTextItem +{ +public: + CGLMEditableTextItem( char *text, uint size, bool forceOverwrite, char *prefix, char *suffix = NULL ); // create a text blob from text source, optional filename suffix + ~CGLMEditableTextItem( ); + + bool HasData( void ); + bool PollForChanges( void ); // return true if stale i.e. you need to get a new edition + void GetCurrentText( char **textOut, uint *sizeOut ); // query for read access to the active blob (could be the original, could be external edited copy) + void OpenInEditor( bool foreground=false ); // call user attention to this text + + // internal methods + void GenHashOfOrigText( void ); + void GenBaseNameAndFullPath( char *prefix, char *suffix ); + void GenMungedText( bool fromMirror ); + + // members + // orig + uint m_origSize; + char *m_origText; // what was submitted + unsigned char m_origDigest[MD5_DIGEST_LENGTH]; // digest of what was submitted + + // munged + uint m_mungedSize; + char *m_mungedText; // re-processed edition, initial content submission to the file mirror + + // mirror + char *m_mirrorBaseName; // generated from the hash of the orig text, plus the label / prefix + char *m_mirrorFullPath; // base name + CGLMFileMirror *m_mirror; // file mirror itself. holds "official" copy for GetCurrentText to return. +}; + + +// debug font +extern unsigned char g_glmDebugFontMap[16384]; + +// class for cracking multi-part text blobs +// sections are demarcated by beginning-of-line markers submitted in a table by the caller + +struct GLMTextSection +{ + int m_markerIndex; // based on table of markers passed in to constructor + uint m_textOffset; // where is the text - offset + int m_textLength; // how big is the section +}; + +class CGLMTextSectioner +{ +public: + CGLMTextSectioner( char *text, int textSize, char **markers ); // constructor finds all the sections + ~CGLMTextSectioner( ); + + int Count( void ); // how many sections found + void GetSection( int index, uint *offsetOut, uint *lengthOut, int *markerIndexOut ); + // find section, size, what marker + // note that more than one section can be marked similarly. + // so policy isn't made here, you walk the sections and decide what to do if there are dupes. + + //members + + //section table + CUtlVector< GLMTextSection > m_sectionTable; +}; + +#endif diff --git a/sp/src/public/togl/osx/glmgrext.h b/sp/src/public/togl/osx/glmgrext.h new file mode 100644 index 00000000..1fc4edce --- /dev/null +++ b/sp/src/public/togl/osx/glmgrext.h @@ -0,0 +1,93 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// glmgrext.h +// helper file for extension testing and runtime importing of entry points +// +//=============================================================================== + +#pragma once + +#ifdef OSX +#include +#include +#elif defined(LINUX) +#include +#include +#else +#error +#endif + +#ifndef GL_EXT_framebuffer_sRGB + #define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 + #define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif + +#ifndef ARB_texture_rg + #define GL_COMPRESSED_RED 0x8225 + #define GL_COMPRESSED_RG 0x8226 + #define GL_RG 0x8227 + #define GL_RG_INTEGER 0x8228 + #define GL_R8 0x8229 + #define GL_R16 0x822A + #define GL_RG8 0x822B + #define GL_RG16 0x822C + #define GL_R16F 0x822D + #define GL_R32F 0x822E + #define GL_RG16F 0x822F + #define GL_RG32F 0x8230 + #define GL_R8I 0x8231 + #define GL_R8UI 0x8232 + #define GL_R16I 0x8233 + #define GL_R16UI 0x8234 + #define GL_R32I 0x8235 + #define GL_R32UI 0x8236 + #define GL_RG8I 0x8237 + #define GL_RG8UI 0x8238 + #define GL_RG16I 0x8239 + #define GL_RG16UI 0x823A + #define GL_RG32I 0x823B + #define GL_RG32UI 0x823C +#endif + +#ifndef GL_EXT_bindable_uniform + #define GL_UNIFORM_BUFFER_EXT 0x8DEE +#endif + +// unpublished extension enums (thus the "X") + +// from EXT_framebuffer_multisample_blit_scaled.. +#define XGL_SCALED_RESOLVE_FASTEST_EXT 0x90BA +#define XGL_SCALED_RESOLVE_NICEST_EXT 0x90BB + +#ifndef GL_TEXTURE_MINIMIZE_STORAGE_APPLE +#define GL_TEXTURE_MINIMIZE_STORAGE_APPLE 0x85B6 +#endif + +#ifndef GL_ALL_COMPLETED_NV +#define GL_ALL_COMPLETED_NV 0x84F2 +#endif + +#ifndef GL_MAP_READ_BIT +#define GL_MAP_READ_BIT 0x0001 +#endif + +#ifndef GL_MAP_WRITE_BIT +#define GL_MAP_WRITE_BIT 0x0002 +#endif + +#ifndef GL_MAP_INVALIDATE_RANGE_BIT +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#endif + +#ifndef GL_MAP_INVALIDATE_BUFFER_BIT +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#endif + +#ifndef GL_MAP_FLUSH_EXPLICIT_BIT +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#endif + +#ifndef GL_MAP_UNSYNCHRONIZED_BIT +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#endif + diff --git a/sp/src/public/togl/rendermechanism.h b/sp/src/public/togl/rendermechanism.h new file mode 100644 index 00000000..b409c4ac --- /dev/null +++ b/sp/src/public/togl/rendermechanism.h @@ -0,0 +1,70 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef RENDERMECHANISM_H +#define RENDERMECHANISM_H + +#if defined(DX_TO_GL_ABSTRACTION) + +#undef PROTECTED_THINGS_ENABLE + +#include +#include +#include "tier0/basetypes.h" +#include "tier0/platform.h" + +#if defined(LINUX) || defined(_WIN32) + +#include "togl/linuxwin/glmdebug.h" +#include "togl/linuxwin/glbase.h" +#include "togl/linuxwin/glentrypoints.h" +#include "togl/linuxwin/glmdisplay.h" +#include "togl/linuxwin/glmdisplaydb.h" +#include "togl/linuxwin/glmgrbasics.h" +#include "togl/linuxwin/glmgrext.h" +#include "togl/linuxwin/cglmbuffer.h" +#include "togl/linuxwin/cglmtex.h" +#include "togl/linuxwin/cglmfbo.h" +#include "togl/linuxwin/cglmprogram.h" +#include "togl/linuxwin/cglmquery.h" +#include "togl/linuxwin/glmgr.h" +#include "togl/linuxwin/dxabstract_types.h" +#include "togl/linuxwin/dxabstract.h" + +#elif defined(OSX) +#include "togl/osx/glmdebug.h" +//#include "togl/osx/glbase.h" +#include "togl/osx/glentrypoints.h" +#include "togl/osx/glmdisplay.h" +#include "togl/osx/glmdisplaydb.h" +#include "togl/osx/glmgrbasics.h" +#include "togl/osx/glmgrext.h" +#include "togl/osx/cglmbuffer.h" +#include "togl/osx/cglmtex.h" +#include "togl/osx/cglmfbo.h" +#include "togl/osx/cglmprogram.h" +#include "togl/osx/cglmquery.h" +#include "togl/osx/glmgr.h" +#include "togl/osx/dxabstract_types.h" +#include "togl/osx/dxabstract.h" + +#endif + +#else + //USE_ACTUAL_DX + #ifdef WIN32 + #ifdef _X360 + #include "d3d9.h" + #include "d3dx9.h" + #else + #include + #include "../../dx9sdk/include/d3d9.h" + #include "../../dx9sdk/include/d3dx9.h" + #endif + typedef HWND VD3DHWND; + #endif + + #define GLMPRINTF(args) + #define GLMPRINTSTR(args) + #define GLMPRINTTEXT(args) +#endif // defined(DX_TO_GL_ABSTRACTION) + +#endif // RENDERMECHANISM_H diff --git a/sp/src/public/vgui/IVGui.h b/sp/src/public/vgui/IVGui.h index 06a3ec8c..e512538a 100644 --- a/sp/src/public/vgui/IVGui.h +++ b/sp/src/public/vgui/IVGui.h @@ -95,6 +95,10 @@ public: // data accessor for above virtual bool GetShouldVGuiControlSleep() = 0; + + // enables VR mode + virtual void SetVRMode( bool bVRMode ) = 0; + virtual bool GetVRMode() = 0; }; #define VGUI_IVGUI_INTERFACE_VERSION "VGUI_ivgui008" diff --git a/sp/src/thirdparty/protobuf-2.3.0/install-sh b/sp/src/thirdparty/protobuf-2.3.0/install-sh index 97a459c7..a5897de6 100644 --- a/sp/src/thirdparty/protobuf-2.3.0/install-sh +++ b/sp/src/thirdparty/protobuf-2.3.0/install-sh @@ -1,519 +1,519 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2006-12-25.00 - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - trap '(exit $?); exit' 1 2 13 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dst_arg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writeable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - -*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test -z "$d" && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2006-12-25.00 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sp/src/tier1/lzmaDecoder.cpp b/sp/src/tier1/lzmaDecoder.cpp new file mode 100644 index 00000000..1d7b24a8 --- /dev/null +++ b/sp/src/tier1/lzmaDecoder.cpp @@ -0,0 +1,764 @@ +// +// LZMA Codec. +// +// LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) +// http://www.7-zip.org/ +// +// Modified to use Source platform utilities and memory allocation overrides. +//=====================================================================================// + +#include "tier0/platform.h" +#include "tier0/dbg.h" +#include "tier1/lzmaDecoder.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _LZMA_SYSTEM_SIZE_T */ +/* Use system's size_t. You can use it to enable 64-bit sizes supporting */ + +#ifndef _7ZIP_SIZET_DEFINED +#define _7ZIP_SIZET_DEFINED +#ifdef _LZMA_SYSTEM_SIZE_T +#include +typedef size_t SizeT; +#else +typedef UInt32 SizeT; +#endif +#endif + +/* #define _LZMA_IN_CB */ +/* Use callback for input data */ + +/* #define _LZMA_OUT_READ */ +/* Use read function for output data */ + +#define _LZMA_PROB32 +/* It can increase speed on some 32-bit CPUs, +but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; +#ifdef _LZMA_OUT_READ + UInt32 DictionarySize; +#endif +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + +#ifdef _LZMA_IN_CB + const unsigned char *Buffer; + const unsigned char *BufferLim; +#endif + +#ifdef _LZMA_OUT_READ + unsigned char *Dictionary; + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; + unsigned char TempDictionary[4]; +#endif +} CLzmaDecoderState; + +#ifdef _LZMA_OUT_READ +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } +#endif + +int LzmaDecode(CLzmaDecoderState *vs, +#ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, +#else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, +#endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ +{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + +#ifdef _LZMA_IN_CB + +#define RC_TEST { if (Buffer == BufferLim) \ +{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} + +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 + +#else + +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + +#endif + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ +{ UpdateBit0(p); mi <<= 1; A0; } else \ +{ UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ +{ int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + +#ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } +#endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, +#ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, +#else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, +#endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + +#ifdef _LZMA_OUT_READ + + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; +#ifdef _LZMA_IN_CB + const Byte *Buffer = vs->Buffer; + const Byte *BufferLim = vs->BufferLim; +#else + const Byte *Buffer = inStream; + const Byte *BufferLim = inStream + inSize; +#endif + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + +#ifndef _LZMA_IN_CB + *inSizeProcessed = 0; +#endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; +#ifdef _LZMA_IN_CB + RC_INIT; +#else + RC_INIT(inStream, inSize); +#endif + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + +#else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + +#ifndef _LZMA_IN_CB + *inSizeProcessed = 0; +#endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + +#ifdef _LZMA_IN_CB + RC_INIT; +#else + RC_INIT(inStream, inSize); +#endif + +#endif /* _LZMA_OUT_READ */ + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos +#ifdef _LZMA_OUT_READ + + globalPos +#endif + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos +#ifdef _LZMA_OUT_READ + + globalPos +#endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; +#ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; +#else + matchByte = outStream[nowPos - rep0]; +#endif + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; +#ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; +#endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } +else +{ + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { +#ifdef _LZMA_OUT_READ + UInt32 pos; +#endif + UpdateBit0(prob); + +#ifdef _LZMA_OUT_READ + if (distanceLimit == 0) +#else + if (nowPos == 0) +#endif + return LZMA_RESULT_DATA_ERROR; + + state = state < kNumLitStates ? 9 : 11; +#ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; +#else + previousByte = outStream[nowPos - rep0]; +#endif + outStream[nowPos++] = previousByte; +#ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; +#endif + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; +#ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) +#else + if (rep0 > nowPos) +#endif + return LZMA_RESULT_DATA_ERROR; + +#ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; +#endif + + do + { +#ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; +#else + previousByte = outStream[nowPos - rep0]; +#endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); +} + } + RC_NORMALIZE; + +#ifdef _LZMA_OUT_READ + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; +#endif + +#ifdef _LZMA_IN_CB + vs->Buffer = Buffer; + vs->BufferLim = BufferLim; +#else + *inSizeProcessed = (SizeT)(Buffer - inStream); +#endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} + +//----------------------------------------------------------------------------- +// Returns true if buffer is compressed. +//----------------------------------------------------------------------------- +bool CLZMA::IsCompressed( unsigned char *pInput ) +{ + lzma_header_t *pHeader = (lzma_header_t *)pInput; + if ( pHeader && pHeader->id == LZMA_ID ) + { + return true; + } + + // unrecognized + return false; +} + +//----------------------------------------------------------------------------- +// Returns uncompressed size of compressed input buffer. Used for allocating output +// buffer for decompression. Returns 0 if input buffer is not compressed. +//----------------------------------------------------------------------------- +unsigned int CLZMA::GetActualSize( unsigned char *pInput ) +{ + lzma_header_t *pHeader = (lzma_header_t *)pInput; + if ( pHeader && pHeader->id == LZMA_ID ) + { + return LittleLong( pHeader->actualSize ); + } + + // unrecognized + return 0; +} + +//----------------------------------------------------------------------------- +// Uncompress a buffer, Returns the uncompressed size. Caller must provide an +// adequate sized output buffer or memory corruption will occur. +//----------------------------------------------------------------------------- +unsigned int CLZMA::Uncompress( unsigned char *pInput, unsigned char *pOutput ) +{ + unsigned int actualSize = GetActualSize( pInput ); + if ( !actualSize ) + { + // unrecognized + return 0; + } + + CLzmaDecoderState state; + if ( LzmaDecodeProperties( &state.Properties, ((lzma_header_t *)pInput)->properties, LZMA_PROPERTIES_SIZE ) != LZMA_RESULT_OK ) + { + Assert( 0 ); + } + state.Probs = (CProb *)malloc( LzmaGetNumProbs( &state.Properties ) * sizeof( CProb ) ); + + unsigned int lzmaSize = LittleLong( ((lzma_header_t *)pInput)->lzmaSize ); + + SizeT inProcessed; + SizeT outProcessed; + int result = LzmaDecode( &state, pInput + sizeof( lzma_header_t ), lzmaSize, &inProcessed, pOutput, actualSize, &outProcessed ); + + free( state.Probs ); + + if ( result != LZMA_RESULT_OK || outProcessed != (SizeT)actualSize ) + { + Assert( 0 ); + return 0; + } + + return outProcessed; +} + diff --git a/sp/src/tier1/snappy-stubs-internal.h b/sp/src/tier1/snappy-stubs-internal.h index c585a2e6..f75fd482 100644 --- a/sp/src/tier1/snappy-stubs-internal.h +++ b/sp/src/tier1/snappy-stubs-internal.h @@ -138,12 +138,21 @@ class LogMessage { class LogMessageCrash : public LogMessage { public: LogMessageCrash() { } +#if _MSC_VER == 1700 +// Bogus warning from VS 2012: +// warning C4722: 'snappy::LogMessageCrash::~LogMessageCrash' : destructor never returns, potential memory leak +#pragma warning(push) +#pragma warning(disable : 4722) +#endif ~LogMessageCrash() { fprintf( stderr, "\n" ); // cerr << endl; abort(); } }; +#if _MSC_VER == 1700 +#pragma warning(pop) +#endif // This class is used to explicitly ignore values in the conditional // logging macros. This avoids compiler warnings like "value computed diff --git a/sp/src/tier1/tier1.vpc b/sp/src/tier1/tier1.vpc index 2784d62c..eac035ce 100644 --- a/sp/src/tier1/tier1.vpc +++ b/sp/src/tier1/tier1.vpc @@ -44,7 +44,7 @@ $Project "tier1" $File "interface.cpp" $File "KeyValues.cpp" $File "kvpacker.cpp" - $File "lzmaDecoder.cpp" [!$SOURCESDK] + $File "lzmaDecoder.cpp" $File "lzss.cpp" [!$SOURCESDK] $File "mempool.cpp" $File "memstack.cpp" diff --git a/sp/src/utils/vrad/lightmap.cpp b/sp/src/utils/vrad/lightmap.cpp index b6f8c1f7..bc3d254e 100644 --- a/sp/src/utils/vrad/lightmap.cpp +++ b/sp/src/utils/vrad/lightmap.cpp @@ -661,8 +661,9 @@ bool BuildFacesamples( lightinfo_t *pLightInfo, facelight_t *pFaceLight ) pTex->lightmapVecsLuxelsPerWorldUnits[1] ) ) ); // allocate a large number of samples for creation -- get copied later! - char sampleData[sizeof(sample_t)*SINGLE_BRUSH_MAP*2]; - sample_t *samples = (sample_t*)sampleData; // use a char array to speed up the debug version. + CUtlVector sampleData; + sampleData.SetCount( SINGLE_BRUSH_MAP * 2 ); + sample_t *samples = sampleData.Base(); sample_t *pSamples = samples; // lightmap space winding diff --git a/sp/src/utils/vrad/trace.cpp b/sp/src/utils/vrad/trace.cpp index f049fc40..8069dbe7 100644 --- a/sp/src/utils/vrad/trace.cpp +++ b/sp/src/utils/vrad/trace.cpp @@ -622,14 +622,23 @@ void AddBrushesForRayTrace( void ) for ( int j = 0; j < face->numedges; j++ ) { + if ( j >= MAX_POINTS_ON_WINDING ) + Error( "***** ERROR! MAX_POINTS_ON_WINDING reached!" ); + + if ( face->firstedge + j >= ARRAYSIZE( dsurfedges ) ) + Error( "***** ERROR! face->firstedge + j >= ARRAYSIZE( dsurfedges )!" ); + int surfEdge = dsurfedges[face->firstedge + j]; - short v; + unsigned short v; if (surfEdge < 0) v = dedges[-surfEdge].v[1]; else v = dedges[surfEdge].v[0]; + if ( v >= ARRAYSIZE( dvertexes ) ) + Error( "***** ERROR! v(%u) >= ARRAYSIZE( dvertexes(%d) )!", ( unsigned int )v, ARRAYSIZE( dvertexes ) ); + dvertex_t *dv = &dvertexes[v]; points[j] = dv->point; } diff --git a/sp/src/utils/vrad/vrad_dispcoll.cpp b/sp/src/utils/vrad/vrad_dispcoll.cpp index df69a4ac..7e788d07 100644 --- a/sp/src/utils/vrad/vrad_dispcoll.cpp +++ b/sp/src/utils/vrad/vrad_dispcoll.cpp @@ -665,8 +665,8 @@ void CVRADDispColl::CreateChildPatchesSub( int iParentPatch ) // Split along the longest edge. Vector vecEdges[3]; vecEdges[0] = pParentPatch->winding->p[1] - pParentPatch->winding->p[0]; - vecEdges[1] = pParentPatch->winding->p[2] - pParentPatch->winding->p[0]; - vecEdges[2] = pParentPatch->winding->p[2] - pParentPatch->winding->p[1]; + vecEdges[1] = pParentPatch->winding->p[2] - pParentPatch->winding->p[1]; + vecEdges[2] = pParentPatch->winding->p[0] - pParentPatch->winding->p[2]; // Find the longest edge. float flEdgeLength = 0.0f; diff --git a/sp/src/utils/vrad/vraddisps.cpp b/sp/src/utils/vrad/vraddisps.cpp index 1e8d2606..0bbafd40 100644 --- a/sp/src/utils/vrad/vraddisps.cpp +++ b/sp/src/utils/vrad/vraddisps.cpp @@ -1135,7 +1135,7 @@ void AddPatchLightToRadial( Vector const &patchOrigin, Vector const &patchNormal if( bNeighborBump ) { float flScale = patchNormal.Dot( normals[0] ); - flScale = clamp( flScale, 0.0f, flScale ); + flScale = max( 0.0f, flScale ); float flBumpInfluence = influence * flScale; for( int ndxBump = 0; ndxBump < ( NUM_BUMP_VECTS+1 ); ndxBump++ ) @@ -1148,7 +1148,7 @@ void AddPatchLightToRadial( Vector const &patchOrigin, Vector const &patchNormal else { float flScale = patchNormal.Dot( normals[0] ); - flScale = clamp( flScale, 0.0f, flScale ); + flScale = max( 0.0f, flScale ); float flBumpInfluence = influence * flScale * 0.05f; for( int ndxBump = 0; ndxBump < ( NUM_BUMP_VECTS+1 ); ndxBump++ ) @@ -1162,7 +1162,7 @@ void AddPatchLightToRadial( Vector const &patchOrigin, Vector const &patchNormal else { float flScale = patchNormal.Dot( luxelNormal ); - flScale = clamp( flScale, 0.0f, flScale ); + flScale = max( 0.0f, flScale ); influence *= flScale; pRadial->light[0][ndxRadial].AddWeighted( pPatchLight[0], influence ); @@ -1580,21 +1580,13 @@ bool CVRadDispMgr::BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFace // int ndxU, ndxV; - // NOTE: These allocations are necessary to avoid stack overflow - // FIXME: Solve with storing global per-thread temp buffers if there's - // a performance problem with this solution... - bool bTempAllocationNecessary = ((height + 1) * (width + 1)) > SINGLE_BRUSH_MAP; + CUtlVector samples; + samples.SetCount( SINGLEMAP ); + sample_t *pSamples = samples.Base(); - Vector worldPointBuffer[SINGLE_BRUSH_MAP]; - sample_t sampleBuffer[SINGLE_BRUSH_MAP*2]; - - Vector *pWorldPoints = worldPointBuffer; - sample_t *pSamples = sampleBuffer; - if (bTempAllocationNecessary) - { - pWorldPoints = new Vector[ SINGLEMAP ]; - pSamples = new sample_t[ SINGLEMAP ]; - } + CUtlVector worldPoints; + worldPoints.SetCount( SINGLEMAP ); + Vector *pWorldPoints = worldPoints.Base(); for( ndxV = 0; ndxV < ( height + 1 ); ndxV++ ) { @@ -1607,7 +1599,6 @@ bool CVRadDispMgr::BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFace } } - for( ndxV = 0; ndxV < height; ndxV++ ) { for( ndxU = 0; ndxU < width; ndxU++ ) @@ -1660,7 +1651,7 @@ bool CVRadDispMgr::BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFace pFaceLight->numsamples = width * height; pFaceLight->sample = ( sample_t* )calloc( pFaceLight->numsamples, sizeof( *pFaceLight->sample ) ); if( !pFaceLight->sample ) - goto buildDispSamplesError; + return false; memcpy( pFaceLight->sample, pSamples, pFaceLight->numsamples * sizeof( *pFaceLight->sample ) ); @@ -1669,23 +1660,8 @@ bool CVRadDispMgr::BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFace { Msg( "BuildDispSamples: WARNING - no samples %d\n", pLightInfo->face - g_pFaces ); } - - if (bTempAllocationNecessary) - { - delete[] pWorldPoints; - delete[] pSamples; - } return true; - -buildDispSamplesError: - if (bTempAllocationNecessary) - { - delete[] pWorldPoints; - delete[] pSamples; - } - - return false; } diff --git a/sp/src/vpc_scripts/groups.vgc b/sp/src/vpc_scripts/groups.vgc index 93f7b2c5..c4786f55 100644 --- a/sp/src/vpc_scripts/groups.vgc +++ b/sp/src/vpc_scripts/groups.vgc @@ -23,10 +23,16 @@ $Group "game" "vgui_controls" } +$Group "shaders" +{ + "game_shader_dx9" +} + $Group "everything" { "captioncompiler" "client" + "game_shader_dx9" "glview" "height2normal" "mathlib" diff --git a/sp/src/vpc_scripts/projects.vgc b/sp/src/vpc_scripts/projects.vgc index 4eb01eae..ff17a9d5 100644 --- a/sp/src/vpc_scripts/projects.vgc +++ b/sp/src/vpc_scripts/projects.vgc @@ -19,6 +19,12 @@ $Project "client" "game\client\client_episodic.vpc" [($WIN32||$X360||$POSIX) && $EPISODIC] } +$Project "game_shader_dx9" +{ + "materialsystem\stdshaders\game_shader_dx9_hl2.vpc" [$HL2] + "materialsystem\stdshaders\game_shader_dx9_episodic.vpc" [$EPISODIC] +} + $Project "glview" { "utils\glview\glview.vpc" [$WIN32] diff --git a/sp/src/vpc_scripts/source_base.vpc b/sp/src/vpc_scripts/source_base.vpc index 074b850c..fc70c2e5 100644 --- a/sp/src/vpc_scripts/source_base.vpc +++ b/sp/src/vpc_scripts/source_base.vpc @@ -10,8 +10,8 @@ // This is one file we expect to be different between branches and so it must be merged carefully // Staging branch: -//$Macro STAGING_ONLY "1" +//$Conditional STAGING_ONLY "1" // rel/tf_beta branch: -//$Macro TF_BETA "1" +//$Conditional TF_BETA "1" diff --git a/sp/src/vpc_scripts/source_dll_win32_base.vpc b/sp/src/vpc_scripts/source_dll_win32_base.vpc index 77f577e2..4382efaa 100644 --- a/sp/src/vpc_scripts/source_dll_win32_base.vpc +++ b/sp/src/vpc_scripts/source_dll_win32_base.vpc @@ -130,7 +130,7 @@ $Project $CustomBuildStep { // General - $CommandLine "$QUOTE$(VCInstallDir)bin\ml.exe$QUOTE /c /Cp /Zi /Fo$QUOTE$(IntDir)\$(InputName).obj$QUOTE $QUOTE$(InputPath)$QUOTE" + $CommandLine "$QUOTE$(VCInstallDir)bin\ml.exe$QUOTE /safeseh /c /Cp /Zi /Fo$QUOTE$(IntDir)\$(InputName).obj$QUOTE $QUOTE$(InputPath)$QUOTE" $Description "Compiling pointeroverride.asm" $Outputs "$(IntDir)\$(InputName).obj" } diff --git a/sp/src/vpc_scripts/source_video_base.vpc b/sp/src/vpc_scripts/source_video_base.vpc index b1baa408..dd7f3653 100644 --- a/sp/src/vpc_scripts/source_video_base.vpc +++ b/sp/src/vpc_scripts/source_video_base.vpc @@ -31,7 +31,7 @@ $Macro GL "1" [!$DEDICATED && !$WIN32 && !$WIN64] // If we're using OpenGL, we're implicitly using SDL. -$Macro SDL "1" [$GL && !$OSXALL && !$DEDICATED] +$Macro SDL "1" [$GL && !$DEDICATED] $Configuration { @@ -57,5 +57,14 @@ $Configuration $PreprocessorDefinitions "$BASE;USE_SDL" [$SDL] $AdditionalIncludeDirectories "$BASE;$SRCDIR\thirdparty\SDL2" [$SDL || $DEDICATED] } + +} + +$Project +{ + $Folder "Link Libraries" [$OSXALL && $SDL] + { + $DynamicFile "$SRCDIR\lib\public\$PLATFORM\$_IMPLIB_PREFIXSDL2$_IMPLIB_EXT" + } } diff --git a/sp/src/vpc_scripts/source_win32_base.vpc b/sp/src/vpc_scripts/source_win32_base.vpc index 8be3bcf6..04ef53b8 100644 --- a/sp/src/vpc_scripts/source_win32_base.vpc +++ b/sp/src/vpc_scripts/source_win32_base.vpc @@ -60,10 +60,6 @@ $Configuration $PreprocessorDefinitions "$BASE;WIN64;_WIN64;COMPILER_MSVC64" [$WIN64] $PreprocessorDefinitions "$BASE;COMPILER_MSVC32" [$WIN32] - // The VS 2012 compiler keeps hitting internal compiler errors during /analyze. In order to get these - // fixed we need to report them. - $AdditionalOptions "$BASE /errorReport:send" [$ANALYZE] - // Pass on appropriate branch define to preprocessor $PreprocessorDefinitions "$BASE;STAGING_ONLY" [$STAGING_ONLY] $PreprocessorDefinitions "$BASE;TF_BETA" [$TF_BETA] diff --git a/thirdpartylegalnotices.txt b/thirdpartylegalnotices.txt index 126ea8ce..cf9a5f6f 100644 --- a/thirdpartylegalnotices.txt +++ b/thirdpartylegalnotices.txt @@ -1,870 +1,870 @@ -The Source engine and Valve games use Third Party code for certain functions. The -required legal notices for using such code are reproduced below in accordance with -Valve’s obligations to provide such notices: - -************************************************************************************ -Xzip/Xunzip: -************************************************************************************ - - // This is version 2002-Feb-16 of the Info-ZIP copyright and license. The - // definitive version of this document should be available at - // ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely. - // - // Copyright (c) 1990-2002 Info-ZIP. All rights reserved. - // - // For the purposes of this copyright and license, "Info-ZIP" is defined as - // the following set of individuals: - // - // Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, - // Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase, - // Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, - // David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, - // Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, - // Kai Uwe Rommel, Steve Salisbury, Dave Smith, Christian Spieler, - // Antoine Verheijen, Paul von Behren, Rich Wales, Mike White - // - // This software is provided "as is", without warranty of any kind, express - // or implied. In no event shall Info-ZIP or its contributors be held liable - // for any direct, indirect, incidental, special or consequential damages - // arising out of the use of or inability to use this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. Redistributions of source code must retain the above copyright notice, - // definition, disclaimer, and this list of conditions. - // - // 2. Redistributions in binary form (compiled executables) must reproduce - // the above copyright notice, definition, disclaimer, and this list of - // conditions in documentation and/or other materials provided with the - // distribution. The sole exception to this condition is redistribution - // of a standard UnZipSFX binary as part of a self-extracting archive; - // that is permitted without inclusion of this license, as long as the - // normal UnZipSFX banner has not been removed from the binary or disabled. - // - // 3. Altered versions--including, but not limited to, ports to new - // operating systems, existing ports with new graphical interfaces, and - // dynamic, shared, or static library versions--must be plainly marked - // as such and must not be misrepresented as being the original source. - // Such altered versions also must not be misrepresented as being - // Info-ZIP releases--including, but not limited to, labeling of the - // altered versions with the names "Info-ZIP" (or any variation thereof, - // including, but not limited to, different capitalizations), - // "Pocket UnZip", "WiZ" or "MacZip" without the explicit permission of - // Info-ZIP. Such altered versions are further prohibited from - // misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or - // of the Info-ZIP URL(s). - // - // 4. Info-ZIP retains the right to use the names "Info-ZIP", "Zip", "UnZip", - // "UnZipSFX", "WiZ", "Pocket UnZip", "Pocket Zip", and "MacZip" for its - // own source and binary releases. - // - /////////////////////////////////////////////////////////////////////////////// - -************************************************************************************ -JPEG image support: -************************************************************************************ - - The Source engine and SDK also make use of library functions for working with .jpg - files. Specifically, the Source engine jpeg library is based in part on the work of - the Independent JPEG Group (IJG). The original source code and project files for the IJG's - JPEG libraries may be found at: http://www.ijg.org/files/jpegsrc.v6b.tar.gz - - The following is the README. File from that archive and is produced in accordance with the legal - notices required by the library: - - The Independent JPEG Group's JPEG software - ========================================== - - README for release 6b of 27-Mar-1998 - ==================================== - - This distribution contains the sixth public release of the Independent JPEG - Group's free JPEG software. You are welcome to redistribute this software and - to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. - - Serious users of this software (particularly those incorporating it into - larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to - our electronic mailing list. Mailing list members are notified of updates - and have a chance to participate in technical discussions, etc. - - This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, - Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, - Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG - Group. - - IJG is not affiliated with the official ISO JPEG standards committee. - - - DOCUMENTATION ROADMAP - ===================== - - This file contains the following sections: - - OVERVIEW General description of JPEG and the IJG software. - LEGAL ISSUES Copyright, lack of warranty, terms of distribution. - REFERENCES Where to learn more about JPEG. - ARCHIVE LOCATIONS Where to find newer versions of this software. - RELATED SOFTWARE Other stuff you should get. - FILE FORMAT WARS Software *not* to get. - TO DO Plans for future IJG releases. - - Other documentation files in the distribution are: - - User documentation: - install.doc How to configure and install the IJG software. - usage.doc Usage instructions for cjpeg, djpeg, jpegtran, - rdjpgcom, and wrjpgcom. - *.1 Unix-style man pages for programs (same info as usage.doc). - wizard.doc Advanced usage instructions for JPEG wizards only. - change.log Version-to-version change highlights. - Programmer and internal documentation: - libjpeg.doc How to use the JPEG library in your own programs. - example.c Sample code for calling the JPEG library. - structure.doc Overview of the JPEG library's internal structure. - filelist.doc Road map of IJG files. - coderules.doc Coding style rules --- please read if you contribute code. - - Please read at least the files install.doc and usage.doc. Useful information - can also be found in the JPEG FAQ (Frequently Asked Questions) article. See - ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. - - If you want to understand how the JPEG code works, we suggest reading one or - more of the REFERENCES, then looking at the documentation files (in roughly - the order listed) before diving into the code. - - - OVERVIEW - ======== - - This package contains C software to implement JPEG image compression and - decompression. JPEG (pronounced "jay-peg") is a standardized compression - method for full-color and gray-scale images. JPEG is intended for compressing - "real-world" scenes; line drawings, cartoons and other non-realistic images - are not its strong suit. JPEG is lossy, meaning that the output image is not - exactly identical to the input image. Hence you must not use JPEG if you - have to have identical output bits. However, on typical photographic images, - very good compression levels can be obtained with no visible change, and - remarkably high compression levels are possible if you can tolerate a - low-quality image. For more details, see the references, or just experiment - with various compression settings. - - This software implements JPEG baseline, extended-sequential, and progressive - compression processes. Provision is made for supporting all variants of these - processes, although some uncommon parameter settings aren't implemented yet. - For legal reasons, we are not distributing code for the arithmetic-coding - variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting - the hierarchical or lossless processes defined in the standard. - - We provide a set of library routines for reading and writing JPEG image files, - plus two sample applications "cjpeg" and "djpeg", which use the library to - perform conversion between JPEG and some other popular image file formats. - The library is intended to be reused in other applications. - - In order to support file conversion and viewing software, we have included - considerable functionality beyond the bare JPEG coding/decoding capability; - for example, the color quantization modules are not strictly part of JPEG - decoding, but they are essential for output to colormapped file formats or - colormapped displays. These extra functions can be compiled out of the - library if not required for a particular application. We have also included - "jpegtran", a utility for lossless transcoding between different JPEG - processes, and "rdjpgcom" and "wrjpgcom", two simple applications for - inserting and extracting textual comments in JFIF files. - - The emphasis in designing this software has been on achieving portability and - flexibility, while also making it fast enough to be useful. In particular, - the software is not intended to be read as a tutorial on JPEG. (See the - REFERENCES section for introductory material.) Rather, it is intended to - be reliable, portable, industrial-strength code. We do not claim to have - achieved that goal in every aspect of the software, but we strive for it. - - We welcome the use of this software as a component of commercial products. - No royalty is required, but we do ask for an acknowledgement in product - documentation, as described under LEGAL ISSUES. - - - LEGAL ISSUES - ============ - - In plain English: - - 1. We don't promise that this software works. (But if you find any bugs, - please let us know!) - 2. You can use this software for whatever you want. You don't have to pay us. - 3. You may not pretend that you wrote this software. If you use it in a - program, you must acknowledge somewhere in your documentation that - you've used the IJG code. - - In legalese: - - The authors make NO WARRANTY or representation, either express or implied, - with respect to this software, its quality, accuracy, merchantability, or - fitness for a particular purpose. This software is provided "AS IS", and you, - its user, assume the entire risk as to its quality and accuracy. - - This software is copyright (C) 1991-1998, Thomas G. Lane. - All Rights Reserved except as specified below. - - Permission is hereby granted to use, copy, modify, and distribute this - software (or portions thereof) for any purpose, without fee, subject to these - conditions: - (1) If any part of the source code for this software is distributed, then this - README file must be included, with this copyright and no-warranty notice - unaltered; and any additions, deletions, or changes to the original files - must be clearly indicated in accompanying documentation. - (2) If only executable code is distributed, then the accompanying - documentation must state that "this software is based in part on the work of - the Independent JPEG Group". - (3) Permission for use of this software is granted only if the user accepts - full responsibility for any undesirable consequences; the authors accept - NO LIABILITY for damages of any kind. - - These conditions apply to any software derived from or based on the IJG code, - not just to the unmodified library. If you use our work, you ought to - acknowledge us. - - Permission is NOT granted for the use of any IJG author's name or company name - in advertising or publicity relating to this software or products derived from - it. This software may be referred to only as "the Independent JPEG Group's - software". - - We specifically permit and encourage the use of this software as the basis of - commercial products, provided that all warranty or liability claims are - assumed by the product vendor. - - - ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, - sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. - ansi2knr.c is NOT covered by the above copyright and conditions, but instead - by the usual distribution terms of the Free Software Foundation; principally, - that you must include source code if you redistribute it. (See the file - ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part - of any program generated from the IJG code, this does not limit you more than - the foregoing paragraphs do. - - The Unix configuration script "configure" was produced with GNU Autoconf. - It is copyright by the Free Software Foundation but is freely distributable. - The same holds for its supporting scripts (config.guess, config.sub, - ltconfig, ltmain.sh). Another support script, install-sh, is copyright - by M.I.T. but is also freely distributable. - - It appears that the arithmetic coding option of the JPEG spec is covered by - patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot - legally be used without obtaining one or more licenses. For this reason, - support for arithmetic coding has been removed from the free JPEG software. - (Since arithmetic coding provides only a marginal gain over the unpatented - Huffman mode, it is unlikely that very many implementations will support it.) - So far as we are aware, there are no patent restrictions on the remaining - code. - - The IJG distribution formerly included code to read and write GIF files. - To avoid entanglement with the Unisys LZW patent, GIF reading support has - been removed altogether, and the GIF writer has been simplified to produce - "uncompressed GIFs". This technique does not use the LZW algorithm; the - resulting GIF files are larger than usual, but are readable by all standard - GIF decoders. - - We are required to state that - "The Graphics Interchange Format(c) is the Copyright property of - CompuServe Incorporated. GIF(sm) is a Service Mark property of - CompuServe Incorporated." - - - REFERENCES - ========== - - We highly recommend reading one or more of these references before trying to - understand the innards of the JPEG software. - - The best short technical introduction to the JPEG compression algorithm is - Wallace, Gregory K. "The JPEG Still Picture Compression Standard", - Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. - (Adjacent articles in that issue discuss MPEG motion picture compression, - applications of JPEG, and related topics.) If you don't have the CACM issue - handy, a PostScript file containing a revised version of Wallace's article is - available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually - a preprint for an article that appeared in IEEE Trans. Consumer Electronics) - omits the sample images that appeared in CACM, but it includes corrections - and some added material. Note: the Wallace article is copyright ACM and IEEE, - and it may not be used for commercial purposes. - - A somewhat less technical, more leisurely introduction to JPEG can be found in - "The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by - M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides - good explanations and example C code for a multitude of compression methods - including JPEG. It is an excellent source if you are comfortable reading C - code but don't know much about data compression in general. The book's JPEG - sample code is far from industrial-strength, but when you are ready to look - at a full implementation, you've got one here... - - The best full description of JPEG is the textbook "JPEG Still Image Data - Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published - by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. - The book includes the complete text of the ISO JPEG standards (DIS 10918-1 - and draft DIS 10918-2). This is by far the most complete exposition of JPEG - in existence, and we highly recommend it. - - The JPEG standard itself is not available electronically; you must order a - paper copy through ISO or ITU. (Unless you feel a need to own a certified - official copy, we recommend buying the Pennebaker and Mitchell book instead; - it's much cheaper and includes a great deal of useful explanatory material.) - In the USA, copies of the standard may be ordered from ANSI Sales at (212) - 642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI - doesn't take credit card orders, but Global does.) It's not cheap: as of - 1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% - shipping/handling. The standard is divided into two parts, Part 1 being the - actual specification, while Part 2 covers compliance testing methods. Part 1 - is titled "Digital Compression and Coding of Continuous-tone Still Images, - Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS - 10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of - Continuous-tone Still Images, Part 2: Compliance testing" and has document - numbers ISO/IEC IS 10918-2, ITU-T T.83. - - Some extensions to the original JPEG standard are defined in JPEG Part 3, - a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG - currently does not support any Part 3 extensions. - - The JPEG standard does not specify all details of an interchangeable file - format. For the omitted details we follow the "JFIF" conventions, revision - 1.02. A copy of the JFIF spec is available from: - Literature Department - C-Cube Microsystems, Inc. - 1778 McCarthy Blvd. - Milpitas, CA 95035 - phone (408) 944-6300, fax (408) 944-6314 - A PostScript version of this document is available by FTP at - ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text - version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing - the figures. - - The TIFF 6.0 file format specification can be obtained by FTP from - ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme - found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. - IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). - Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 - (Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or - from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision - of the TIFF spec will replace the 6.0 JPEG design with the Note's design. - Although IJG's own code does not support TIFF/JPEG, the free libtiff library - uses our library to implement TIFF/JPEG per the Note. libtiff is available - from ftp://ftp.sgi.com/graphics/tiff/. - - - ARCHIVE LOCATIONS - ================= - - The "official" archive site for this software is ftp.uu.net (Internet - address 192.48.96.9). The most recent released version can always be found - there in directory graphics/jpeg. This particular version will be archived - as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have - direct Internet access, UUNET's archives are also available via UUCP; contact - help@uunet.uu.net for information on retrieving files that way. - - Numerous Internet sites maintain copies of the UUNET files. However, only - ftp.uu.net is guaranteed to have the latest official version. - - You can also obtain this software in DOS-compatible "zip" archive format from - the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or - on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 - "JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net - release. - - The JPEG FAQ (Frequently Asked Questions) article is a useful source of - general information about JPEG. It is updated constantly and therefore is - not included in this distribution. The FAQ is posted every two weeks to - Usenet newsgroups comp.graphics.misc, news.answers, and other groups. - It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ - and other news.answers archive sites, including the official news.answers - archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. - If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu - with body - send usenet/news.answers/jpeg-faq/part1 - send usenet/news.answers/jpeg-faq/part2 - - - RELATED SOFTWARE - ================ - - Numerous viewing and image manipulation programs now support JPEG. (Quite a - few of them use this library to do so.) The JPEG FAQ described above lists - some of the more popular free and shareware viewers, and tells where to - obtain them on Internet. - - If you are on a Unix machine, we highly recommend Jef Poskanzer's free - PBMPLUS software, which provides many useful operations on PPM-format image - files. In particular, it can convert PPM images to and from a wide range of - other formats, thus making cjpeg/djpeg considerably more useful. The latest - version is distributed by the NetPBM group, and is available from numerous - sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. - Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; - you are likely to have difficulty making it work on any non-Unix machine. - - A different free JPEG implementation, written by the PVRG group at Stanford, - is available from ftp://havefun.stanford.edu/pub/jpeg/. This program - is designed for research and experimentation rather than production use; - it is slower, harder to use, and less portable than the IJG code, but it - is easier to read and modify. Also, the PVRG code supports lossless JPEG, - which we do not. (On the other hand, it doesn't do progressive JPEG.) - - - FILE FORMAT WARS - ================ - - Some JPEG programs produce files that are not compatible with our library. - The root of the problem is that the ISO JPEG committee failed to specify a - concrete file format. Some vendors "filled in the blanks" on their own, - creating proprietary formats that no one else could read. (For example, none - of the early commercial JPEG implementations for the Macintosh were able to - exchange compressed files.) - - The file format we have adopted is called JFIF (see REFERENCES). This format - has been agreed to by a number of major commercial JPEG vendors, and it has - become the de facto standard. JFIF is a minimal or "low end" representation. - We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF - Technical Note #2) for "high end" applications that need to record a lot of - additional data about an image. TIFF/JPEG is fairly new and not yet widely - supported, unfortunately. - - The upcoming JPEG Part 3 standard defines a file format called SPIFF. - SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should - be able to read the most common variant of SPIFF. SPIFF has some technical - advantages over JFIF, but its major claim to fame is simply that it is an - official standard rather than an informal one. At this point it is unclear - whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto - standard. IJG intends to support SPIFF once the standard is frozen, but we - have not decided whether it should become our default output format or not. - (In any case, our decoder will remain capable of reading JFIF indefinitely.) - - Various proprietary file formats incorporating JPEG compression also exist. - We have little or no sympathy for the existence of these formats. Indeed, - one of the original reasons for developing this free software was to help - force convergence on common, open format standards for JPEG files. Don't - use a proprietary file format! - - - TO DO - ===== - - The major thrust for v7 will probably be improvement of visual quality. - The current method for scaling the quantization tables is known not to be - very good at low Q values. We also intend to investigate block boundary - smoothing, "poor man's variable quantization", and other means of improving - quality-vs-file-size performance without sacrificing compatibility. - - In future versions, we are considering supporting some of the upcoming JPEG - Part 3 extensions --- principally, variable quantization and the SPIFF file - format. - - As always, speeding things up is of great interest. - - Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. - -************************************************************************************ -Celt Codec: -************************************************************************************ - - Copyright 2001-2009 Jean-Marc Valin, Timothy B. Terriberry, - CSIRO, and other contributors - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -************************************************************************************ -SPEEX Codes: -************************************************************************************ - SPEEX © 2002-2003, Jean-Marc Valin/Xiph.Org Foundation - Redistribution and use in source and binary forms, with or without modification, are permitted - provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - * Neither the name of the Xiph.org Foundation nor the names of its contributors may be - used to endorse or promote products derived from this software without specific prior - written permission. - This software is provided by the copyright holders and contributors “as is” and any express or - implied warranties, including, but not limited to, the implied warranties of merchantability and - fitness for a particular purpose are disclaimed. In no event shall the foundation or contributors be - liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, - but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or - business interruption) however caused and on any theory of liability, whether in contract, strict - liability, or tort (including negligence or otherwise) arising in any way out of the use of this - software, even if advised of the possibility of such damage. - -************************************************************************************ -google-perftools: -************************************************************************************ - - http://code.google.com/p/gperftools/ - - Copyright (c) 2012, Google Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - For Google libjingle: - http://sourceforge.net/projects/libjingle/ - Copyright (c) 2004--2005, Google Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. - -************************************************************************************ -CakePHP: -************************************************************************************ - - CakePHP(tm) : Rapid Development Framework - Copyright 2005-2007, Cake Software Foundation, Inc. - 1785 E. Sahara Avenue, Suite 490-204 - Las Vegas, Nevada 89104 - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -************************************************************************************ -LZMA -************************************************************************************ - - LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) - http://www.7-zip.org/ - LZMA SDK is licensed under two licenses: - 1) GNU Lesser General Public License (GNU LGPL) - 2) Common Public License (CPL) - It means that you can select one of these two licenses and - follow rules of that license. - SPECIAL EXCEPTION: - Igor Pavlov, as the author of this Code, expressly permits you to - statically or dynamically link your Code (or bind by name) to the - interfaces of this file without subjecting your linked Code to the - terms of the CPL or GNU LGPL. Any modifications or additions - to this file, however, are subject to the LGPL or CPL terms. - -************************************************************************************ -Fast Pow Function -************************************************************************************ - - /* - * (c) Ian Stephenson - * - * ian@dctsystems.co.uk - * - * Fast pow() reference implementation - */ - - Used with permission from author - - For libantlr3c: - // [The "BSD licence"] - // Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC - // http://www.temporal-wave.com - // http://www.linkedin.com/in/jimidle - // - // All rights reserved. - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions - // are met: - // 1. Redistributions of source code must retain the above copyright - // notice, this list of conditions and the following disclaimer. - // 2. Redistributions in binary form must reproduce the above copyright - // notice, this list of conditions and the following disclaimer in the - // documentation and/or other materials provided with the distribution. - // 3. The name of the author may not be used to endorse or promote products - // derived from this software without specific prior written permission. - // - // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -************************************************************************************ -Autodesk® FBX®: -************************************************************************************ - - “This software contains Autodesk® FBX® code developed by Autodesk, Inc. Copyright 2012 Autodesk, Inc. - All rights, reserved. Such code is provided “as is” and Autodesk, Inc. disclaims any and all warranties, - whether express or implied, including without limitation the implied warranties of merchantability, fitness for a - particular purpose or non-infringement of third party rights. In no event shall Autodesk, Inc. be liable for any - direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, - procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however - caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or - otherwise) arising in any way out of such code.” - -************************************************************************************ -OpenSSL: -************************************************************************************ - - * This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/) - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - /* ==================================================================== - * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be - used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * - */ - - - /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an - acknowledgement: - * "This product includes software written by Tim Hudson - (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -************************************************************************************ -Google protocol buffers -************************************************************************************ - - // Protocol Buffers - Google's data interchange format - // Copyright 2008 Google Inc. All rights reserved. - // http://code.google.com/p/protobuf/ - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions are - // met: - // - // * Redistributions of source code must retain the above copyright - // notice, this list of conditions and the following disclaimer. - // * Redistributions in binary form must reproduce the above - // copyright notice, this list of conditions and the following disclaimer - // in the documentation and/or other materials provided with the - // distribution. - // * Neither the name of Google Inc. nor the names of its - // contributors may be used to endorse or promote products derived from - // this software without specific prior written permission. - // - // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - // Author: kenton@google.com (Kenton Varda) - // Based on original Protocol Buffers design by - // Sanjay Ghemawat, Jeff Dean, and others. - -************************************************************************************ -Google Snappy -************************************************************************************ - - // Copyright 2005 Google Inc. All Rights Reserved. - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions are - // met: - // - // * Redistributions of source code must retain the above copyright - // notice, this list of conditions and the following disclaimer. - // * Redistributions in binary form must reproduce the above - // copyright notice, this list of conditions and the following disclaimer - // in the documentation and/or other materials provided with the - // distribution. - // * Neither the name of Google Inc. nor the names of its - // contributors may be used to endorse or promote products derived from - // this software without specific prior written permission. - // - // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +The Source engine and Valve games use Third Party code for certain functions. The +required legal notices for using such code are reproduced below in accordance with +Valve’s obligations to provide such notices: + +************************************************************************************ +Xzip/Xunzip: +************************************************************************************ + + // This is version 2002-Feb-16 of the Info-ZIP copyright and license. The + // definitive version of this document should be available at + // ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely. + // + // Copyright (c) 1990-2002 Info-ZIP. All rights reserved. + // + // For the purposes of this copyright and license, "Info-ZIP" is defined as + // the following set of individuals: + // + // Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, + // Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase, + // Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, + // David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, + // Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, + // Kai Uwe Rommel, Steve Salisbury, Dave Smith, Christian Spieler, + // Antoine Verheijen, Paul von Behren, Rich Wales, Mike White + // + // This software is provided "as is", without warranty of any kind, express + // or implied. In no event shall Info-ZIP or its contributors be held liable + // for any direct, indirect, incidental, special or consequential damages + // arising out of the use of or inability to use this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. Redistributions of source code must retain the above copyright notice, + // definition, disclaimer, and this list of conditions. + // + // 2. Redistributions in binary form (compiled executables) must reproduce + // the above copyright notice, definition, disclaimer, and this list of + // conditions in documentation and/or other materials provided with the + // distribution. The sole exception to this condition is redistribution + // of a standard UnZipSFX binary as part of a self-extracting archive; + // that is permitted without inclusion of this license, as long as the + // normal UnZipSFX banner has not been removed from the binary or disabled. + // + // 3. Altered versions--including, but not limited to, ports to new + // operating systems, existing ports with new graphical interfaces, and + // dynamic, shared, or static library versions--must be plainly marked + // as such and must not be misrepresented as being the original source. + // Such altered versions also must not be misrepresented as being + // Info-ZIP releases--including, but not limited to, labeling of the + // altered versions with the names "Info-ZIP" (or any variation thereof, + // including, but not limited to, different capitalizations), + // "Pocket UnZip", "WiZ" or "MacZip" without the explicit permission of + // Info-ZIP. Such altered versions are further prohibited from + // misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or + // of the Info-ZIP URL(s). + // + // 4. Info-ZIP retains the right to use the names "Info-ZIP", "Zip", "UnZip", + // "UnZipSFX", "WiZ", "Pocket UnZip", "Pocket Zip", and "MacZip" for its + // own source and binary releases. + // + /////////////////////////////////////////////////////////////////////////////// + +************************************************************************************ +JPEG image support: +************************************************************************************ + + The Source engine and SDK also make use of library functions for working with .jpg + files. Specifically, the Source engine jpeg library is based in part on the work of + the Independent JPEG Group (IJG). The original source code and project files for the IJG's + JPEG libraries may be found at: http://www.ijg.org/files/jpegsrc.v6b.tar.gz + + The following is the README. File from that archive and is produced in accordance with the legal + notices required by the library: + + The Independent JPEG Group's JPEG software + ========================================== + + README for release 6b of 27-Mar-1998 + ==================================== + + This distribution contains the sixth public release of the Independent JPEG + Group's free JPEG software. You are welcome to redistribute this software and + to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. + + Serious users of this software (particularly those incorporating it into + larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to + our electronic mailing list. Mailing list members are notified of updates + and have a chance to participate in technical discussions, etc. + + This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, + Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, + Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG + Group. + + IJG is not affiliated with the official ISO JPEG standards committee. + + + DOCUMENTATION ROADMAP + ===================== + + This file contains the following sections: + + OVERVIEW General description of JPEG and the IJG software. + LEGAL ISSUES Copyright, lack of warranty, terms of distribution. + REFERENCES Where to learn more about JPEG. + ARCHIVE LOCATIONS Where to find newer versions of this software. + RELATED SOFTWARE Other stuff you should get. + FILE FORMAT WARS Software *not* to get. + TO DO Plans for future IJG releases. + + Other documentation files in the distribution are: + + User documentation: + install.doc How to configure and install the IJG software. + usage.doc Usage instructions for cjpeg, djpeg, jpegtran, + rdjpgcom, and wrjpgcom. + *.1 Unix-style man pages for programs (same info as usage.doc). + wizard.doc Advanced usage instructions for JPEG wizards only. + change.log Version-to-version change highlights. + Programmer and internal documentation: + libjpeg.doc How to use the JPEG library in your own programs. + example.c Sample code for calling the JPEG library. + structure.doc Overview of the JPEG library's internal structure. + filelist.doc Road map of IJG files. + coderules.doc Coding style rules --- please read if you contribute code. + + Please read at least the files install.doc and usage.doc. Useful information + can also be found in the JPEG FAQ (Frequently Asked Questions) article. See + ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. + + If you want to understand how the JPEG code works, we suggest reading one or + more of the REFERENCES, then looking at the documentation files (in roughly + the order listed) before diving into the code. + + + OVERVIEW + ======== + + This package contains C software to implement JPEG image compression and + decompression. JPEG (pronounced "jay-peg") is a standardized compression + method for full-color and gray-scale images. JPEG is intended for compressing + "real-world" scenes; line drawings, cartoons and other non-realistic images + are not its strong suit. JPEG is lossy, meaning that the output image is not + exactly identical to the input image. Hence you must not use JPEG if you + have to have identical output bits. However, on typical photographic images, + very good compression levels can be obtained with no visible change, and + remarkably high compression levels are possible if you can tolerate a + low-quality image. For more details, see the references, or just experiment + with various compression settings. + + This software implements JPEG baseline, extended-sequential, and progressive + compression processes. Provision is made for supporting all variants of these + processes, although some uncommon parameter settings aren't implemented yet. + For legal reasons, we are not distributing code for the arithmetic-coding + variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting + the hierarchical or lossless processes defined in the standard. + + We provide a set of library routines for reading and writing JPEG image files, + plus two sample applications "cjpeg" and "djpeg", which use the library to + perform conversion between JPEG and some other popular image file formats. + The library is intended to be reused in other applications. + + In order to support file conversion and viewing software, we have included + considerable functionality beyond the bare JPEG coding/decoding capability; + for example, the color quantization modules are not strictly part of JPEG + decoding, but they are essential for output to colormapped file formats or + colormapped displays. These extra functions can be compiled out of the + library if not required for a particular application. We have also included + "jpegtran", a utility for lossless transcoding between different JPEG + processes, and "rdjpgcom" and "wrjpgcom", two simple applications for + inserting and extracting textual comments in JFIF files. + + The emphasis in designing this software has been on achieving portability and + flexibility, while also making it fast enough to be useful. In particular, + the software is not intended to be read as a tutorial on JPEG. (See the + REFERENCES section for introductory material.) Rather, it is intended to + be reliable, portable, industrial-strength code. We do not claim to have + achieved that goal in every aspect of the software, but we strive for it. + + We welcome the use of this software as a component of commercial products. + No royalty is required, but we do ask for an acknowledgement in product + documentation, as described under LEGAL ISSUES. + + + LEGAL ISSUES + ============ + + In plain English: + + 1. We don't promise that this software works. (But if you find any bugs, + please let us know!) + 2. You can use this software for whatever you want. You don't have to pay us. + 3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + + In legalese: + + The authors make NO WARRANTY or representation, either express or implied, + with respect to this software, its quality, accuracy, merchantability, or + fitness for a particular purpose. This software is provided "AS IS", and you, + its user, assume the entire risk as to its quality and accuracy. + + This software is copyright (C) 1991-1998, Thomas G. Lane. + All Rights Reserved except as specified below. + + Permission is hereby granted to use, copy, modify, and distribute this + software (or portions thereof) for any purpose, without fee, subject to these + conditions: + (1) If any part of the source code for this software is distributed, then this + README file must be included, with this copyright and no-warranty notice + unaltered; and any additions, deletions, or changes to the original files + must be clearly indicated in accompanying documentation. + (2) If only executable code is distributed, then the accompanying + documentation must state that "this software is based in part on the work of + the Independent JPEG Group". + (3) Permission for use of this software is granted only if the user accepts + full responsibility for any undesirable consequences; the authors accept + NO LIABILITY for damages of any kind. + + These conditions apply to any software derived from or based on the IJG code, + not just to the unmodified library. If you use our work, you ought to + acknowledge us. + + Permission is NOT granted for the use of any IJG author's name or company name + in advertising or publicity relating to this software or products derived from + it. This software may be referred to only as "the Independent JPEG Group's + software". + + We specifically permit and encourage the use of this software as the basis of + commercial products, provided that all warranty or liability claims are + assumed by the product vendor. + + + ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, + sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. + ansi2knr.c is NOT covered by the above copyright and conditions, but instead + by the usual distribution terms of the Free Software Foundation; principally, + that you must include source code if you redistribute it. (See the file + ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part + of any program generated from the IJG code, this does not limit you more than + the foregoing paragraphs do. + + The Unix configuration script "configure" was produced with GNU Autoconf. + It is copyright by the Free Software Foundation but is freely distributable. + The same holds for its supporting scripts (config.guess, config.sub, + ltconfig, ltmain.sh). Another support script, install-sh, is copyright + by M.I.T. but is also freely distributable. + + It appears that the arithmetic coding option of the JPEG spec is covered by + patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot + legally be used without obtaining one or more licenses. For this reason, + support for arithmetic coding has been removed from the free JPEG software. + (Since arithmetic coding provides only a marginal gain over the unpatented + Huffman mode, it is unlikely that very many implementations will support it.) + So far as we are aware, there are no patent restrictions on the remaining + code. + + The IJG distribution formerly included code to read and write GIF files. + To avoid entanglement with the Unisys LZW patent, GIF reading support has + been removed altogether, and the GIF writer has been simplified to produce + "uncompressed GIFs". This technique does not use the LZW algorithm; the + resulting GIF files are larger than usual, but are readable by all standard + GIF decoders. + + We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + + + REFERENCES + ========== + + We highly recommend reading one or more of these references before trying to + understand the innards of the JPEG software. + + The best short technical introduction to the JPEG compression algorithm is + Wallace, Gregory K. "The JPEG Still Picture Compression Standard", + Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. + (Adjacent articles in that issue discuss MPEG motion picture compression, + applications of JPEG, and related topics.) If you don't have the CACM issue + handy, a PostScript file containing a revised version of Wallace's article is + available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually + a preprint for an article that appeared in IEEE Trans. Consumer Electronics) + omits the sample images that appeared in CACM, but it includes corrections + and some added material. Note: the Wallace article is copyright ACM and IEEE, + and it may not be used for commercial purposes. + + A somewhat less technical, more leisurely introduction to JPEG can be found in + "The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by + M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides + good explanations and example C code for a multitude of compression methods + including JPEG. It is an excellent source if you are comfortable reading C + code but don't know much about data compression in general. The book's JPEG + sample code is far from industrial-strength, but when you are ready to look + at a full implementation, you've got one here... + + The best full description of JPEG is the textbook "JPEG Still Image Data + Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published + by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. + The book includes the complete text of the ISO JPEG standards (DIS 10918-1 + and draft DIS 10918-2). This is by far the most complete exposition of JPEG + in existence, and we highly recommend it. + + The JPEG standard itself is not available electronically; you must order a + paper copy through ISO or ITU. (Unless you feel a need to own a certified + official copy, we recommend buying the Pennebaker and Mitchell book instead; + it's much cheaper and includes a great deal of useful explanatory material.) + In the USA, copies of the standard may be ordered from ANSI Sales at (212) + 642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI + doesn't take credit card orders, but Global does.) It's not cheap: as of + 1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% + shipping/handling. The standard is divided into two parts, Part 1 being the + actual specification, while Part 2 covers compliance testing methods. Part 1 + is titled "Digital Compression and Coding of Continuous-tone Still Images, + Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS + 10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of + Continuous-tone Still Images, Part 2: Compliance testing" and has document + numbers ISO/IEC IS 10918-2, ITU-T T.83. + + Some extensions to the original JPEG standard are defined in JPEG Part 3, + a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG + currently does not support any Part 3 extensions. + + The JPEG standard does not specify all details of an interchangeable file + format. For the omitted details we follow the "JFIF" conventions, revision + 1.02. A copy of the JFIF spec is available from: + Literature Department + C-Cube Microsystems, Inc. + 1778 McCarthy Blvd. + Milpitas, CA 95035 + phone (408) 944-6300, fax (408) 944-6314 + A PostScript version of this document is available by FTP at + ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text + version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing + the figures. + + The TIFF 6.0 file format specification can be obtained by FTP from + ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme + found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. + IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). + Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 + (Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or + from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision + of the TIFF spec will replace the 6.0 JPEG design with the Note's design. + Although IJG's own code does not support TIFF/JPEG, the free libtiff library + uses our library to implement TIFF/JPEG per the Note. libtiff is available + from ftp://ftp.sgi.com/graphics/tiff/. + + + ARCHIVE LOCATIONS + ================= + + The "official" archive site for this software is ftp.uu.net (Internet + address 192.48.96.9). The most recent released version can always be found + there in directory graphics/jpeg. This particular version will be archived + as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have + direct Internet access, UUNET's archives are also available via UUCP; contact + help@uunet.uu.net for information on retrieving files that way. + + Numerous Internet sites maintain copies of the UUNET files. However, only + ftp.uu.net is guaranteed to have the latest official version. + + You can also obtain this software in DOS-compatible "zip" archive format from + the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or + on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 + "JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net + release. + + The JPEG FAQ (Frequently Asked Questions) article is a useful source of + general information about JPEG. It is updated constantly and therefore is + not included in this distribution. The FAQ is posted every two weeks to + Usenet newsgroups comp.graphics.misc, news.answers, and other groups. + It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ + and other news.answers archive sites, including the official news.answers + archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. + If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu + with body + send usenet/news.answers/jpeg-faq/part1 + send usenet/news.answers/jpeg-faq/part2 + + + RELATED SOFTWARE + ================ + + Numerous viewing and image manipulation programs now support JPEG. (Quite a + few of them use this library to do so.) The JPEG FAQ described above lists + some of the more popular free and shareware viewers, and tells where to + obtain them on Internet. + + If you are on a Unix machine, we highly recommend Jef Poskanzer's free + PBMPLUS software, which provides many useful operations on PPM-format image + files. In particular, it can convert PPM images to and from a wide range of + other formats, thus making cjpeg/djpeg considerably more useful. The latest + version is distributed by the NetPBM group, and is available from numerous + sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. + Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; + you are likely to have difficulty making it work on any non-Unix machine. + + A different free JPEG implementation, written by the PVRG group at Stanford, + is available from ftp://havefun.stanford.edu/pub/jpeg/. This program + is designed for research and experimentation rather than production use; + it is slower, harder to use, and less portable than the IJG code, but it + is easier to read and modify. Also, the PVRG code supports lossless JPEG, + which we do not. (On the other hand, it doesn't do progressive JPEG.) + + + FILE FORMAT WARS + ================ + + Some JPEG programs produce files that are not compatible with our library. + The root of the problem is that the ISO JPEG committee failed to specify a + concrete file format. Some vendors "filled in the blanks" on their own, + creating proprietary formats that no one else could read. (For example, none + of the early commercial JPEG implementations for the Macintosh were able to + exchange compressed files.) + + The file format we have adopted is called JFIF (see REFERENCES). This format + has been agreed to by a number of major commercial JPEG vendors, and it has + become the de facto standard. JFIF is a minimal or "low end" representation. + We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF + Technical Note #2) for "high end" applications that need to record a lot of + additional data about an image. TIFF/JPEG is fairly new and not yet widely + supported, unfortunately. + + The upcoming JPEG Part 3 standard defines a file format called SPIFF. + SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should + be able to read the most common variant of SPIFF. SPIFF has some technical + advantages over JFIF, but its major claim to fame is simply that it is an + official standard rather than an informal one. At this point it is unclear + whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto + standard. IJG intends to support SPIFF once the standard is frozen, but we + have not decided whether it should become our default output format or not. + (In any case, our decoder will remain capable of reading JFIF indefinitely.) + + Various proprietary file formats incorporating JPEG compression also exist. + We have little or no sympathy for the existence of these formats. Indeed, + one of the original reasons for developing this free software was to help + force convergence on common, open format standards for JPEG files. Don't + use a proprietary file format! + + + TO DO + ===== + + The major thrust for v7 will probably be improvement of visual quality. + The current method for scaling the quantization tables is known not to be + very good at low Q values. We also intend to investigate block boundary + smoothing, "poor man's variable quantization", and other means of improving + quality-vs-file-size performance without sacrificing compatibility. + + In future versions, we are considering supporting some of the upcoming JPEG + Part 3 extensions --- principally, variable quantization and the SPIFF file + format. + + As always, speeding things up is of great interest. + + Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. + +************************************************************************************ +Celt Codec: +************************************************************************************ + + Copyright 2001-2009 Jean-Marc Valin, Timothy B. Terriberry, + CSIRO, and other contributors + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +************************************************************************************ +SPEEX Codes: +************************************************************************************ + SPEEX © 2002-2003, Jean-Marc Valin/Xiph.Org Foundation + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Xiph.org Foundation nor the names of its contributors may be + used to endorse or promote products derived from this software without specific prior + written permission. + This software is provided by the copyright holders and contributors “as is” and any express or + implied warranties, including, but not limited to, the implied warranties of merchantability and + fitness for a particular purpose are disclaimed. In no event shall the foundation or contributors be + liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, + but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or + business interruption) however caused and on any theory of liability, whether in contract, strict + liability, or tort (including negligence or otherwise) arising in any way out of the use of this + software, even if advised of the possibility of such damage. + +************************************************************************************ +google-perftools: +************************************************************************************ + + http://code.google.com/p/gperftools/ + + Copyright (c) 2012, Google Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + For Google libjingle: + http://sourceforge.net/projects/libjingle/ + Copyright (c) 2004--2005, Google Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +************************************************************************************ +CakePHP: +************************************************************************************ + + CakePHP(tm) : Rapid Development Framework + Copyright 2005-2007, Cake Software Foundation, Inc. + 1785 E. Sahara Avenue, Suite 490-204 + Las Vegas, Nevada 89104 + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +************************************************************************************ +LZMA +************************************************************************************ + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. + +************************************************************************************ +Fast Pow Function +************************************************************************************ + + /* + * (c) Ian Stephenson + * + * ian@dctsystems.co.uk + * + * Fast pow() reference implementation + */ + + Used with permission from author + + For libantlr3c: + // [The "BSD licence"] + // Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC + // http://www.temporal-wave.com + // http://www.linkedin.com/in/jimidle + // + // All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // 1. Redistributions of source code must retain the above copyright + // notice, this list of conditions and the following disclaimer. + // 2. Redistributions in binary form must reproduce the above copyright + // notice, this list of conditions and the following disclaimer in the + // documentation and/or other materials provided with the distribution. + // 3. The name of the author may not be used to endorse or promote products + // derived from this software without specific prior written permission. + // + // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +************************************************************************************ +Autodesk® FBX®: +************************************************************************************ + + “This software contains Autodesk® FBX® code developed by Autodesk, Inc. Copyright 2012 Autodesk, Inc. + All rights, reserved. Such code is provided “as is” and Autodesk, Inc. disclaims any and all warranties, + whether express or implied, including without limitation the implied warranties of merchantability, fitness for a + particular purpose or non-infringement of third party rights. In no event shall Autodesk, Inc. be liable for any + direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, + procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however + caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or + otherwise) arising in any way out of such code.” + +************************************************************************************ +OpenSSL: +************************************************************************************ + + * This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/) + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + /* ==================================================================== + * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be + used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * + */ + + + /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an + acknowledgement: + * "This product includes software written by Tim Hudson + (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +************************************************************************************ +Google protocol buffers +************************************************************************************ + + // Protocol Buffers - Google's data interchange format + // Copyright 2008 Google Inc. All rights reserved. + // http://code.google.com/p/protobuf/ + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions are + // met: + // + // * Redistributions of source code must retain the above copyright + // notice, this list of conditions and the following disclaimer. + // * Redistributions in binary form must reproduce the above + // copyright notice, this list of conditions and the following disclaimer + // in the documentation and/or other materials provided with the + // distribution. + // * Neither the name of Google Inc. nor the names of its + // contributors may be used to endorse or promote products derived from + // this software without specific prior written permission. + // + // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + // Author: kenton@google.com (Kenton Varda) + // Based on original Protocol Buffers design by + // Sanjay Ghemawat, Jeff Dean, and others. + +************************************************************************************ +Google Snappy +************************************************************************************ + + // Copyright 2005 Google Inc. All Rights Reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions are + // met: + // + // * Redistributions of source code must retain the above copyright + // notice, this list of conditions and the following disclaimer. + // * Redistributions in binary form must reproduce the above + // copyright notice, this list of conditions and the following disclaimer + // in the documentation and/or other materials provided with the + // distribution. + // * Neither the name of Google Inc. nor the names of its + // contributors may be used to endorse or promote products derived from + // this software without specific prior written permission. + // + // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.