зеркало из https://github.com/mozilla/gecko-dev.git
merged mozilla-central to birch
--HG-- rename : gfx/thebes/GLContextProviderEGL.cpp => gfx/gl/GLContextProviderEGL.cpp rename : embedding/android/AndroidManifest.xml.in => mobile/android/base/AndroidManifest.xml.in
This commit is contained in:
Коммит
b219896cab
|
@ -56,6 +56,7 @@ endif
|
|||
DIRS += pgo
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += autoconf/test
|
||||
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||
DIRS += mobile/sutagent/android \
|
||||
mobile/sutagent/android/watcher \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/env perl
|
||||
#!/usr/bin/env perl
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -16,10 +16,12 @@
|
|||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1999
|
||||
# Portions created by the Initial Developer are Copyright (C) 1999-2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Steve Lamm <slamm@netscape.com>
|
||||
# Joey Armstrong <joey@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -35,29 +37,81 @@
|
|||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# make-makefiles - Quickly create Makefiles for subdirectories.
|
||||
# Also, creates any needed subdirectories.
|
||||
#
|
||||
# usage: make-makefiles [ -t <topsrcdir> -p <print_topsrcdir> -d <depth> ] [ <subdir> | <subdir>/Makefile ] ...
|
||||
##----------------------------##
|
||||
##---] CORE/CPAN INCLUDES [---##
|
||||
##----------------------------##
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
|
||||
# Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
|
||||
use Benchmark;
|
||||
use Cwd;
|
||||
use File::Basename;
|
||||
use File::Copy;
|
||||
use File::Path qw{mkpath};
|
||||
|
||||
#$debug = 1;
|
||||
##-------------------##
|
||||
##---] EXPORTS [---##
|
||||
##-------------------##
|
||||
our $VERSION = qw(2.0);
|
||||
|
||||
if ($^O eq 'msys') {
|
||||
$pwdcmd = 'pwd -W';
|
||||
##--------------------##
|
||||
##---] INCLUDES [---##
|
||||
##--------------------##
|
||||
|
||||
##############################################################
|
||||
# pymake: special case path handling for windows cmd shell.
|
||||
# if invoked by cmd.exe and msys-perl is in play
|
||||
# $0 may contain a drive letter
|
||||
# modules use-or-expect msys/unix paths
|
||||
# adjust $0 => C:/foo => /c/foo so string tests and
|
||||
# manipulation can by applied properly.
|
||||
##############################################################
|
||||
sub BEGIN
|
||||
{
|
||||
if ($^O eq 'msys' && $ENV{PATH} =~ m!\w:/!)
|
||||
{
|
||||
$0 =~ s!^(\w):!/$1!;
|
||||
}
|
||||
eval 'use FindBin';
|
||||
die $@ if ($@);
|
||||
}
|
||||
else {
|
||||
$pwdcmd = 'pwd';
|
||||
|
||||
use lib $FindBin::Bin;
|
||||
use makemakefile;
|
||||
|
||||
##-------------------##
|
||||
##---] GLOBALS [---##
|
||||
##-------------------##
|
||||
my %argv;
|
||||
|
||||
my $t0 = Benchmark->new();
|
||||
sub END
|
||||
{
|
||||
if ($argv{bench})
|
||||
{
|
||||
my $t1 = Benchmark->new();
|
||||
my $delta = timediff($t1, $t0);
|
||||
print STDERR timestr($delta), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
##----------------##
|
||||
##---] MAIN [---##
|
||||
##----------------##
|
||||
umask 0;
|
||||
|
||||
my $debug = $argv{debug} || 0;
|
||||
|
||||
my $pwdcmd = ($^O eq 'msys') ? 'pwd -W' : 'pwd';
|
||||
|
||||
# Determine various tree path variables
|
||||
#
|
||||
($topsrcdir, $ptopsrcdir, $depth, @makefiles) = parse_arguments(@ARGV);
|
||||
my ($topsrcdir, $ptopsrcdir, $depth, @makefiles) = parse_arguments(@ARGV);
|
||||
|
||||
$object_fullpath = `$pwdcmd`;
|
||||
my $object_fullpath = `$pwdcmd`; # Cwd::getcwd()
|
||||
chdir $depth;
|
||||
$object_root = `$pwdcmd`;
|
||||
my $object_root = `$pwdcmd`; # Cwd::getcwd()
|
||||
chomp $object_fullpath;
|
||||
chomp $object_root;
|
||||
|
||||
|
@ -65,24 +119,23 @@ chomp $object_root;
|
|||
# 'make-makefile' was called. For example, if make-makefile was
|
||||
# called from "mozilla/gfx/src", then $source_subdir would be
|
||||
# "gfx/src/".
|
||||
$source_subdir = "$object_fullpath/";
|
||||
my $source_subdir = "$object_fullpath/";
|
||||
my $quoted_object_root = quotemeta($object_root);
|
||||
$source_subdir =~ s|^$quoted_object_root/||;
|
||||
|
||||
# Prefix makefiles with $source_subdir so that paths
|
||||
# will be relative to the top of the object tree.
|
||||
#
|
||||
for $makefile (@makefiles) {
|
||||
my $makefile;
|
||||
for $makefile (@makefiles) { # dead code ?
|
||||
$makefile = "$source_subdir$makefile";
|
||||
}
|
||||
|
||||
create_directories(@makefiles);
|
||||
|
||||
# Find the path to the source directory based on how 'make-makefile'
|
||||
# was invoked. The path is either relative to the object directory
|
||||
# or an absolute path.
|
||||
$given_srcdir = find_srcdir($topsrcdir, $depth);
|
||||
$pgiven_srcdir = find_srcdir($ptopsrcdir, $depth);
|
||||
my $given_srcdir = find_srcdir($topsrcdir, $depth);
|
||||
my $pgiven_srcdir = find_srcdir($ptopsrcdir, $depth);
|
||||
|
||||
if ($debug) {
|
||||
warn "object_fullpath = $object_fullpath\n";
|
||||
|
@ -92,18 +145,21 @@ if ($debug) {
|
|||
warn "given_srcdir = $given_srcdir\n";
|
||||
}
|
||||
|
||||
@unhandled = update_makefiles($given_srcdir, $pgiven_srcdir, @makefiles);
|
||||
my @errors;
|
||||
my @unhandled = update_makefiles_legacy($given_srcdir, $pgiven_srcdir, @makefiles);
|
||||
push(@errors, $@) if ($@);
|
||||
|
||||
run_config_status(@unhandled);
|
||||
push(@errors, $@) if ($@ && $argv{'no-warnings'});
|
||||
|
||||
exit scalar(@errors);
|
||||
|
||||
# end of Main
|
||||
############################################################
|
||||
|
||||
sub dirname {
|
||||
return $_[0] =~ /(.*)\/.*/ ? "$1" : '.';
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# find_depth: Pull the value of DEPTH out of a Makefile (or Makefile.in)
|
||||
###########################################################################
|
||||
sub find_depth {
|
||||
my $depth = '';
|
||||
open(MAKEFILE, "<$_[0]") || die "Unable to open $_[0]: $!\n";
|
||||
|
@ -116,39 +172,115 @@ sub find_depth {
|
|||
return $depth;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
## Intent: Parse command line arguments and assign values
|
||||
###########################################################################
|
||||
sub parse_arguments {
|
||||
my @args = @_;
|
||||
my $depth = '';
|
||||
my $topsrcdir = '';
|
||||
my $ptopsrcdir;
|
||||
my @makefiles = ();
|
||||
|
||||
while (1) {
|
||||
if ($args[0] eq '-d') {
|
||||
$depth = $args[1];
|
||||
shift @args;
|
||||
shift @args;
|
||||
} elsif ($args[0] eq '-t') {
|
||||
$topsrcdir = $args[1];
|
||||
shift @args;
|
||||
shift @args;
|
||||
} elsif ($args[0] eq '-p') {
|
||||
$ptopsrcdir = $args[1];
|
||||
shift @args;
|
||||
shift @args;
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
my @arglist = qw(badtokens! bench
|
||||
chdir=s
|
||||
debug
|
||||
depth|d=s
|
||||
enhanced
|
||||
obj=s top|t=s ptop|p=s
|
||||
src=s dst=s
|
||||
);
|
||||
unless(GetOptions(\%argv, @arglist))
|
||||
{
|
||||
my $script = join('/', $FindBin::RealBin, $FindBin::Script);
|
||||
system("perldoc $script </dev/null");
|
||||
exit
|
||||
}
|
||||
@args = @ARGV;
|
||||
|
||||
my $topsrcdir = $argv{top} || '';
|
||||
if (! $topsrcdir)
|
||||
{
|
||||
$topsrcdir = $argv{top} = getTopDir();
|
||||
}
|
||||
|
||||
if ($topsrcdir eq '') {
|
||||
$topsrcdir = $0; # Figure out topsrcdir based on program name.
|
||||
$topsrcdir =~ s|/?build/autoconf/.*$||;
|
||||
my $ptopsrcdir ||= $argv{ptop} || $topsrcdir || '';
|
||||
|
||||
## Init --no- switch values
|
||||
foreach my $var (qw(badtokens exclusions warnings))
|
||||
{
|
||||
$argv{"no-${var}"} = $argv{$var} || 0;
|
||||
}
|
||||
if ($ptopsrcdir eq '') {
|
||||
$ptopsrcdir = $topsrcdir;
|
||||
# Propogate parsed arguments for module use [--debug, --verbose]
|
||||
while (my($k, $v) = each %argv)
|
||||
{
|
||||
$main::argv{$k} = $v;
|
||||
}
|
||||
if ($depth eq '') {
|
||||
|
||||
if ($argv{chdir})
|
||||
{
|
||||
chdir $argv{chdir} || die "chdir $argv{chdir} failed: $!";
|
||||
}
|
||||
|
||||
##############################################################
|
||||
## Arguments allowing make-makefile to be invoked from $topsrc
|
||||
##############################################################
|
||||
if (!$argv{top} || !$argv{obj})
|
||||
{
|
||||
}
|
||||
## Limit access to container makefiles for now
|
||||
elsif ($argv{enhanced})
|
||||
{
|
||||
my @errors;
|
||||
|
||||
## iterate over @ARGV to preserve original filename for 'unhandled'
|
||||
my @files = map{ getRelPath($_) } @ARGV;
|
||||
|
||||
my $top = getTopDir();
|
||||
my $obj = getObjDir();
|
||||
|
||||
mkdirr(map{ "$obj/$_" } @files);
|
||||
push(@errors, $@) if ($@); # legacy behavior: do not exit with status
|
||||
|
||||
my $exclude = join('/', $FindBin::RealBin, $FindBin::Script);
|
||||
$exclude .= '.excl'; # $argv{exclude}
|
||||
my %exclude = getExclusions($exclude);
|
||||
my @unhandled;
|
||||
foreach my $relpath (@files)
|
||||
{
|
||||
my $rel = join('/', $relpath, 'Makefile.in');
|
||||
my $mf = join('/', $top, $rel);
|
||||
next if ($exclude{$rel});
|
||||
print STDERR " ** relpath=[$relpath], mf=[$mf]\n" if ($main::argv{debug});
|
||||
|
||||
my $rc = updateMakefiles($relpath, {depth=>$depth, obj=>$obj, top=>$top});
|
||||
if ($@)
|
||||
{
|
||||
push(@errors, $@);
|
||||
}
|
||||
elsif ($rc eq 'badtokens')
|
||||
{
|
||||
push(@unhandled, $mf);
|
||||
}
|
||||
}
|
||||
|
||||
run_config_status(@unhandled);
|
||||
push(@errors, $@) if ($@ && $argv{'no-warnings'});
|
||||
exit scalar(@errors);
|
||||
}
|
||||
|
||||
|
||||
my $depth = $argv{depth} || '';
|
||||
if (! $depth)
|
||||
{
|
||||
foreach my $fyl (@args)
|
||||
{
|
||||
if (my $tmp = find_depth($fyl))
|
||||
{
|
||||
$depth = $tmp;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! $depth) {
|
||||
# Use $(DEPTH) in the Makefile or Makefile.in to determine the depth
|
||||
if (-e "Makefile.in") {
|
||||
$depth = find_depth("Makefile.in");
|
||||
|
@ -166,34 +298,21 @@ sub parse_arguments {
|
|||
# Build the list of makefiles to generate
|
||||
#
|
||||
@makefiles = ();
|
||||
my $makefile;
|
||||
foreach $makefile (@args) {
|
||||
$makefile =~ s/\.in$//;
|
||||
$makefile =~ s/\/$//;
|
||||
$makefile =~ /Makefile$/
|
||||
or $makefile =~ /^\.\//
|
||||
or $makefile .= "/Makefile";
|
||||
while (@args)
|
||||
{
|
||||
next unless my $makefile = shift @args;
|
||||
$makefile =~ s/\.in$//;
|
||||
$makefile =~ s/\/$//;
|
||||
$makefile =~ /Makefile$/
|
||||
or $makefile =~ /^\.\//
|
||||
or $makefile .= "/Makefile";
|
||||
push @makefiles, "$makefile";
|
||||
}
|
||||
@makefiles = "Makefile" unless @args;
|
||||
@makefiles = "Makefile" unless @makefiles;
|
||||
|
||||
return ($topsrcdir, $ptopsrcdir, $depth, @makefiles);
|
||||
}
|
||||
|
||||
|
||||
# Create all the directories at once.
|
||||
# This can be much faster than calling mkdir() for each one.
|
||||
sub create_directories {
|
||||
my @makefiles = @_;
|
||||
my @dirs = ();
|
||||
my $ac_file;
|
||||
foreach $ac_file (@makefiles) {
|
||||
push @dirs, dirname($ac_file);
|
||||
}
|
||||
# Call mkdir with the directories sorted by subdir count (how many /'s)
|
||||
system "mkdir -p ". join(' ', map("\"$_\"", @dirs)) if @dirs;
|
||||
}
|
||||
|
||||
# Find the top of the source directory
|
||||
# (Assuming that the executable is in $top_srcdir/build/autoconf)
|
||||
sub find_srcdir {
|
||||
|
@ -214,111 +333,146 @@ sub find_srcdir {
|
|||
return $ac_given_srcdir;
|
||||
}
|
||||
|
||||
# Output the makefiles.
|
||||
#
|
||||
sub update_makefiles {
|
||||
my ($ac_given_srcdir, $pac_given_srcdir, @makefiles) = @_;
|
||||
my @unhandled=();
|
||||
1;
|
||||
###########################################################################
|
||||
## perldoc
|
||||
###########################################################################
|
||||
__END__
|
||||
|
||||
my $ac_file;
|
||||
foreach $ac_file (@makefiles) {
|
||||
my $ac_file_in = "$ac_given_srcdir/${ac_file}.in";
|
||||
my $ac_dir = dirname($ac_file);
|
||||
my $ac_dots = '';
|
||||
my $ac_dir_suffix = '';
|
||||
my $srcdir = '.';
|
||||
my $top_srcdir = '.';
|
||||
=head1 NAME
|
||||
|
||||
# Determine $srcdir and $top_srcdir
|
||||
#
|
||||
if ($ac_dir ne '.') {
|
||||
$ac_dir_suffix = "/$ac_dir";
|
||||
$ac_dir_suffix =~ s%^/\./%/%;
|
||||
$ac_dots = $ac_dir_suffix;
|
||||
# Remove .. components from the provided dir suffix, and
|
||||
# also the forward path components they were reversing.
|
||||
my $backtracks = $ac_dots =~ s%\.\.(/|$)%%g;
|
||||
while ($backtracks--) {
|
||||
$ac_dots =~ s%/[^/]*%%;
|
||||
}
|
||||
$ac_dots =~ s%/[^/]*%../%g;
|
||||
}
|
||||
if ($ac_given_srcdir eq '.') {
|
||||
if ($ac_dots ne '') {
|
||||
$top_srcdir = $ac_dots;
|
||||
$top_srcdir =~ s%/$%%;
|
||||
}
|
||||
} elsif ($pac_given_srcdir =~ m%^/% or $pac_given_srcdir =~ m%^.:/%) {
|
||||
$srcdir = "$pac_given_srcdir$ac_dir_suffix";
|
||||
$top_srcdir = "$pac_given_srcdir";
|
||||
} else {
|
||||
if ($debug) {
|
||||
print "ac_dots = $ac_dots\n";
|
||||
print "ac_dir_suffix = $ac_dir_suffix\n";
|
||||
}
|
||||
$srcdir = "$ac_dots$ac_given_srcdir$ac_dir_suffix";
|
||||
$top_srcdir = "$ac_dots$ac_given_srcdir";
|
||||
}
|
||||
make-makefile - Generate a Makefile from a F<Makefile.in> template
|
||||
|
||||
if ($debug) {
|
||||
print "ac_dir = $ac_dir\n";
|
||||
print "ac_file = $ac_file\n";
|
||||
print "ac_file_in = $ac_file_in\n";
|
||||
print "srcdir = $srcdir\n";
|
||||
print "top_srcdir = $top_srcdir\n";
|
||||
print "cwd = " . `$pwdcmd` . "\n";
|
||||
}
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# Copy the file and make substitutions.
|
||||
# @srcdir@ -> value of $srcdir
|
||||
# @top_srcdir@ -> value of $top_srcdir
|
||||
#
|
||||
if (-e $ac_file) {
|
||||
next if -M _ < -M $ac_file_in; # Next if Makefile is up-to-date.
|
||||
warn "updating $ac_file\n";
|
||||
} else {
|
||||
warn "creating $ac_file\n";
|
||||
}
|
||||
make-makefile [--top t] [--obj o] [--depth d] foo/bar/Makefile.in tans/fans/Makefile foo/bar
|
||||
|
||||
open INFILE, "<$ac_file_in" or do {
|
||||
warn "$0: Cannot read $ac_file_in: No such file or directory\n";
|
||||
next;
|
||||
};
|
||||
open OUTFILE, ">$ac_file" or do {
|
||||
warn "$0: Unable to create $ac_file\n";
|
||||
next;
|
||||
};
|
||||
=head1 DESCRIPTION
|
||||
|
||||
while (<INFILE>) {
|
||||
#if (/\@[_a-zA-Z]*\@.*\@[_a-zA-Z]*\@/) {
|
||||
# #warn "Two defines on a line:$ac_file:$.:$_";
|
||||
# push @unhandled, $ac_file;
|
||||
# last;
|
||||
#}
|
||||
Given options and makefile path arguments determine path to the template
|
||||
F<Makefile.in> beneath a source directory and path to generated F<Makefile>
|
||||
beneath $MOZ_OBJDIR. DEPTH from destination directory to the 'root' will
|
||||
also be determined. F<Makefile.in> will be read in, template strings of the
|
||||
gorm @token@ will be replaced with derived values and a generated makefile
|
||||
will be written out as F<Makefile>.
|
||||
|
||||
s/\@srcdir\@/$srcdir/g;
|
||||
s/\@top_srcdir\@/$top_srcdir/g;
|
||||
Makefile DEPTH= can be determined in a few different ways:
|
||||
o The string C<DEPTH=../../..> may be embedded within F<Makefile.in>.
|
||||
o Search parent directories for F<Makefile.in> and use it to assign the child.
|
||||
|
||||
if (/\@[_a-zA-Z]*\@/) {
|
||||
#warn "Unknown variable:$ac_file:$.:$_";
|
||||
push @unhandled, $ac_file;
|
||||
last;
|
||||
}
|
||||
print OUTFILE;
|
||||
}
|
||||
close INFILE;
|
||||
close OUTFILE;
|
||||
}
|
||||
return @unhandled;
|
||||
}
|
||||
|
||||
sub run_config_status {
|
||||
my @unhandled = @_;
|
||||
=head2 Option List
|
||||
|
||||
# Run config.status with any unhandled files.
|
||||
#
|
||||
if (@unhandled) {
|
||||
$ENV{CONFIG_FILES}= join ' ', @unhandled;
|
||||
system "./config.status";
|
||||
}
|
||||
}
|
||||
=over 4
|
||||
|
||||
=item --chdir
|
||||
|
||||
Move to this directory before doing anything else
|
||||
|
||||
=item -d, --depth
|
||||
|
||||
Explicitly specify the relative path from directory containing Makefile.in
|
||||
to the top sandbox directory. memory/makefile, DEPTH=../.., js/src/config, DEPTH=..
|
||||
|
||||
=item --enhanced
|
||||
|
||||
Use alternate/simplified path construction when options --top and --obj are
|
||||
passed. This feature will be used by container makefiles to support makefile
|
||||
generation while cd'd into the sandbox top directory.
|
||||
|
||||
=item -t, --top
|
||||
|
||||
Path the root of a development sandbox.
|
||||
|
||||
=item --obj
|
||||
|
||||
Path to object directory where generated makefile will be written ($MOZ_OBJDIR).
|
||||
|
||||
=item --ptop
|
||||
|
||||
Print top source dir
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Options List DEBUG
|
||||
|
||||
=over 4
|
||||
|
||||
=item --bench
|
||||
|
||||
Enable script benchmarking, report elapsed runtime.
|
||||
|
||||
=item --debug
|
||||
|
||||
Enable script debug mode.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Options List --NO-
|
||||
|
||||
=over 4
|
||||
|
||||
=item --no-badtokens (wip)
|
||||
|
||||
Handle unexpanded @token@ makefile tokens as an error condition.
|
||||
Do not rely on system(config.status) to externally supply values.
|
||||
|
||||
=item --no-excludes
|
||||
|
||||
Ignore file entries on the exclusion list, generate everything.
|
||||
|
||||
=item --no-warnings
|
||||
|
||||
Warnings are handled as an error condition.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Examples
|
||||
|
||||
=over 4
|
||||
|
||||
=item * make-makefile -t /mozilla/nightly -d . memory/mozalloc
|
||||
|
||||
cd $MOZ_OBJDIR;
|
||||
--top and --depth are explicitly set for generting memory/mozalloc/Makefile.
|
||||
|
||||
=item * make-makefile -t /mozilla/nightly -d ../../../.. html5lib_tree_construction/Makefile
|
||||
|
||||
cd $MOZ_OBJDIR/parser/htmlparser/tests/mochitest
|
||||
|
||||
--top and --depth are explicitly set for generting a makefile from within
|
||||
a subdirectory of $MOZ_OBJDIR
|
||||
|
||||
=item * make-makefile --top /mozilla/nightly --obj /mozilla/nightly/obj memory/mozalloc
|
||||
|
||||
With --top and --obj explicitly set generate $MOZ_OBJDIR/memory/mozalloc/Makefile
|
||||
while sitting in the sandbox root.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Work In Progress
|
||||
|
||||
=over 4
|
||||
|
||||
=item --no-badtokens
|
||||
|
||||
Fail on unexpanded @foo@ makefile tokens. Any tokens that can be expanded
|
||||
directly by make-makefile will avoid config.status shell overhead.
|
||||
|
||||
=item Depth from delta(--obj, --top)
|
||||
|
||||
If DEPTH= has not been embedded within a makefile the value could
|
||||
be set directly if --top and --obj are specified and the paths overlap.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<config/rules.mk>
|
||||
|
||||
=cut
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
###########################################################################
|
||||
## Intent: Exclusion list for container make builds
|
||||
###########################################################################
|
||||
|
||||
# EOF
|
|
@ -0,0 +1,745 @@
|
|||
package makemakefile;
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1999-2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Steve Lamm <slamm@netscape.com>
|
||||
# Joey Armstrong <joey@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
##----------------------------##
|
||||
##---] CORE/CPAN INCLUDES [---##
|
||||
##----------------------------##
|
||||
use strict;
|
||||
use warnings;
|
||||
# use feature 'state'; 5.10+ not available everywhere
|
||||
|
||||
##-------------------##
|
||||
##---] EXPORTS [---##
|
||||
##-------------------##
|
||||
our $VERSION = qw(2.0);
|
||||
use Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(dirname_legacy
|
||||
getConfig getDepth getRelPath getObjDir getTopDir mkdirr
|
||||
getExclusions
|
||||
run_config_status
|
||||
updateMakefiles
|
||||
update_makefiles_legacy
|
||||
);
|
||||
|
||||
##--------------------##
|
||||
##---] INCLUDES [---##
|
||||
##--------------------##
|
||||
use Cwd;
|
||||
use Cwd qw{abs_path};
|
||||
use FindBin;
|
||||
use File::Basename;
|
||||
use File::Copy;
|
||||
|
||||
##-------------------##
|
||||
##---] GLOBALS [---##
|
||||
##-------------------##
|
||||
umask 0;
|
||||
my $cwd = Cwd::abs_path('.');
|
||||
my %argv;
|
||||
|
||||
|
||||
###########################################################################
|
||||
## Intent: Helper function, retrieve contents of a file with error checking
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## scalar path to input file
|
||||
## Returns:
|
||||
## array contents of the given file
|
||||
## $@ set on error
|
||||
###########################################################################
|
||||
sub cat
|
||||
{
|
||||
my $fyl = shift || '';
|
||||
$@ = '';
|
||||
my @data;
|
||||
|
||||
local *FYL;
|
||||
if (!open(FYL, $fyl))
|
||||
{
|
||||
$@ = "open($fyl) failed: $!";
|
||||
}
|
||||
else
|
||||
{
|
||||
@data = <FYL>;
|
||||
close(FYL);
|
||||
}
|
||||
return @data;
|
||||
} # cat
|
||||
|
||||
###########################################################################
|
||||
## Intent: Return directory path for a given argument
|
||||
## -----------------------------------------------------------------------
|
||||
## -----------------------------------------------------------------------
|
||||
## Todo:
|
||||
## o Check if function can be replaced by File::Basename::dirname()
|
||||
###########################################################################
|
||||
sub dirname_legacy
|
||||
{
|
||||
my $str = (@_ && defined($_[0])) ? shift : '';
|
||||
return $str =~ /(.*)\/.*/ ? "$1" : '.';
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
## Intent: Given a list of makefile paths recursively create all
|
||||
## directories between file and the root
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## array A list of makefiles
|
||||
## fargs Function arguments
|
||||
## mode Filesystem mode used for directory creation
|
||||
## Returns:
|
||||
## $@ Set on error
|
||||
## 0 on success
|
||||
## -----------------------------------------------------------------------
|
||||
## Note:
|
||||
## Reporting directory creation can be enabled by the --verbose
|
||||
## command line argument.
|
||||
###########################################################################
|
||||
sub mkdirr
|
||||
{
|
||||
my %fargs = (@_ && ref($_[$#_])) ? %{ (pop) } : ();
|
||||
my $mode = $fargs{mode} || 0755;
|
||||
my $verbose = $main::argv{verbose} || 0;
|
||||
$@ = '' unless ($fargs{recursive});
|
||||
$fargs{recursive} = 1;
|
||||
|
||||
my @errors;
|
||||
push(@errors, $@) if ($@);
|
||||
foreach my $path (@_)
|
||||
{
|
||||
(my $dir = $path) =~ s%/?Makefile[^/]*$%%o;
|
||||
next unless (length($dir));
|
||||
next if (-e $dir);
|
||||
mkdirr( dirname($dir), \%fargs);
|
||||
eval{ File::Path::mkpath($dir, $verbose, 0755); };
|
||||
push(@errors, $@) if ($@);
|
||||
}
|
||||
$@ = join("\n", @errors);
|
||||
return $@ ? 0 : 1;
|
||||
} # mkdirr
|
||||
|
||||
###########################################################################
|
||||
## Intent: Read in configure values and return a hash of key/value pairs
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## fargs Function arguments
|
||||
## reset clear value storage and repopulate
|
||||
## Returns:
|
||||
## hash configure data to use for makefile substitutions
|
||||
## -----------------------------------------------------------------------
|
||||
## Todo: wrapper for reading config* and run_config_status
|
||||
###########################################################################
|
||||
my %_CONFIG_; # todo: state %config; w/5.10
|
||||
sub getConfig
|
||||
{
|
||||
my %fargs = (@_ && ref($_[$#_]) eq 'HASH') ? %{ (pop) } : ();
|
||||
if ($fargs{reset})
|
||||
{
|
||||
%_CONFIG_ = ();
|
||||
shift;
|
||||
}
|
||||
|
||||
#my $ac_file_in = "$ac_given_srcdir/${ac_file}.in";
|
||||
#my $ac_dir = dirname_legacy($ac_file);
|
||||
#my $ac_dots = '';
|
||||
#my $ac_dir_suffix = '';
|
||||
#my $srcdir = '.';
|
||||
#my $top_srcdir = '.';
|
||||
unless (%_CONFIG_)
|
||||
{
|
||||
while (@_)
|
||||
{
|
||||
my ($k, $v) = splice(@_, 0, 2);
|
||||
$_CONFIG_{$k} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return %_CONFIG_;
|
||||
} # getConfig
|
||||
|
||||
###########################################################################
|
||||
## Intent: Determine path depth between leaf and root directory.
|
||||
## o DEPTH= may be set by makefile content
|
||||
## o DEPTH= may be set by Makefile in a parent
|
||||
## o Manually determine by relpath form leaf to sandbox top
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## scalar Path to makefile or directory to determine DEPTH for
|
||||
## Returns:
|
||||
## scalar Relative path from leaf to root directory
|
||||
## -----------------------------------------------------------------------
|
||||
###########################################################################
|
||||
sub getDepth($)
|
||||
{
|
||||
my $fyl = shift || '';
|
||||
|
||||
my @path = split(m%/%o, $fyl);
|
||||
pop(@path) if ('Makefile' eq substr($path[$#path], 0, 8));
|
||||
my $depth;
|
||||
my @depth;
|
||||
|
||||
my $top = getTopDir();
|
||||
my @top = split(m%/%o, $top);
|
||||
my @pathNoTop = @path;
|
||||
splice(@pathNoTop, 0, scalar(@top));
|
||||
|
||||
SEARCH:
|
||||
while (@path)
|
||||
{
|
||||
## Search for a file containing DEPTH=../..
|
||||
foreach my $fyl ( qw{Makefile.in Makefile} )
|
||||
{
|
||||
my $path = join('/', @path, $fyl);
|
||||
local *FYL;
|
||||
if (!open(FYL, $path)) {} # NOP
|
||||
elsif (my @tmp = map{ /^\s*DEPTH\s*=\s*([\.\/]+)/o ? $1 : () } <FYL>)
|
||||
{
|
||||
$depth = join('/', @depth, shift @tmp);
|
||||
last SEARCH;
|
||||
}
|
||||
close(FYL);
|
||||
}
|
||||
pop @path;
|
||||
pop @pathNoTop;
|
||||
|
||||
if (0 == scalar(@pathNoTop))
|
||||
{
|
||||
$depth = join('/', @depth);
|
||||
last;
|
||||
}
|
||||
|
||||
## Construct path manually
|
||||
push(@depth, '..');
|
||||
}
|
||||
return $depth;
|
||||
} # getDepth
|
||||
|
||||
###########################################################################
|
||||
## Intent: Read in the exclusion file
|
||||
###########################################################################
|
||||
sub getExclusions
|
||||
{
|
||||
my $file = shift || '';
|
||||
|
||||
return () if ($main::argv{'no-exclusions'});
|
||||
|
||||
my %exclude;
|
||||
if ($file)
|
||||
{
|
||||
my @data = cat($file);
|
||||
foreach (@data)
|
||||
{
|
||||
next unless ($_);
|
||||
next if (/^\s*\#/o);
|
||||
next unless (m%/%);
|
||||
chomp;
|
||||
$exclude{$_}++;
|
||||
}
|
||||
}
|
||||
return %exclude;
|
||||
} # getExclusions
|
||||
|
||||
###########################################################################
|
||||
## Intent: Given the path to a makefile beneath either src or obj
|
||||
## derive the relative path prefix between makefile and root.
|
||||
###########################################################################
|
||||
sub getRelPath
|
||||
{
|
||||
my $path0 = shift;
|
||||
my $abspath;
|
||||
|
||||
# Determine type and orientation
|
||||
my $name = basename($path0);
|
||||
my $haveMF = ($name eq 'Makefile.in') ? 1
|
||||
: ($name eq 'Makefile') ? -1
|
||||
: 0
|
||||
;
|
||||
|
||||
####################################################
|
||||
## Prep work: form a relative path with ../ removed
|
||||
####################################################
|
||||
my $top = getTopDir();
|
||||
my $obj = getObjDir();
|
||||
## If the same Makefile will be created alongside Makefile.in
|
||||
my $topQM = quotemeta($top);
|
||||
my $objQM = quotemeta($obj);
|
||||
|
||||
if ('..' eq substr($path0, 0, 2))
|
||||
{
|
||||
my @cwd = split(m%/%, $cwd);
|
||||
my @pth = split(m%/%, $path0);
|
||||
while (@pth && $pth[0] eq '..')
|
||||
{
|
||||
pop(@cwd);
|
||||
shift @pth;
|
||||
}
|
||||
$path0 = join('/', @cwd, @pth);
|
||||
$abspath = $path0;
|
||||
}
|
||||
|
||||
if ('/' eq substr($path0, 0, 1))
|
||||
{
|
||||
$path0 =~ s%^$objQM\/?%%;
|
||||
$path0 =~ s%^$topQM\/?%%;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
## Build a list of directories to search. Input source will be one
|
||||
## of path to Makefile.in, path to Makefile, directory, file within
|
||||
## a directory or relative path from cwd.
|
||||
#######################################################################
|
||||
my @subdirs;
|
||||
my $path = (0 == $haveMF) ? $path0 : dirname($path0);
|
||||
push(@subdirs, $path); # containing directory
|
||||
push(@subdirs, dirname($path)) if (0 == $haveMF && -f $path); # Arg is file within a directory
|
||||
push(@subdirs, $cwd); # relative to pwd
|
||||
|
||||
# obj - path to generated makefile
|
||||
# top - path to Makefile.in source template
|
||||
my @prefixes = ('/' ne substr($path0, 0, 1))
|
||||
? (&getTopDir, &getObjDir)
|
||||
: ()
|
||||
;
|
||||
|
||||
ON_SAFARI:
|
||||
for my $prefix (@prefixes)
|
||||
{
|
||||
next unless ($prefix); # no command line not passed
|
||||
foreach my $subdir (@subdirs)
|
||||
{
|
||||
foreach my $mf ('Makefile.in', 'Makefile')
|
||||
{
|
||||
my $path = join('/', $prefix, $subdir, $mf);
|
||||
if (-e $path)
|
||||
{
|
||||
$name = $mf;
|
||||
$haveMF = ($mf eq 'Makefile.in') ? 1 : -1;
|
||||
$abspath = $path;
|
||||
last ON_SAFARI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
## Generated makefile does not yet exist or path is invalid.
|
||||
## Should this conditon be handled to detect non-existent Makefile.in:
|
||||
## Makefile.am => Makefile.in => Makefile but Makefile.in
|
||||
#######################################################################
|
||||
if (!$abspath && -1 == $haveMF && $obj)
|
||||
{
|
||||
$abspath = ('/' eq substr($path0, 0, 1))
|
||||
? $path0
|
||||
: join('/', $obj, $path0)
|
||||
;
|
||||
}
|
||||
|
||||
########################################################
|
||||
## If --top and/or --obj specified extract relative path
|
||||
########################################################
|
||||
my $relpath;
|
||||
if (! $abspath)
|
||||
{
|
||||
# Error, fall through
|
||||
}
|
||||
elsif (1 == $haveMF) # Makefile.in
|
||||
{
|
||||
## err w/o --top
|
||||
(my $tmp = $abspath) =~ s%^$topQM/?%%;
|
||||
$relpath = dirname($tmp) unless ($tmp eq $abspath);
|
||||
}
|
||||
elsif (-1 == $haveMF) # Makefile
|
||||
{
|
||||
## err w/o --obj
|
||||
(my $tmp = $abspath) =~ s%^$objQM/?%%;
|
||||
$relpath = dirname($tmp) unless ($tmp eq $abspath);
|
||||
}
|
||||
|
||||
$relpath ||= '';
|
||||
$relpath =~ s%/./%/%og; # filter ./
|
||||
|
||||
$@ = ($relpath) ? '' : "ERROR($path0): Unable to locate sources";
|
||||
return $relpath || '';
|
||||
} # getRelPath
|
||||
|
||||
###########################################################################
|
||||
## Intent: Determine sandbox root from script startup directory
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## _set_ optional, if passed use the given value as path
|
||||
## _reset_ clear cached directory path to reassign
|
||||
## Returns:
|
||||
## scalar - absolute path to the sandbox root directory
|
||||
## -----------------------------------------------------------------------
|
||||
###########################################################################
|
||||
my $gtd_dir;
|
||||
sub getTopDir
|
||||
{
|
||||
if (@_) # testing override
|
||||
{
|
||||
$gtd_dir = abs_path($_[1] || '.') if ($_[0] eq '_set_');
|
||||
$gtd_dir = '' if ($_[0] eq '_reset_');
|
||||
}
|
||||
|
||||
unless ($gtd_dir)
|
||||
{
|
||||
## Set by command line
|
||||
if ($main::argv{top})
|
||||
{
|
||||
$gtd_dir = $main::argv{top};
|
||||
}
|
||||
else
|
||||
{
|
||||
my $path = abs_path($FindBin::RealBin);
|
||||
my @path = split(m%/%o, $path);
|
||||
## --2 memory/mozalloc/Makefile.in
|
||||
## --3 was this for FindBin::Script ?
|
||||
splice(@path, -2);
|
||||
$gtd_dir = join('/', @path);
|
||||
}
|
||||
}
|
||||
return $gtd_dir;
|
||||
} # getTopDir
|
||||
|
||||
###########################################################################
|
||||
## Intent: Determine path to MOZ_OBJDIR/object directory
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## _set_ optional testing arg, if passed re-compute cached value
|
||||
## Returns:
|
||||
## scalar - absolute path to the sandbox object directory
|
||||
## -----------------------------------------------------------------------
|
||||
###########################################################################
|
||||
my $god_dir;
|
||||
sub getObjDir
|
||||
{
|
||||
if (@_) # testing override
|
||||
{
|
||||
if ($_[0] eq '_reset_')
|
||||
{
|
||||
$god_dir = '';
|
||||
shift;
|
||||
}
|
||||
elsif ($_[0] eq '_set_')
|
||||
{
|
||||
shift;
|
||||
my $path = $_[0] || '.';
|
||||
$god_dir = abs_path($path);
|
||||
shift;
|
||||
}
|
||||
}
|
||||
|
||||
## extract $obj from given path
|
||||
unless ($god_dir)
|
||||
{
|
||||
if ($main::argv{obj})
|
||||
{
|
||||
$god_dir = $main::argv{obj};
|
||||
}
|
||||
elsif (@_ && 'Makefile' eq substr($_, -8))
|
||||
{
|
||||
$god_dir = abs_path(shift);
|
||||
}
|
||||
else # assume we are sitting in moz_objdir
|
||||
{
|
||||
$god_dir = abs_path('.');
|
||||
}
|
||||
}
|
||||
|
||||
return $god_dir;
|
||||
} # getObjDir
|
||||
|
||||
###########################################################################
|
||||
## Intent: Generate Makefile from a given Makefile.in template
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## scalar Relative path to a directory containing a makefile
|
||||
## fargs Hash ref of function arguments.
|
||||
## obj Absolute path to MOZ_OBJ/a destination directory
|
||||
## top Absolute path to the sandbox root
|
||||
## Returns:
|
||||
## $@ Set on error
|
||||
## scalar
|
||||
## 1 True if the makefile was updated
|
||||
## 0 Otherwise
|
||||
## badtokens - If the makefile contains unexpandable @token@ strings
|
||||
## -----------------------------------------------------------------------
|
||||
###########################################################################
|
||||
sub updateMakefiles
|
||||
{
|
||||
my %fargs = (@_ && ref($_[$#_])) ? %{ (pop) } : ();
|
||||
local $_;
|
||||
$@ = '';
|
||||
|
||||
my $top = $fargs{top};
|
||||
my $obj = $fargs{obj};
|
||||
|
||||
my $relpath = shift || '';
|
||||
my $src = join('/', $top, $relpath, 'Makefile.in');
|
||||
my $depth = getDepth($src);
|
||||
|
||||
my @src = cat($src);
|
||||
return 0 if ($@);
|
||||
|
||||
my $dst = join('/', $obj, $relpath, 'Makefile');
|
||||
my @dst = cat($dst);
|
||||
$@ = '';
|
||||
|
||||
my $dstD = dirname($dst);
|
||||
mkdirr($dstD);
|
||||
return 0 if ($@);
|
||||
|
||||
my %data =
|
||||
( getConfig(),
|
||||
depth => $depth,
|
||||
srcdir => join('/', $top, $relpath),
|
||||
top_srcdir => $top,
|
||||
);
|
||||
|
||||
my $line = 0;
|
||||
my @data;
|
||||
while (scalar @src)
|
||||
{
|
||||
$line++;
|
||||
$_ = shift(@src);
|
||||
|
||||
## Expand embedded @foo@
|
||||
while (/\@[^\@\s\$]+\@/go)
|
||||
{
|
||||
my $end = pos($_);
|
||||
my $val = $&;
|
||||
my $len = length($val);
|
||||
$val =~ s/^\@\s*//o;
|
||||
$val =~ s/\s*\@$//o;
|
||||
|
||||
## Identify expansions to see if we can avoid shell overhead
|
||||
if (!defined $data{$val} && !$argv{'no-badtokens'})
|
||||
{
|
||||
if (1) # warnings
|
||||
{
|
||||
print STDERR "WARNING: token $val not defined\n";
|
||||
print STDERR " line $line, src: $src\n";
|
||||
}
|
||||
return 'badtokens';
|
||||
}
|
||||
|
||||
# Insert $(error txt) makefile macros for invalid tokens
|
||||
my $val1 = defined($data{$val})
|
||||
? $data{$val}
|
||||
: "\$(error $FindBin::Script: variable ${val} is undefined)"
|
||||
;
|
||||
substr($_, ($end-$len), $len, $val1);
|
||||
}
|
||||
push(@data, $_);
|
||||
}
|
||||
|
||||
if (("@data" eq "@dst") && scalar(@data))
|
||||
{
|
||||
print "Skipping up2date makefile: $dst\n" if ($argv{verbose});
|
||||
}
|
||||
else
|
||||
{
|
||||
my $action = (scalar @dst) ? 'Updating' : 'Creating';
|
||||
print "$action makefile: $dst\n";
|
||||
|
||||
my $tmp = join('.', $dst, "tmp_$$");
|
||||
if (!open(FYL, "> $tmp"))
|
||||
{
|
||||
$@ = "open($tmp) failed: $!";
|
||||
}
|
||||
else
|
||||
{
|
||||
print FYL @data;
|
||||
close(FYL);
|
||||
|
||||
## Install the new makefile
|
||||
File::Copy::move($tmp, $dst)
|
||||
|| ($@ = "move($tmp, $dst) failed: $!");
|
||||
}
|
||||
}
|
||||
|
||||
return $@ ? 0 : 1;
|
||||
} # updateMakefiles
|
||||
|
||||
# Output the makefiles.
|
||||
#
|
||||
sub update_makefiles_legacy {
|
||||
my ($ac_given_srcdir, $pac_given_srcdir, @makefiles) = @_;
|
||||
my $debug = $main::argv{debug} || 0;
|
||||
my $pwdcmd = ($^O eq 'msys') ? 'pwd -W' : 'pwd';
|
||||
my @unhandled=();
|
||||
|
||||
my @warn;
|
||||
|
||||
my $ac_file;
|
||||
foreach $ac_file (@makefiles) {
|
||||
my $ac_file_in = "$ac_given_srcdir/${ac_file}.in";
|
||||
my $ac_dir = dirname_legacy($ac_file);
|
||||
my $ac_dots = '';
|
||||
my $ac_dir_suffix = '';
|
||||
my $srcdir = '.';
|
||||
my $top_srcdir = '.';
|
||||
|
||||
# Determine $srcdir and $top_srcdir
|
||||
#
|
||||
if ($ac_dir ne '.') {
|
||||
$ac_dir_suffix = "/$ac_dir";
|
||||
$ac_dir_suffix =~ s%^/\./%/%;
|
||||
$ac_dots = $ac_dir_suffix;
|
||||
# Remove .. components from the provided dir suffix, and
|
||||
# also the forward path components they were reversing.
|
||||
my $backtracks = $ac_dots =~ s%\.\.(/|$)%%g;
|
||||
while ($backtracks--) {
|
||||
$ac_dots =~ s%/[^/]*%%;
|
||||
}
|
||||
$ac_dots =~ s%/[^/]*%../%g;
|
||||
}
|
||||
if ($ac_given_srcdir eq '.') {
|
||||
if ($ac_dots ne '') {
|
||||
$top_srcdir = $ac_dots;
|
||||
$top_srcdir =~ s%/$%%;
|
||||
}
|
||||
} elsif ($pac_given_srcdir =~ m%^/% or $pac_given_srcdir =~ m%^.:/%) {
|
||||
$srcdir = "$pac_given_srcdir$ac_dir_suffix";
|
||||
$top_srcdir = "$pac_given_srcdir";
|
||||
} else {
|
||||
if ($debug) {
|
||||
print "ac_dots = $ac_dots\n";
|
||||
print "ac_dir_suffix = $ac_dir_suffix\n";
|
||||
}
|
||||
$srcdir = "$ac_dots$ac_given_srcdir$ac_dir_suffix";
|
||||
$top_srcdir = "$ac_dots$ac_given_srcdir";
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
print "ac_dir = $ac_dir\n";
|
||||
print "ac_file = $ac_file\n";
|
||||
print "ac_file_in = $ac_file_in\n";
|
||||
print "srcdir = $srcdir\n";
|
||||
print "top_srcdir = $top_srcdir\n";
|
||||
print "cwd = " . `$pwdcmd` . "\n";
|
||||
}
|
||||
|
||||
# Copy the file and make substitutions.
|
||||
# @srcdir@ -> value of $srcdir
|
||||
# @top_srcdir@ -> value of $top_srcdir
|
||||
#
|
||||
if (-e $ac_file) {
|
||||
next if -M _ < -M $ac_file_in; # Next if Makefile is up-to-date.
|
||||
warn "updating $ac_file\n";
|
||||
} else {
|
||||
warn "creating $ac_file\n";
|
||||
}
|
||||
|
||||
mkdirr(dirname($ac_file));
|
||||
|
||||
open INFILE, "<$ac_file_in" or do {
|
||||
warn "$0: Cannot read $ac_file_in: No such file or directory\n";
|
||||
next;
|
||||
};
|
||||
open OUTFILE, ">$ac_file" or do {
|
||||
warn "$0: Unable to create $ac_file\n";
|
||||
next;
|
||||
};
|
||||
|
||||
while (<INFILE>) {
|
||||
s/\@srcdir\@/$srcdir/g;
|
||||
s/\@top_srcdir\@/$top_srcdir/g;
|
||||
|
||||
if (/\@[_a-zA-Z]*\@/) {
|
||||
#warn "Unknown variable:$ac_file:$.:$_";
|
||||
push @unhandled, $ac_file;
|
||||
last;
|
||||
}
|
||||
print OUTFILE;
|
||||
}
|
||||
close INFILE;
|
||||
close OUTFILE;
|
||||
}
|
||||
return @unhandled;
|
||||
} # update_makefiles_legacy
|
||||
|
||||
###########################################################################
|
||||
## Intent: Invoke config.status for unknown makefiles to create
|
||||
## directory hierarchy for the tree.
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## array an optional list of makefiles to process
|
||||
## Returns:
|
||||
## 0 on success
|
||||
## $# set on error
|
||||
## -----------------------------------------------------------------------
|
||||
## Note: Is this function needed anymore ? Undefined tokens should fail
|
||||
## at time of expansion rather than having to source config.status.
|
||||
## Also config.status could be parsed to define values and avoide the
|
||||
## shell overhead altogether.
|
||||
###########################################################################
|
||||
sub run_config_status {
|
||||
my @unhandled = @_;
|
||||
|
||||
# Run config.status with any unhandled files.
|
||||
#
|
||||
my @errors;
|
||||
if (@unhandled) {
|
||||
local $ENV{CONFIG_FILES}= join ' ', @unhandled;
|
||||
|
||||
my $conf = 'config.status';
|
||||
if (! -e $conf) # legacy behavior, warn rather than err
|
||||
{
|
||||
my $cwd = cwd();
|
||||
my $err = "$FindBin::Script ERROR: Config file $conf does not exist, cwd=$cwd";
|
||||
push(@errors, $err);
|
||||
}
|
||||
elsif (0 != system("./config.status"))
|
||||
{
|
||||
my $cwd = cwd();
|
||||
push(@errors, "config.status failed \$?=$?, \$!=$!, cwd: $cwd");
|
||||
}
|
||||
}
|
||||
$@ = join("\n", @errors);
|
||||
|
||||
## Legacy behavior: config.status problems are not fatal {yet}.
|
||||
## Display warning since caller will not be calling die.
|
||||
warn $@ if ($@ && $argv{'no-warnings'});
|
||||
return $@ ? 1 : 0;
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,94 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Joey Armstrong <joey@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
##################################################
|
||||
## Gather a list of tests, generate timestamp deps
|
||||
##################################################
|
||||
TS=.ts
|
||||
ifneq (,$(findstring check,$(MAKECMDGOALS)))
|
||||
allsrc = $(wildcard $(srcdir)/*)
|
||||
tests2run = $(notdir $(filter %.tpl,$(allsrc)))
|
||||
tests2run += $(notdir $(filter %.tpm,$(allsrc)))
|
||||
check_targets += $(addprefix $(TS)/,$(tests2run))
|
||||
endif
|
||||
|
||||
all_nop: # export, libs and tools are not needed
|
||||
|
||||
check:: $(TS) $(check_targets)
|
||||
|
||||
#############################################
|
||||
# Only invoke tests when sources have changed
|
||||
#############################################
|
||||
$(TS)/%: $(srcdir)/%
|
||||
$(PERL) $(srcdir)/runtest $<
|
||||
@touch $@
|
||||
|
||||
parent = $(patsubst %/,%,$(dir $(srcdir)))
|
||||
$(TS)/make-makefile.tpl: \
|
||||
$(srcdir)/make-makefile.tpl\
|
||||
$(parent)/makemakefile.pm\
|
||||
$(NULL)
|
||||
$(PERL) $(srcdir)/runtest $<
|
||||
@touch $@
|
||||
|
||||
$(TS)/makemakefile.tpm: \
|
||||
$(srcdir)/makemakefile.tpm \
|
||||
$(parent)/makemakefile.pm \
|
||||
$(NULL)
|
||||
$(PERL) $(srcdir)/runtest $<
|
||||
@touch $@
|
||||
|
||||
#####################################################
|
||||
## Extra dep needed to synchronize parallel execution
|
||||
#####################################################
|
||||
$(TS): $(TS)/.done
|
||||
$(TS)/.done:
|
||||
$(MKDIR) -p $(dir $@)
|
||||
touch $@
|
||||
|
||||
GARBAGE_DIRS += $(TS)
|
||||
|
||||
# EOF
|
|
@ -0,0 +1,4 @@
|
|||
jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
|
||||
@$(RM) $@ jsautocfg.tmp
|
||||
./jscpucfg > jsautocfg.tmp
|
||||
mv jsautocfg.tmp $@
|
|
@ -0,0 +1,4 @@
|
|||
jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
|
||||
@$(RM) $@ jsautocfg.tmp
|
||||
./jscpucfg > jsautocfg.tmp
|
||||
mv jsautocfg.tmp $@
|
|
@ -0,0 +1,8 @@
|
|||
###########################################################################
|
||||
## Intent: Exclusion list for container make builds
|
||||
###########################################################################
|
||||
|
||||
/dev/null
|
||||
/foo/bar
|
||||
/a/b/c
|
||||
/a/b/d
|
|
@ -0,0 +1,436 @@
|
|||
#!/usr/bin/env perl
|
||||
###########################################################################
|
||||
## Intent: Unit test to verify make-makefile.tpl
|
||||
###########################################################################
|
||||
|
||||
##----------------------------##
|
||||
##---] CORE/CPAN INCLUDES [---##
|
||||
##----------------------------##
|
||||
use strict;
|
||||
use warnings;
|
||||
#use feature 'state'; # 5.10+ not installed everywhere
|
||||
use Getopt::Long;
|
||||
|
||||
use Cwd;
|
||||
use Cwd qw{abs_path};
|
||||
use File::Basename;
|
||||
use File::Copy;
|
||||
use File::Path;
|
||||
use File::Temp qw{ tempdir };
|
||||
|
||||
use Test;
|
||||
sub BEGIN { plan tests => 4 };
|
||||
my @workdirs;
|
||||
sub END { system("/bin/rm -fr @workdirs"); } # cleanup behind interrupts
|
||||
|
||||
##-------------------##
|
||||
##---] EXPORTS [---##
|
||||
##-------------------##
|
||||
use FindBin;
|
||||
our $VERSION = qw(1.0);
|
||||
|
||||
##------------------##
|
||||
##---] INCLUDES [---##
|
||||
##------------------##
|
||||
use FindBin;
|
||||
use lib "$FindBin::RealBin/..";
|
||||
use makemakefile;
|
||||
|
||||
##-------------------##
|
||||
##---] GLOBALS [---##
|
||||
##-------------------##
|
||||
my %argv;
|
||||
|
||||
###########################################################################
|
||||
## Intent: Create a temp sandbox populated with sources
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## array a list of file paths to copy
|
||||
## Returns:
|
||||
## $@ set on error
|
||||
## scalar path to scratch sandbox
|
||||
## -----------------------------------------------------------------------
|
||||
###########################################################################
|
||||
my $root; # state $root not available
|
||||
sub createSandbox
|
||||
{
|
||||
my @errors;
|
||||
|
||||
unless ($root)
|
||||
{
|
||||
my @tmp = split(m%/%, $FindBin::RealBin);
|
||||
splice(@tmp, -3);
|
||||
$root = join('/', @tmp);
|
||||
}
|
||||
|
||||
my $work = tempdir();
|
||||
push(@workdirs, $work);
|
||||
my @dirs = map{ join('/', $work, dirname($_)) } @_;
|
||||
mkdirr(@dirs);
|
||||
push(@errors, "createSandbox: $@") if ($@);
|
||||
|
||||
foreach (@_)
|
||||
{
|
||||
## Copy sources into the temp source directory
|
||||
my $src = join('/', $root, $_);
|
||||
my $dst = join('/', $work, $_);
|
||||
unless (copy($src, $dst))
|
||||
{
|
||||
push(@errors, "copy($src, $dst) failed: $!");
|
||||
}
|
||||
}
|
||||
print STDERR "createSandbox: $work\n" if ($main::argv{debug});
|
||||
$@ = join('', map{ "$_\n" } @errors);
|
||||
$work;
|
||||
} # createSandbox
|
||||
|
||||
###########################################################################
|
||||
## Intent: wrapper to run the make-makefile command.
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## array command line arguments passed to make-makefile
|
||||
## Returns:
|
||||
## array command output
|
||||
## $@ set by shell exit status, empty string on success
|
||||
## $? command shell exit status
|
||||
###########################################################################
|
||||
my $mm; # state $mm not available
|
||||
sub makemakefile
|
||||
{
|
||||
my %fargs = (@_ && ref($_[$#_])) ? %{ (pop) } : ();
|
||||
$mm ||= join('/', dirname($FindBin::Bin), 'make-makefile'); # cmd in parent of test/
|
||||
my $cmd = join(' ', $mm, @_);
|
||||
print "RUNNING: $cmd\n" if ($fargs{debug});
|
||||
my @out = `$cmd 2>&1`;
|
||||
print STDERR map{ "out> $_" } @out if ($argv{verbose});
|
||||
$@ = (0 == $?) ? '' : "Command failed: $cmd\n@out";
|
||||
@out;
|
||||
} # makemakefile
|
||||
|
||||
###########################################################################
|
||||
## Intent: Helper function, display the contents of a given sandbox
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## scalar Path to sandbox
|
||||
## Returns:
|
||||
## none
|
||||
## -----------------------------------------------------------------------
|
||||
###########################################################################
|
||||
sub find_ls
|
||||
{
|
||||
my $path = shift || '';
|
||||
|
||||
# Assuming dot contributes to cryptic problems
|
||||
die "find_ls: a path is required" unless ($path);
|
||||
|
||||
my $cmd = "find $path -ls";
|
||||
print "\nRunning: $cmd\n";
|
||||
print '=' x 75, "\n";
|
||||
print `$cmd`;
|
||||
} # myls
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify make-makefile is able to digest paths and generate
|
||||
## makefiles when object directory is a child of top.
|
||||
###########################################################################
|
||||
sub check_makemakefile
|
||||
{
|
||||
my $work = createSandbox
|
||||
(
|
||||
'memory/mozalloc/Makefile.in',
|
||||
'toolkit/system/windowsproxy/Makefile.in',
|
||||
'toolkit/crashreporter/google-breakpad/src/client/Makefile.in',
|
||||
);
|
||||
|
||||
|
||||
my $workdir = createSandbox();
|
||||
my $top = $workdir;
|
||||
chdir $top;
|
||||
|
||||
my $objA = 'obj-arch-dir';
|
||||
my $obj = join('/', $top, $objA);
|
||||
|
||||
# getTopDir()
|
||||
local $main::argv{top} = $work;
|
||||
local $main::argv{obj} = $obj;
|
||||
getObjDir('_reset_');
|
||||
|
||||
my @root = split(m%/%, $FindBin::RealBin);
|
||||
splice(@root, -3);
|
||||
my $root = join('/', @root);
|
||||
my @args =
|
||||
(
|
||||
|
||||
[
|
||||
banner => "--top and --obj are impled, generate Makefile",
|
||||
rel => 'memory/mozalloc',
|
||||
cmd => join(' ',
|
||||
'--top', $top,
|
||||
'--obj', $obj,
|
||||
'memory/mozalloc/Makefile',
|
||||
),
|
||||
],
|
||||
|
||||
[
|
||||
banner => "--top and abs(obj) passed",
|
||||
rel => "toolkit/system/windowsproxy",
|
||||
cmd => join(' ',
|
||||
'--top', $top,
|
||||
"$obj/toolkit/system/windowsproxy/Makefile",
|
||||
),
|
||||
exp => "$obj/toolkit/system/windowsproxy/Makefile",
|
||||
skip => 1, #
|
||||
],
|
||||
|
||||
|
||||
[
|
||||
banner => "--obj and abs(top) passed",
|
||||
rel => "toolkit/crashreporter/google-breakpad/src/client",
|
||||
cmd => join(' ',
|
||||
'--obj', $obj,
|
||||
"$top/toolkit/crashreporter/google-breakpad/src/client/Makefile.in",
|
||||
),
|
||||
exp => "$top/toolkit/crashreporter/google-breakpad/src/client/Makefile.in",
|
||||
skip => 1, #
|
||||
],
|
||||
|
||||
);
|
||||
|
||||
foreach (@args)
|
||||
{
|
||||
my %rec = @{ $_ };
|
||||
next if ($rec{skip});
|
||||
next unless ($rec{rel});
|
||||
|
||||
my $srcR = join('/', $top, $rec{rel});
|
||||
my $dstR = join('/', $obj, $rec{rel});
|
||||
|
||||
my $src = join('/', $top, $rec{rel}, 'Makefile.in');
|
||||
my $dst = join('/', $obj, $rec{rel}, 'Makefile');
|
||||
|
||||
# Use distinct sources to avoid cleanup overhead between tests
|
||||
die "Test source already used: $dstR" if (-d $dstR);
|
||||
|
||||
## Copy sources into the temp source directory
|
||||
my $rootR = join('/', $root, $rec{rel});
|
||||
my $rootS = join('/', $root, $rec{rel}, 'Makefile.in');
|
||||
File::Path::mkpath($srcR, 0, 0700);
|
||||
copy($rootS, $src) or die "copy($rootS, $src) failed: $!";
|
||||
|
||||
die "source does not exist: $src" unless (-e $src);
|
||||
|
||||
######################
|
||||
## Generate and verify
|
||||
######################
|
||||
print STDERR "RUNNING: $rec{banner}\n" if ($argv{debug});
|
||||
my @errs;
|
||||
makemakefile('--enhanced', $rec{cmd}, {verbose=>1});
|
||||
if ($@)
|
||||
{
|
||||
push(@errs, "\$@ should not be set: $@\n");
|
||||
}
|
||||
elsif (! -e $dst)
|
||||
{
|
||||
push(@errs, "Generated makefile does not exist: $dst, banner: $rec{banner}\n");
|
||||
}
|
||||
|
||||
ok(scalar(@errs), 0, "Errors detected:\n" . join(" $_", @errs));
|
||||
find_ls($top) if (@errs);
|
||||
}
|
||||
|
||||
} # check_makemakefile
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify make-makefile is able to digest paths and generate
|
||||
## makefiles when top/MOZ_OBJDIR are not parent/child directories
|
||||
## ---------------------------------------------------------------------------
|
||||
## Args:
|
||||
## none
|
||||
## Returns:
|
||||
## none
|
||||
## ---------------------------------------------------------------------------
|
||||
###########################################################################
|
||||
sub check_makemakefile_distinct
|
||||
{
|
||||
my $workdir = createSandbox();
|
||||
# my $workdir = tempdir();
|
||||
|
||||
###############################################
|
||||
## Now update when top/obj are not parent/child
|
||||
###############################################
|
||||
my $top = join('/', $workdir, 'top');
|
||||
my $obj = join('/', $workdir, 'obj');
|
||||
|
||||
$main::argv{top} = $top;
|
||||
$main::argv{obj} = $obj; # test afterward, using undef ?
|
||||
|
||||
my @sbxroot = split(m%/%, $FindBin::RealBin);
|
||||
splice(@sbxroot, -2);
|
||||
my $sbxroot = join('/', @sbxroot);
|
||||
|
||||
## Copy in a makefile template to to convert
|
||||
File::Path::mkpath(["$top/memory/mozalloc"], 0, 0700);
|
||||
copy("$sbxroot/memory/mozalloc/Makefile.in", "$top/memory/mozalloc/Makefile.in");
|
||||
|
||||
|
||||
# work/memory/mozalloc/Makefile.in
|
||||
|
||||
my @args =
|
||||
(
|
||||
[
|
||||
banner => '--top and --obj are distinct [1]',
|
||||
cmd => "--obj $obj memory/mozalloc/Makefile",
|
||||
exp => "$obj/memory/mozalloc/Makefile",
|
||||
],
|
||||
|
||||
[
|
||||
banner => "--top and --obj are distinct [2]",
|
||||
cmd => "--top $top memory/mozalloc/Makefile.in",
|
||||
exp => "$obj/memory/mozalloc/Makefile",
|
||||
skip => 1, # test problem: top != obj
|
||||
],
|
||||
|
||||
[
|
||||
banner => "--top and --obj are distinct [3]",
|
||||
cmd => join(' ',
|
||||
"--top $top",
|
||||
"--obj $obj",
|
||||
"memory/mozalloc/Makefile.in",
|
||||
),
|
||||
exp => "$obj/memory/mozalloc/Makefile",
|
||||
skip => 1, # test problem: top != obj
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
foreach (@args)
|
||||
{
|
||||
my %rec = @{ $_ };
|
||||
print STDERR "banner: $rec{banner}\n" if ($argv{debug});
|
||||
next if $rec{skip};
|
||||
|
||||
unlink $rec{exp};
|
||||
makemakefile('--enhanced', $rec{cmd});
|
||||
|
||||
my @errs;
|
||||
if ($@)
|
||||
{
|
||||
push(@errs, "\$@ should not be set: $@\n");
|
||||
}
|
||||
elsif (! -e $rec{exp})
|
||||
{
|
||||
push(@errs, "Makefile does not exist: $rec{exp}\n");
|
||||
}
|
||||
ok(scalar(@errs), 0, "Errors detected:\n" . join(" $_", @errs));
|
||||
}
|
||||
|
||||
} # check_makemakefile_distinct
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify legacy behavior, invoke make-makefile when cwd is
|
||||
## a subdirectory beneath MOZ_OBJDIR.
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## none
|
||||
## Returns:
|
||||
## none
|
||||
## -----------------------------------------------------------------------
|
||||
###########################################################################
|
||||
sub check_makemakefile_legacy
|
||||
{
|
||||
my $work = createSandbox
|
||||
(
|
||||
'memory/mozalloc/Makefile.in',
|
||||
'parser/htmlparser/tests/mochitest/html5lib_tree_construction/Makefile.in',
|
||||
);
|
||||
|
||||
my $obj = join('/', $work, 'obj');
|
||||
mkdir $obj;
|
||||
|
||||
my @args =
|
||||
(
|
||||
{
|
||||
banner => '-t path -d dot',
|
||||
cwd => $obj,
|
||||
cmd => "-t $work -d . memory/mozalloc/Makefile",
|
||||
exp => "$obj/memory/mozalloc/Makefile",
|
||||
skip => 0,
|
||||
},
|
||||
|
||||
{
|
||||
banner => '-t path -d relpath',
|
||||
cwd => join('/', $obj, 'parser/htmlparser/tests/mochitest'),
|
||||
cmd => "-t $work -d ../../../.. html5lib_tree_construction/Makefile",
|
||||
exp => "$obj/parser/htmlparser/tests/mochitest/html5lib_tree_construction/Makefile",
|
||||
skip => 0,
|
||||
},
|
||||
);
|
||||
|
||||
foreach (@args)
|
||||
{
|
||||
my %rec = %{ $_ };
|
||||
next if ($rec{skip});
|
||||
|
||||
## make-make while sitting in $objdir
|
||||
mkdirr($rec{cwd});
|
||||
chdir $rec{cwd} || die "chdir $rec{cwd} failed; $!";
|
||||
|
||||
makemakefile($rec{cmd});
|
||||
my @errs;
|
||||
if ($@)
|
||||
{
|
||||
push(@errs, "make-makefile $rec{cmd} failed: $@");
|
||||
}
|
||||
elsif (! -e $rec{exp})
|
||||
{
|
||||
push(@errs, "generated makefile does not exist: $rec{exp}");
|
||||
}
|
||||
ok(scalar(@errs), 0, "Errors detected: @errs");
|
||||
find_ls($work) if (@errs);
|
||||
}
|
||||
chdir $FindBin::RealBin;
|
||||
} # check_makemakefile_legacy
|
||||
|
||||
###########################################################################
|
||||
## Intent: Smoke tests for the unittests module
|
||||
###########################################################################
|
||||
sub smoke
|
||||
{
|
||||
print STDERR "Running test: smoke()\n" if ($argv{debug});
|
||||
} # smoke()
|
||||
|
||||
###########################################################################
|
||||
## Intent: Intitialize global test objects and consts
|
||||
###########################################################################
|
||||
sub init
|
||||
{
|
||||
print "Running: init()\n" if ($argv{debug});
|
||||
# testplan(24, 0);
|
||||
} # init()
|
||||
|
||||
##----------------##
|
||||
##---] MAIN [---##
|
||||
##----------------##
|
||||
unless(GetOptions(\%argv,
|
||||
qw(
|
||||
debug|d
|
||||
manual
|
||||
test=s@
|
||||
verbose
|
||||
)))
|
||||
{
|
||||
print "USAGE: $0\n";
|
||||
print " --debug Enable script debug mode\n";
|
||||
print " --manual Also run disabled tests\n";
|
||||
print " --smoke Run smoke tests then exit\n";
|
||||
print " --test Run a list of tests by function name\n";
|
||||
print " --verbose Enable script verbose mode\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
init();
|
||||
smoke();
|
||||
|
||||
check_makemakefile();
|
||||
check_makemakefile_distinct();
|
||||
check_makemakefile_legacy();
|
|
@ -0,0 +1,519 @@
|
|||
#!/usr/bin/env perl
|
||||
###########################################################################
|
||||
## Intent: Unit test to verify the makemakefile.pm module
|
||||
###########################################################################
|
||||
|
||||
##----------------------------##
|
||||
##---] CORE/CPAN INCLUDES [---##
|
||||
##----------------------------##
|
||||
use strict;
|
||||
use warnings;
|
||||
#use feature 'state';
|
||||
use Getopt::Long;
|
||||
|
||||
use FindBin;
|
||||
use Cwd qw{abs_path};
|
||||
use File::Basename;
|
||||
use File::Compare;
|
||||
use File::Copy;
|
||||
use File::Temp qw{tempdir};
|
||||
|
||||
use Test;
|
||||
sub BEGIN { plan tests => 36 };
|
||||
my @workdirs;
|
||||
sub END { system("/bin/rm -fr @workdirs"); } # cleanup behind interrupts
|
||||
|
||||
##-------------------##
|
||||
##---] EXPORTS [---##
|
||||
##-------------------##
|
||||
our $VERSION = qw(1.0);
|
||||
|
||||
##------------------##
|
||||
##---] INCLUDES [---##
|
||||
##------------------##
|
||||
use FindBin;
|
||||
use lib "$FindBin::RealBin/..";
|
||||
use makemakefile;
|
||||
|
||||
##-------------------##
|
||||
##---] GLOBALS [---##
|
||||
##-------------------##
|
||||
my %argv;
|
||||
|
||||
###########################################################################
|
||||
## Intent: Create a temp sandbox populated with sources
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## array files to copy into the temporary sandbox
|
||||
## Returns:
|
||||
## $@ set on error
|
||||
## array
|
||||
## top - path to temp sandbox root
|
||||
## obj - path to temp sandbox moz_obj directory
|
||||
## -----------------------------------------------------------------------
|
||||
###########################################################################
|
||||
my $_root_; # state $root
|
||||
sub createSandbox
|
||||
{
|
||||
# state $root;
|
||||
my @errors;
|
||||
|
||||
unless ($_root_)
|
||||
{
|
||||
my @tmp = split(m%/%, $FindBin::RealBin);
|
||||
splice(@tmp, -3);
|
||||
$_root_ = join('/', @tmp);
|
||||
}
|
||||
|
||||
my $work = tempdir(CLEANUP=>1);
|
||||
push(@workdirs, $work);
|
||||
my @dirs = map{ join('/', $work, dirname($_)) } @_;
|
||||
mkdirr(@dirs);
|
||||
push(@errors, "createSandbox: $@") if ($@);
|
||||
|
||||
foreach (@_)
|
||||
{
|
||||
## Copy sources into the temp source directory
|
||||
my $src = join('/', $_root_, $_);
|
||||
my $dst = join('/', $work, $_);
|
||||
unless (copy($src, $dst))
|
||||
{
|
||||
push(@errors, "copy($src, $dst) failed: $!");
|
||||
}
|
||||
}
|
||||
print STDERR "createSandbox: $work\n" if ($main::argv{debug});
|
||||
$@ = join('', map{ "$_\n" } @errors);
|
||||
$work;
|
||||
} # createSandbox
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify legacy dirname function
|
||||
###########################################################################
|
||||
sub check_dirname_legacy
|
||||
{
|
||||
print "Running: check_dirname_legacy\n" if ($main::argv{debug});
|
||||
|
||||
foreach (
|
||||
['/dev/null', '/dev'],
|
||||
['/foo/bar/Makefile', '/foo/bar'],
|
||||
)
|
||||
{
|
||||
my ($src, $exp) = @{ $_ };
|
||||
my $dir = dirname_legacy($src);
|
||||
ok($dir, $exp, "dirname_legacy($src) failed");
|
||||
}
|
||||
|
||||
my $path = dirname_legacy(undef);
|
||||
ok($path ? 1 : 0, 1, "dirname('') should expand to cwd");
|
||||
} # check_dirname_legacy
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify topdir lookup function
|
||||
###########################################################################
|
||||
sub check_getTopDir
|
||||
{
|
||||
print "Running: check_getTopDir\n" if ($main::argv{debug});
|
||||
|
||||
my $path = getTopDir();
|
||||
|
||||
## Unit test is special, cmd not invoked from the same directory
|
||||
## as the makemakefile.pm module.
|
||||
ok($path ? 1 : 0, 1, "getTopDir failed");
|
||||
ok(-d $path ? 1 : 0, 1, "getTopDir: directory $path does not exist");
|
||||
ok($FindBin::RealBin =~ m%$path/% ? 1 : 0, 1, 'Invalid topdir path');
|
||||
ok(-e "$path/client.mk" ? 1 : 0, 1, "client.mk not found in $path");
|
||||
} # check_getTopDir
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify objdir lookup function
|
||||
###########################################################################
|
||||
sub check_getObjDir
|
||||
{
|
||||
print "Running: check_getObjDir\n" if ($main::argv{debug});
|
||||
local $main::argv{obj} = '/bin';
|
||||
my $path = getObjDir('_reset_');
|
||||
ok($path ? 1 : 0, 1, "getObjDir failed");
|
||||
ok(-d $path ? 1 : 0, 1, "getObjDir: directory $path does not exist");
|
||||
|
||||
my $top = getTopDir();
|
||||
$main::argv{obj} = join('/', $top, 'browser'); # use existing path so file can be resolved
|
||||
my $obj = getObjDir('_reset_');
|
||||
ok($top ne $obj ? 1 : 0, 1, "top and object directory paths should not match");
|
||||
|
||||
## If we fail for /bin use here getObjDir() was not reset
|
||||
my $client = join('/', $obj, '..', 'client.mk');
|
||||
ok(-e $client ? 1 : 0, 1, "client.mk not found in parent of $path, $client");
|
||||
getObjDir('_set_'); # clear cached value and recompute
|
||||
|
||||
foreach my $file ("$top/memory/mozalloc/Makefile")
|
||||
{
|
||||
my $obj = getObjDir('_reset_', $file);
|
||||
ok($obj ne $file ? 1 : 0, 1, "getObjDir($file) failed")
|
||||
}
|
||||
} # check_getObjDir
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify rel-path-to-root/getdepth function
|
||||
###########################################################################
|
||||
sub check_getDepth
|
||||
{
|
||||
my @tmp = split(m%/%o, $FindBin::Bin);
|
||||
splice(@tmp, -3);
|
||||
my $root = abs_path( join('/', @tmp) );
|
||||
|
||||
my %data =
|
||||
(
|
||||
$root => '.',
|
||||
join('/', $root, 'netwerk/Makefile.in') => '..',
|
||||
|
||||
join('/', $root, 'browser/components/privatebrowsing/test/browser/Makefile.in') => '../../../../..',
|
||||
join('/', $root, 'browser/components/privatebrowsing/test/browser/') => '../../../../..',
|
||||
join('/', $root, 'browser/components/privatebrowsing/test/browser') => '../../../../..',
|
||||
join('/', $root, 'browser/components/privatebrowsing/test') => '../../../..',
|
||||
);
|
||||
|
||||
while (my($k, $v) = each %data)
|
||||
{
|
||||
my $depth = makemakefile::getDepth($k);
|
||||
ok($depth, $v, "getDepth($k) failed");
|
||||
}
|
||||
} # check_getDepth
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify reading the exclusion file
|
||||
###########################################################################
|
||||
sub check_getExclusions
|
||||
{
|
||||
my $cfg = join('/', $FindBin::RealBin, 'make-makefile.excl');
|
||||
my %excl = getExclusions($cfg);
|
||||
ok($@, '', '$@ should not be set');
|
||||
|
||||
my @excl = sort keys %excl;
|
||||
ok(scalar @excl, 4, "Exclusion file is invalid: \@excl=@excl");
|
||||
} # check_getExclusions
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify rel-path-to-root function
|
||||
## -----------------------------------------------------------------------
|
||||
## Args:
|
||||
## none
|
||||
## Returns:
|
||||
## none
|
||||
## -----------------------------------------------------------------------
|
||||
## Note:
|
||||
## String test only, top and obj paths are bogus for this test
|
||||
###########################################################################
|
||||
sub check_getRelPath
|
||||
{
|
||||
my @tmp = split(m%/%o, $FindBin::Bin);
|
||||
splice(@tmp, -3);
|
||||
my $root = abs_path( join('/', @tmp) );
|
||||
my $obj0 = 'obj-arch';
|
||||
my $obj = join('/', $root, $obj0);
|
||||
|
||||
local $main::argv{top} = $root;
|
||||
local $main::argv{obj} = $obj;
|
||||
getTopDir('_reset_');
|
||||
getObjDir('_set_', $obj);
|
||||
|
||||
## Cannot test relative paths with objdir beneath /tmp
|
||||
## Commented paths are needed for full test coverage
|
||||
## but are not currently supported by all module functions.
|
||||
my %data =
|
||||
(
|
||||
# Relative - path correct for build directory but
|
||||
'profile/dirserviceprovider/public/Makefile.in' => 'profile/dirserviceprovider/public',
|
||||
|
||||
join('/', $root, 'profile/dirserviceprovider/public/Makefile.in') => 'profile/dirserviceprovider/public',
|
||||
|
||||
# File search
|
||||
'profile/dirserviceprovider/public' => 'profile/dirserviceprovider/public',
|
||||
|
||||
# cwd + cleanup
|
||||
# '../../../profile/dirserviceprovider/public/Makefile.in' => 'profile/dirserviceprovider/public',
|
||||
# "../../../${obj0}/profile/dirserviceprovider/public/Makefile.in" => 'profile/dirserviceprovider/public',
|
||||
|
||||
## Special case: This could be handled but permutations of non-existent files, non-overlapping paths
|
||||
## and relative paths containing partial subdirectories will compilicate the logic. Wait until needed.
|
||||
## Relative path: $root + obj + subdir
|
||||
# "${obj0}/profile/dirserviceprovider/public/Makefile" => 'profile/dirserviceprovider/public',
|
||||
join('/', $obj, 'profile/dirserviceprovider/public/Makefile') => 'profile/dirserviceprovider/public',
|
||||
|
||||
# $RealBin, -d ../../..
|
||||
# top and obj not subdirectories of each other: /foo/x, /bar/y
|
||||
);
|
||||
|
||||
while (my($k, $v) = each %data)
|
||||
{
|
||||
my $dir = getRelPath($k);
|
||||
ok($@, '', '$@ should not be set');
|
||||
ok($dir, $v, "ERROR[$k]: exp[$v] != found=[$dir]");
|
||||
}
|
||||
|
||||
|
||||
my $top = '/tmp/foo';
|
||||
my $tmp = '/tmp/bar';
|
||||
local $main::argv{top} = $tmp;
|
||||
local $main::argv{obj} = $obj;
|
||||
|
||||
%data =
|
||||
(
|
||||
# "$top/profile/dirserviceprovider/public/Makefile.in" => 'profile/dirserviceprovider/public',
|
||||
"$obj/profile/dirserviceprovider/public/Makefile" => 'profile/dirserviceprovider/public',
|
||||
);
|
||||
|
||||
while (my($k, $v) = each %data)
|
||||
{
|
||||
my $dir = getRelPath($k);
|
||||
ok($dir, $v, "ERROR[$k]: exp[$v] != found=[$dir]");
|
||||
}
|
||||
} # check_getRelPath
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify rel-path-to-root directory creation
|
||||
###########################################################################
|
||||
sub check_mkdirr
|
||||
{
|
||||
if (-w '/bin') # cygwin may be writable
|
||||
{
|
||||
ok(1, 1, 'bogus test to maintain count');
|
||||
} else {
|
||||
mkdirr('/bin/invalid/Makefile');
|
||||
ok($@ ? 1 : 0, 1, '$@ should be set');
|
||||
}
|
||||
|
||||
my $work = createSandbox();
|
||||
my @paths = map{ join('/', $work, $_, 'Makefile.in') } qw (xyz/abc foo/bar a/b/c/d/e);
|
||||
mkdirr(@paths);
|
||||
ok($@ ? 1 : 0, 0, '$@ should not be set');
|
||||
|
||||
push(@paths, '/bin');
|
||||
|
||||
my @errors;
|
||||
foreach (@paths)
|
||||
{
|
||||
my $dir = dirname($_);
|
||||
next if (-d $dir);
|
||||
push(@errors, "mkdirr($dir) failed\n");
|
||||
}
|
||||
ok(scalar @errors, 0, "Errors detected: @errors");
|
||||
} # check_mkdirr
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify permutations for system("config.status")
|
||||
###########################################################################
|
||||
sub check_run_config_status
|
||||
{
|
||||
print STDERR "Running: check_run_config_status()\n"
|
||||
if ($main::argv{debug});
|
||||
|
||||
my $work = createSandbox();
|
||||
chdir $work;
|
||||
run_config_status();
|
||||
ok($@ ? 1 : 0, '$@ should be set, config.status does not exist');
|
||||
|
||||
my $cfg = join('/', $work, 'config.status');
|
||||
local *CFG;
|
||||
open(CFG, "> $cfg") && close(CFG);
|
||||
run_config_status();
|
||||
ok($@, qr/config.status failed/, '$@ should be set, config.status is not executabl');
|
||||
|
||||
open(CFG, "> $cfg");
|
||||
print CFG join("\n",
|
||||
'#!/bin/sh',
|
||||
'',
|
||||
'true',
|
||||
'');
|
||||
close(CFG);
|
||||
chmod 0555, $cfg;
|
||||
run_config_status();
|
||||
ok($@, qr/config.status failed/, '$@ should not be set');
|
||||
|
||||
} # check_run_config_status
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify makefile generation by legacy make-makefile functions
|
||||
## o make-makefile -t /x/y -d ..
|
||||
###########################################################################
|
||||
sub check_update_makefiles_legacy
|
||||
{
|
||||
print STDERR "Running: check_update_makefiles_legacy()\n"
|
||||
if ($main::argv{debug});
|
||||
|
||||
return unless ($argv{legacy});
|
||||
print STDERR "check_update_makefiles_legacy: not yet implemented\n";
|
||||
|
||||
} # check_update_makefiles_legacy
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify updateMakefiles()
|
||||
## o a makefile is generated when none exists.
|
||||
## o a makefile will only be updated when the templates changes.
|
||||
## o existing makefiles will be updated when the template changes.
|
||||
## o @foo@ tokens have been expanded
|
||||
###########################################################################
|
||||
sub check_updateMakefiles
|
||||
{
|
||||
my @errors;
|
||||
|
||||
print STDERR "Running: check_updateMakefiles()\n"
|
||||
if ($main::argv{debug});
|
||||
|
||||
my $mf = 'memory/mozalloc/Makefile.in';
|
||||
|
||||
my $work = createSandbox($mf);
|
||||
my $obj = join('/', $work, 'obj');
|
||||
my %args =
|
||||
(
|
||||
top => $work,
|
||||
obj => $obj,
|
||||
);
|
||||
|
||||
my $mf_src = join('/', $work, 'memory/mozalloc/Makefile.in');
|
||||
my $mf_dst = join('/', $obj, 'memory/mozalloc/Makefile');
|
||||
|
||||
updateMakefiles('memory/mozalloc', \%args);
|
||||
my $tlm0 = (stat $mf_dst)[9] || 0;
|
||||
ok(-e $mf_dst ? 1 : 0, 1, "failed to generate makefile: $mf_dst");
|
||||
|
||||
#############################
|
||||
## Regeneration will be a nop
|
||||
#############################
|
||||
updateMakefiles('memory/mozalloc', \%args);
|
||||
my $tlm1 = (stat $mf_dst)[9] || -1;
|
||||
ok($tlm1, $tlm0, "makefile should not have been modified");
|
||||
|
||||
#####################################################
|
||||
## Modify template to verify makefile will regenerate
|
||||
#####################################################
|
||||
local *MF;
|
||||
if (open(MF, ">> $mf_src"))
|
||||
{
|
||||
print MF map{ "# MODIFIED MAKEFILE\n" } 0..4;
|
||||
close(MF);
|
||||
}
|
||||
updateMakefiles('memory/mozalloc', \%args);
|
||||
my @data = makemakefile::cat($mf_dst);
|
||||
## Check content to avoid a silly 'sleep [n]' call here
|
||||
ok(grep(/^\# MODIFIED MAKEFILE/o, @data) ? 1 : 0,
|
||||
1,
|
||||
"template modified, makefile should have regenerated");
|
||||
|
||||
## VERIFY template expansion
|
||||
my @gen = makemakefile::cat($mf_dst);
|
||||
push(@errors, $@) if ($@);
|
||||
|
||||
foreach (@gen)
|
||||
{
|
||||
if (/\@[^\@]+\@/o)
|
||||
{
|
||||
push(@errors, join("\n",
|
||||
"Unexpanded template string detected [$_]",
|
||||
"Makefile: $mf_src",
|
||||
));
|
||||
last;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ok(scalar(@errors), 0, "Errors detected: @errors");
|
||||
} # check_updateMakefiles
|
||||
|
||||
###########################################################################
|
||||
## Intent: Verify makefile generation by updateMakefiles() when
|
||||
## command line arguments --top and --obj were passed.
|
||||
###########################################################################
|
||||
sub check_updateMakefilesByTopObj
|
||||
{
|
||||
my @errors;
|
||||
|
||||
print STDERR "Running: check_updateMakefilesByTopObj()\n"
|
||||
if ($main::argv{debug});
|
||||
|
||||
my $work = createSandbox();
|
||||
my %args =
|
||||
(
|
||||
top => $work,
|
||||
obj => $work,
|
||||
);
|
||||
|
||||
## Grab a list of makefile templates to generate
|
||||
my @all = glob('data/mf.*');
|
||||
my @src = map{ /\.exp$/o ? () : $_ } @all;
|
||||
|
||||
foreach my $src (@src)
|
||||
{
|
||||
my $dst = join('/', $work, 'Makefile');
|
||||
unlink $dst;
|
||||
copy($src, "$work/Makefile.in");
|
||||
updateMakefiles('.', \%args);
|
||||
ok($@, '', '$@ should not be set');
|
||||
|
||||
my @dst = makemakefile::cat($dst);
|
||||
|
||||
my $exp = join('.', $src, 'exp');
|
||||
my @exp = makemakefile::cat($exp);
|
||||
ok("@dst", "@exp", "updateMakefile($dst) failed");
|
||||
}
|
||||
return;
|
||||
} # check_updateMakefilesByTopObj
|
||||
|
||||
###########################################################################
|
||||
## Intent: Smoke tests for the unittests module
|
||||
###########################################################################
|
||||
sub smoke
|
||||
{
|
||||
print STDERR "Running test: smoke()\n" if ($argv{debug});
|
||||
} # smoke()
|
||||
|
||||
###########################################################################
|
||||
## Intent: Intitialize global test objects and consts
|
||||
###########################################################################
|
||||
sub init
|
||||
{
|
||||
print "Running: init()\n" if ($argv{debug});
|
||||
# testplan(24, 0);
|
||||
|
||||
my @path = split(m%/%, $FindBin::RealBin);
|
||||
splice(@path, -3);
|
||||
my $top = join('/', @path);
|
||||
## Top set based on make-makefile startup directory so adjust for test/ use
|
||||
getTopDir('_set_', $top);
|
||||
|
||||
} # init()
|
||||
|
||||
##----------------##
|
||||
##---] MAIN [---##
|
||||
##----------------##
|
||||
unless(GetOptions(\%argv,
|
||||
qw(
|
||||
debug|d
|
||||
manual
|
||||
test=s@
|
||||
verbose
|
||||
)))
|
||||
{
|
||||
print "USAGE: $0\n";
|
||||
print " --debug Enable script debug mode\n";
|
||||
print " --manual Also run disabled tests\n";
|
||||
print " --smoke Run smoke tests then exit\n";
|
||||
print " --test Run a list of tests by function name\n";
|
||||
print " --verbose Enable script verbose mode\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
init();
|
||||
smoke();
|
||||
|
||||
check_dirname_legacy();
|
||||
|
||||
check_getTopDir();
|
||||
check_getObjDir();
|
||||
check_getDepth();
|
||||
check_getExclusions();
|
||||
check_getRelPath();
|
||||
check_mkdirr();
|
||||
|
||||
check_updateMakefiles();
|
||||
check_update_makefiles_legacy();
|
||||
check_updateMakefilesByTopObj();
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env perl
|
||||
###########################################################################
|
||||
## Intent:
|
||||
## Test::Harness is a testing wrapper that will process output
|
||||
## from Test.pm module tests. Sumarize results, report stats
|
||||
## and exit with overall status for the testing suites.
|
||||
##
|
||||
## Run testing suite:
|
||||
## % make clean test
|
||||
## % perl runtest
|
||||
##
|
||||
## Run Individual tests
|
||||
## % perl tUtils0
|
||||
###########################################################################
|
||||
|
||||
##----------------------------##
|
||||
##---] CORE/CPAN INCLUDES [---##
|
||||
##----------------------------##
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
|
||||
use Test::Harness;
|
||||
|
||||
##-------------------##
|
||||
##---] EXPORTS [---##
|
||||
##-------------------##
|
||||
our $VERSION = qw(1.0);
|
||||
use FindBin;
|
||||
|
||||
##-------------------##
|
||||
##---] GLOBALS [---##
|
||||
##-------------------##
|
||||
my %argv;
|
||||
|
||||
##----------------##
|
||||
##---] MAIN [---##
|
||||
##----------------##
|
||||
unless(GetOptions(\%argv,
|
||||
qw(debug|d)
|
||||
))
|
||||
{
|
||||
print "Usage: $0\n";
|
||||
print " --debug Enable debug mode\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if (2 > $Test::Harness::VERSION)
|
||||
{
|
||||
print "Unit tests will not be run, Test::Harness is too old\n"
|
||||
if ($argv{debug});
|
||||
exit 0;
|
||||
}
|
||||
|
||||
|
||||
my @tests;
|
||||
|
||||
########################################
|
||||
## Gather a list of tests if none passed
|
||||
########################################
|
||||
unless (@tests = @ARGV)
|
||||
{
|
||||
local *D;
|
||||
opendir(D, '.');
|
||||
while($_ = readdir(D)) {
|
||||
next unless /.t\S+$/;
|
||||
next if (/\.ts$/);
|
||||
push(@tests, $_);
|
||||
}
|
||||
closedir(D);
|
||||
}
|
||||
|
||||
###############################################
|
||||
## Glob a list of tests when directories passed
|
||||
###############################################
|
||||
my @tmp;
|
||||
foreach (@tests)
|
||||
{
|
||||
local *D;
|
||||
if (-d $_ && (my $dir = $_))
|
||||
{
|
||||
opendir(D, $_) || die "opendir(D) failed: $!";
|
||||
my @tests = grep(/\.t[^\.\s]+/o, readdir(D));
|
||||
closedir(D);
|
||||
push(@tmp, map{ join('/', $dir, $_); } @tests);
|
||||
} else {
|
||||
push(@tmp, $_);
|
||||
}
|
||||
}
|
||||
@tests = @tmp;
|
||||
|
||||
print "$0: @ARGV\n" if ($argv{debug});
|
||||
runtests(@tests);
|
||||
|
||||
# EOF
|
|
@ -16,5 +16,6 @@
|
|||
__malloc_hook;
|
||||
__realloc_hook;
|
||||
__memalign_hook;
|
||||
_IO_stdin_used;
|
||||
local: *;
|
||||
};
|
||||
|
|
|
@ -109,3 +109,10 @@ endif
|
|||
|
||||
endif # ! MOZ_DEBUG
|
||||
endif # WIN32_REDIST_DIR
|
||||
|
||||
# run the binscope tool to make sure the binary and all libraries
|
||||
# are using all available Windows OS-level security mechanisms
|
||||
check::
|
||||
$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/firefox.exe $(DIST)/crashreporter-symbols/
|
||||
$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/plugin-container.exe $(DIST)/crashreporter-symbols/
|
||||
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# the Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# imelven@mozilla.com
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# run Microsoft's Binscope tool (http://www.microsoft.com/download/en/details.aspx?id=11910)
|
||||
# against a fresh Windows build. output a 'binscope.log' file with full details
|
||||
# of the run and appropriate strings to integrate with the buildbots
|
||||
|
||||
# from the docs : "The error code returned when running under the command line is equal
|
||||
# to the number of failures the tool reported plus the number of errors. BinScope will return
|
||||
# 0 only if there are no errors or failures."
|
||||
|
||||
# the symbol dir should point to the symbol dir hierarchy created
|
||||
# via running make buildsymbols in a windows build's objdir
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
BINSCOPE_OUTPUT_LOGFILE = r".\binscope_xml_output.log"
|
||||
|
||||
# usage
|
||||
if len(sys.argv) < 3:
|
||||
print """usage : autobinscope.by path_to_binary path_to_symbols [log_file_path]"
|
||||
log_file_path is optional, log will be written to .\binscope_xml_output.log by default"""
|
||||
sys.exit(0)
|
||||
|
||||
binary_path = sys.argv[1]
|
||||
symbol_path = sys.argv[2]
|
||||
|
||||
if len(sys.argv) == 4:
|
||||
log_file_path = sys.argv[3]
|
||||
else:
|
||||
log_file_path = BINSCOPE_OUTPUT_LOGFILE
|
||||
|
||||
# execute binscope against the binary, using the BINSCOPE environment
|
||||
# variable as the path to binscope.exe
|
||||
try:
|
||||
binscope_path = os.environ['BINSCOPE']
|
||||
except KeyError:
|
||||
print "BINSCOPE environment variable is not set, can't check DEP/ASLR etc. status."
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
proc = subprocess.Popen([binscope_path, "/target", binary_path,
|
||||
"/output", log_file_path, "/sympath", symbol_path,
|
||||
"/c", "ATLVersionCheck", "/c", "ATLVulnCheck", "/c", "FunctionPointersCheck",
|
||||
"/c", "SharedSectionCheck", "/c", "APTCACheck", "/c", "NXCheck",
|
||||
"/c", "GSCheck", "/c", "GSFunctionSafeBuffersCheck", "/c", "GSFriendlyInitCheck",
|
||||
"/c", "CompilerVersionCheck", "/c", "SafeSEHCheck", "/c", "SNCheck",
|
||||
"/c", "DBCheck"], stdout=subprocess.PIPE)
|
||||
|
||||
except WindowsError, (errno, strerror):
|
||||
if errno != 2 and errno != 3:
|
||||
print "Unexpected error ! \nError " + str(errno) + " : " + strerror + "\nExiting !\n"
|
||||
sys.exit(0)
|
||||
else:
|
||||
print "Could not locate binscope at location : %s\n" % binscope_path
|
||||
print "Binscope wasn't installed or the BINSCOPE env variable wasn't set correctly, skipping this check and exiting..."
|
||||
sys.exit(0)
|
||||
|
||||
proc.wait()
|
||||
|
||||
output = proc.communicate()[0]
|
||||
|
||||
# is this a PASS or a FAIL ?
|
||||
if proc.returncode != 0:
|
||||
print "TEST-UNEXPECTED-FAIL | autobinscope.py | %s is missing a needed Windows protection, such as /GS or ASLR" % binary_path
|
||||
else:
|
||||
print "TEST-PASS | autobinscope.py | %s succeeded" % binary_path
|
||||
|
||||
|
||||
|
|
@ -819,9 +819,7 @@ nsContentSink::ProcessLink(nsIContent* aElement,
|
|||
const nsSubstring& aRel, const nsSubstring& aTitle,
|
||||
const nsSubstring& aType, const nsSubstring& aMedia)
|
||||
{
|
||||
// XXX seems overkill to generate this string array
|
||||
nsTArray<nsString> linkTypes;
|
||||
nsStyleLinkElement::ParseLinkTypes(aRel, linkTypes);
|
||||
PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(aRel);
|
||||
|
||||
// The link relation may apply to a different resource, specified
|
||||
// in the anchor parameter. For the link relations supported so far,
|
||||
|
@ -831,22 +829,22 @@ nsContentSink::ProcessLink(nsIContent* aElement,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool hasPrefetch = linkTypes.Contains(NS_LITERAL_STRING("prefetch"));
|
||||
bool hasPrefetch = linkTypes & PREFETCH;
|
||||
// prefetch href if relation is "next" or "prefetch"
|
||||
if (hasPrefetch || linkTypes.Contains(NS_LITERAL_STRING("next"))) {
|
||||
if (hasPrefetch || (linkTypes & NEXT)) {
|
||||
PrefetchHref(aHref, aElement, hasPrefetch);
|
||||
}
|
||||
|
||||
if ((!aHref.IsEmpty()) && linkTypes.Contains(NS_LITERAL_STRING("dns-prefetch"))) {
|
||||
if (!aHref.IsEmpty() && (linkTypes & DNS_PREFETCH)) {
|
||||
PrefetchDNS(aHref);
|
||||
}
|
||||
|
||||
// is it a stylesheet link?
|
||||
if (!linkTypes.Contains(NS_LITERAL_STRING("stylesheet"))) {
|
||||
if (!(linkTypes & STYLESHEET)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool isAlternate = linkTypes.Contains(NS_LITERAL_STRING("alternate"));
|
||||
bool isAlternate = linkTypes & ALTERNATE;
|
||||
return ProcessStyleLink(aElement, aHref, isAlternate, aTitle, aType,
|
||||
aMedia);
|
||||
}
|
||||
|
|
|
@ -1782,31 +1782,38 @@ IdentifierMapEntryTraverse(nsIdentifierMapEntry *aEntry, void *aArg)
|
|||
}
|
||||
|
||||
static const char* kNSURIs[] = {
|
||||
" ([none])",
|
||||
" (xmlns)",
|
||||
" (xml)",
|
||||
" (xhtml)",
|
||||
" (XLink)",
|
||||
" (XSLT)",
|
||||
" (XBL)",
|
||||
" (MathML)",
|
||||
" (RDF)",
|
||||
" (XUL)"
|
||||
"([none])",
|
||||
"(xmlns)",
|
||||
"(xml)",
|
||||
"(xhtml)",
|
||||
"(XLink)",
|
||||
"(XSLT)",
|
||||
"(XBL)",
|
||||
"(MathML)",
|
||||
"(RDF)",
|
||||
"(XUL)"
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
||||
if (NS_UNLIKELY(cb.WantDebugInfo())) {
|
||||
char name[512];
|
||||
nsCAutoString loadedAsData;
|
||||
if (tmp->IsLoadedAsData()) {
|
||||
loadedAsData.AssignLiteral("data");
|
||||
} else {
|
||||
loadedAsData.AssignLiteral("normal");
|
||||
}
|
||||
PRUint32 nsid = tmp->GetDefaultNamespaceID();
|
||||
nsCAutoString uri;
|
||||
if (tmp->mDocumentURI)
|
||||
tmp->mDocumentURI->GetSpec(uri);
|
||||
if (nsid < ArrayLength(kNSURIs)) {
|
||||
PR_snprintf(name, sizeof(name), "nsDocument%s %s", kNSURIs[nsid],
|
||||
uri.get());
|
||||
PR_snprintf(name, sizeof(name), "nsDocument %s %s %s",
|
||||
loadedAsData.get(), kNSURIs[nsid], uri.get());
|
||||
}
|
||||
else {
|
||||
PR_snprintf(name, sizeof(name), "nsDocument %s", uri.get());
|
||||
PR_snprintf(name, sizeof(name), "nsDocument %s %s",
|
||||
loadedAsData.get(), uri.get());
|
||||
}
|
||||
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), sizeof(nsDocument), name);
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
|
|||
|
||||
#ifdef ANDROID
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#endif
|
||||
|
||||
class nsAsyncInstantiateEvent : public nsRunnable {
|
||||
|
@ -1066,11 +1067,7 @@ nsObjectLoadingContent::ObjectState() const
|
|||
case eType_Image:
|
||||
return ImageState();
|
||||
case eType_Plugin:
|
||||
#ifdef ANDROID
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content)
|
||||
return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
|
||||
#endif
|
||||
case eType_Document:
|
||||
case eType_Document:
|
||||
// These are OK. If documents start to load successfully, they display
|
||||
// something, and are thus not broken in this sense. The same goes for
|
||||
// plugins.
|
||||
|
@ -1966,8 +1963,10 @@ nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
|
|||
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content)
|
||||
return ePluginClickToPlay;
|
||||
// if plugins are disabled, don't show the click to play message
|
||||
if (!mozilla::Preferences::GetBool("plugin.disable", false) &&
|
||||
XRE_GetProcessType() == GeckoProcessType_Content)
|
||||
return ePluginClickToPlay;
|
||||
#endif
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
|
|
|
@ -153,14 +153,30 @@ nsStyleLinkElement::SetLineNumber(PRUint32 aLineNumber)
|
|||
mLineNumber = aLineNumber;
|
||||
}
|
||||
|
||||
void nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes,
|
||||
nsTArray<nsString>& aResult)
|
||||
PRUint32 ToLinkMask(const nsAString& aLink)
|
||||
{
|
||||
if (aLink.EqualsLiteral("prefetch"))
|
||||
return PREFETCH;
|
||||
else if (aLink.EqualsLiteral("dns-prefetch"))
|
||||
return DNS_PREFETCH;
|
||||
else if (aLink.EqualsLiteral("stylesheet"))
|
||||
return STYLESHEET;
|
||||
else if (aLink.EqualsLiteral("next"))
|
||||
return NEXT;
|
||||
else if (aLink.EqualsLiteral("alternate"))
|
||||
return ALTERNATE;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRUint32 nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
|
||||
{
|
||||
PRUint32 linkMask = 0;
|
||||
nsAString::const_iterator start, done;
|
||||
aTypes.BeginReading(start);
|
||||
aTypes.EndReading(done);
|
||||
if (start == done)
|
||||
return;
|
||||
return linkMask;
|
||||
|
||||
nsAString::const_iterator current(start);
|
||||
bool inString = !nsCRT::IsAsciiSpace(*current);
|
||||
|
@ -170,7 +186,7 @@ void nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes,
|
|||
if (nsCRT::IsAsciiSpace(*current)) {
|
||||
if (inString) {
|
||||
ToLowerCase(Substring(start, current), subString);
|
||||
aResult.AppendElement(subString);
|
||||
linkMask |= ToLinkMask(subString);
|
||||
inString = false;
|
||||
}
|
||||
}
|
||||
|
@ -184,8 +200,9 @@ void nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes,
|
|||
}
|
||||
if (inString) {
|
||||
ToLowerCase(Substring(start, current), subString);
|
||||
aResult.AppendElement(subString);
|
||||
linkMask |= ToLinkMask(subString);
|
||||
}
|
||||
return linkMask;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -53,6 +53,12 @@
|
|||
#include "nsIURI.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#define PREFETCH 0x00000001
|
||||
#define DNS_PREFETCH 0x00000002
|
||||
#define STYLESHEET 0x00000004
|
||||
#define NEXT 0x00000008
|
||||
#define ALTERNATE 0x00000010
|
||||
|
||||
class nsIDocument;
|
||||
|
||||
class nsStyleLinkElement : public nsIDOMLinkStyle,
|
||||
|
@ -80,7 +86,7 @@ public:
|
|||
virtual void OverrideBaseURI(nsIURI* aNewBaseURI);
|
||||
virtual void SetLineNumber(PRUint32 aLineNumber);
|
||||
|
||||
static void ParseLinkTypes(const nsAString& aTypes, nsTArray<nsString>& aResult);
|
||||
static PRUint32 ParseLinkTypes(const nsAString& aTypes);
|
||||
|
||||
void UpdateStyleSheetInternal() { UpdateStyleSheetInternal(nsnull); }
|
||||
protected:
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
#include "nsStringBuffer.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -1485,6 +1486,8 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
|
|||
// No optional arguments were passed in. Default async to true.
|
||||
async = true;
|
||||
}
|
||||
Telemetry::Accumulate(Telemetry::XMLHTTPREQUEST_ASYNC_OR_SYNC,
|
||||
async ? 0 : 1);
|
||||
|
||||
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
|
|
|
@ -301,16 +301,17 @@ WebGLContext::WebGLContext()
|
|||
|
||||
mContextLost = false;
|
||||
mAllowRestore = false;
|
||||
mRobustnessTimerRunning = false;
|
||||
mDrawSinceRobustnessTimerSet = false;
|
||||
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
}
|
||||
|
||||
WebGLContext::~WebGLContext()
|
||||
{
|
||||
DestroyResourcesAndContext();
|
||||
WebGLMemoryReporter::RemoveWebGLContext(this);
|
||||
if (mContextRestorer) {
|
||||
mContextRestorer->Cancel();
|
||||
mContextRestorer = NULL;
|
||||
}
|
||||
TerminateRobustnessTimer();
|
||||
mContextRestorer = nsnull;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
|
@ -709,6 +710,8 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
|||
mResetLayer = true;
|
||||
mOptionsFrozen = true;
|
||||
|
||||
mHasRobustness = gl->HasRobustness();
|
||||
|
||||
// increment the generation number
|
||||
++mGeneration;
|
||||
|
||||
|
@ -1147,13 +1150,8 @@ WebGLContext::EnsureBackbufferClearedAsNeeded()
|
|||
NS_IMETHODIMP
|
||||
WebGLContext::Notify(nsITimer* timer)
|
||||
{
|
||||
TerminateRobustnessTimer();
|
||||
MaybeRestoreContext();
|
||||
|
||||
if (mContextRestorer) {
|
||||
mContextRestorer->Cancel();
|
||||
mContextRestorer = NULL;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1163,6 +1161,7 @@ WebGLContext::MaybeRestoreContext()
|
|||
if (mContextLost || mAllowRestore)
|
||||
return;
|
||||
|
||||
gl->MakeCurrent();
|
||||
GLContext::ContextResetARB resetStatus =
|
||||
(GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
|
||||
|
||||
|
@ -1174,6 +1173,11 @@ WebGLContext::MaybeRestoreContext()
|
|||
|
||||
switch (resetStatus) {
|
||||
case GLContext::CONTEXT_NO_ERROR:
|
||||
// If there has been activity since the timer was set, it's possible
|
||||
// that we did or are going to miss something, so clear this flag and
|
||||
// run it again some time later.
|
||||
if (mDrawSinceRobustnessTimerSet)
|
||||
SetupRobustnessTimer();
|
||||
return;
|
||||
case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
|
||||
NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
|
||||
|
@ -1191,10 +1195,7 @@ WebGLContext::MaybeRestoreContext()
|
|||
void
|
||||
WebGLContext::ForceLoseContext()
|
||||
{
|
||||
if (mContextRestorer) {
|
||||
mContextRestorer->Cancel();
|
||||
mContextRestorer = NULL;
|
||||
}
|
||||
TerminateRobustnessTimer();
|
||||
|
||||
mWebGLError = LOCAL_GL_CONTEXT_LOST;
|
||||
|
||||
|
|
|
@ -449,17 +449,30 @@ public:
|
|||
// Sets up the GL_ARB_robustness timer if it isn't already, so that if the
|
||||
// driver gets restarted, the context may get reset with it.
|
||||
void SetupRobustnessTimer() {
|
||||
if (mContextLost)
|
||||
if (mContextLost || !mHasRobustness)
|
||||
return;
|
||||
|
||||
if (!mContextRestorer)
|
||||
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
// If the timer was already running, don't restart it here. Instead,
|
||||
// wait until the previous call is done, then fire it one more time.
|
||||
// This is an optimization to prevent unnecessary cross-communication
|
||||
// between threads.
|
||||
if (mRobustnessTimerRunning) {
|
||||
mDrawSinceRobustnessTimerSet = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// As long as there's still activity, we reset the timer each time that
|
||||
// this function gets called.
|
||||
mContextRestorer->InitWithCallback(static_cast<nsITimerCallback*>(this),
|
||||
PR_MillisecondsToInterval(1000),
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mRobustnessTimerRunning = true;
|
||||
mDrawSinceRobustnessTimerSet = false;
|
||||
}
|
||||
|
||||
void TerminateRobustnessTimer() {
|
||||
if (mRobustnessTimerRunning) {
|
||||
mContextRestorer->Cancel();
|
||||
mRobustnessTimerRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -504,6 +517,7 @@ protected:
|
|||
bool mOptionsFrozen;
|
||||
bool mMinCapability;
|
||||
bool mDisableExtensions;
|
||||
bool mHasRobustness;
|
||||
|
||||
WebGLuint mActiveTexture;
|
||||
WebGLenum mWebGLError;
|
||||
|
@ -723,6 +737,8 @@ protected:
|
|||
nsCOMPtr<nsITimer> mContextRestorer;
|
||||
bool mContextLost;
|
||||
bool mAllowRestore;
|
||||
bool mRobustnessTimerRunning;
|
||||
bool mDrawSinceRobustnessTimerSet;
|
||||
|
||||
public:
|
||||
// console logging helpers
|
||||
|
|
|
@ -1622,8 +1622,6 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
|||
if (!ValidateBuffers(&maxAllowedCount, "drawArrays"))
|
||||
return NS_OK;
|
||||
|
||||
SetupRobustnessTimer();
|
||||
|
||||
CheckedInt32 checked_firstPlusCount = CheckedInt32(first) + count;
|
||||
|
||||
if (!checked_firstPlusCount.valid())
|
||||
|
@ -1645,6 +1643,7 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
|||
if (!DoFakeVertexAttrib0(checked_firstPlusCount.value()))
|
||||
return NS_OK;
|
||||
|
||||
SetupRobustnessTimer();
|
||||
gl->fDrawArrays(mode, first, count);
|
||||
|
||||
UndoFakeVertexAttrib0();
|
||||
|
@ -1675,8 +1674,6 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
|||
if (count == 0)
|
||||
return NS_OK;
|
||||
|
||||
SetupRobustnessTimer();
|
||||
|
||||
CheckedUint32 checked_byteCount;
|
||||
|
||||
if (type == LOCAL_GL_UNSIGNED_SHORT) {
|
||||
|
@ -1757,6 +1754,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
|||
if (!DoFakeVertexAttrib0(checked_maxIndexPlusOne.value()))
|
||||
return NS_OK;
|
||||
|
||||
SetupRobustnessTimer();
|
||||
gl->fDrawElements(mode, count, type, (GLvoid*) (byteOffset));
|
||||
|
||||
UndoFakeVertexAttrib0();
|
||||
|
|
|
@ -61,7 +61,7 @@ NS_IMETHODIMP
|
|||
WebGLExtensionLoseContext::LoseContext()
|
||||
{
|
||||
if (!mContext->LoseContext())
|
||||
return mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
||||
mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ NS_IMETHODIMP
|
|||
WebGLExtensionLoseContext::RestoreContext()
|
||||
{
|
||||
if (!mContext->RestoreContext())
|
||||
return mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
||||
mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -3650,8 +3650,8 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
return res.mIsStillLoading ? NS_OK : NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// Ignore nsnull cairo surfaces! See bug 666312.
|
||||
if (!res.mSurface->CairoSurface()) {
|
||||
// Ignore cairo surfaces that are bad! See bug 666312.
|
||||
if (res.mSurface->CairoStatus()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,10 +134,9 @@ function testFailedRender(msg, ref, test, width, height)
|
|||
|
||||
testFailed(msg);
|
||||
|
||||
var data = 'REFTEST TEST-KNOWN-FAIL | ' + msg + ' | image comparison (==)\n' +
|
||||
var data = 'REFTEST TEST-DEBUG-INFO | ' + msg + ' | image comparison (==)\n' +
|
||||
'REFTEST IMAGE 1 (TEST): ' + testData + '\n' +
|
||||
'REFTEST IMAGE 2 (REFERENCE): ' + refData;
|
||||
dump('The following information is for debugging purposes only. It will always print TEST-KNOWN-FAIL, even if it is unexpected.');
|
||||
dump('FAIL: ' + data + '\n');
|
||||
dump('To view the differences between these image renderings, go to the following link: https://hg.mozilla.org/mozilla-central/raw-file/tip/layout/tools/reftest/reftest-analyzer.xhtml#log=' +
|
||||
encodeURIComponent(encodeURIComponent(data)) + '\n');
|
||||
|
|
|
@ -307,9 +307,8 @@ nsHTMLLinkElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
bool dropSheet = false;
|
||||
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::rel &&
|
||||
GetStyleSheet()) {
|
||||
nsAutoTArray<nsString, 4> linkTypes;
|
||||
nsStyleLinkElement::ParseLinkTypes(aValue, linkTypes);
|
||||
dropSheet = !linkTypes.Contains(NS_LITERAL_STRING("stylesheet"));
|
||||
PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(aValue);
|
||||
dropSheet = !(linkTypes & STYLESHEET);
|
||||
}
|
||||
|
||||
UpdateStyleSheetInternal(nsnull,
|
||||
|
@ -413,11 +412,10 @@ nsHTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
|
|||
*aIsAlternate = false;
|
||||
|
||||
nsAutoString rel;
|
||||
nsAutoTArray<nsString, 4> linkTypes;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
|
||||
nsStyleLinkElement::ParseLinkTypes(rel, linkTypes);
|
||||
PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
|
||||
// Is it a stylesheet link?
|
||||
if (!linkTypes.Contains(NS_LITERAL_STRING("stylesheet"))) {
|
||||
if (!(linkTypes & STYLESHEET)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -427,7 +425,7 @@ nsHTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
|
|||
aTitle.Assign(title);
|
||||
|
||||
// If alternate, does it have title?
|
||||
if (linkTypes.Contains(NS_LITERAL_STRING("alternate"))) {
|
||||
if (linkTypes & ALTERNATE) {
|
||||
if (aTitle.IsEmpty()) { // alternates must have title
|
||||
return;
|
||||
} else {
|
||||
|
|
|
@ -2644,18 +2644,16 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
|
|||
nsAutoString relVal;
|
||||
element->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
|
||||
if (!relVal.IsEmpty()) {
|
||||
// XXX seems overkill to generate this string array
|
||||
nsAutoTArray<nsString, 4> linkTypes;
|
||||
nsStyleLinkElement::ParseLinkTypes(relVal, linkTypes);
|
||||
bool hasPrefetch = linkTypes.Contains(NS_LITERAL_STRING("prefetch"));
|
||||
if (hasPrefetch || linkTypes.Contains(NS_LITERAL_STRING("next"))) {
|
||||
PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
|
||||
bool hasPrefetch = linkTypes & PREFETCH;
|
||||
if (hasPrefetch || (linkTypes & NEXT)) {
|
||||
nsAutoString hrefVal;
|
||||
element->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchHref(hrefVal, element, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes.Contains(NS_LITERAL_STRING("dns-prefetch"))) {
|
||||
if (linkTypes & DNS_PREFETCH) {
|
||||
nsAutoString hrefVal;
|
||||
element->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
|
|
|
@ -950,6 +950,7 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
|||
|
||||
// Set the parser as the stream listener for the document loader...
|
||||
if (mParser) {
|
||||
rv = NS_OK;
|
||||
nsCOMPtr<nsIStreamListener> listener = mParser->GetStreamListener();
|
||||
listener.forget(aDocListener);
|
||||
|
||||
|
|
|
@ -90,13 +90,12 @@ public:
|
|||
// nsScriptElement
|
||||
virtual bool HasScriptContent();
|
||||
|
||||
// nsSVGElement specializations:
|
||||
virtual void DidChangeString(PRUint8 aAttrEnum);
|
||||
|
||||
// nsIContent specializations:
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
bool aCompileEventHandlers);
|
||||
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, bool aNotify);
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
|
||||
|
@ -252,16 +251,6 @@ nsSVGScriptElement::HasScriptContent()
|
|||
//----------------------------------------------------------------------
|
||||
// nsSVGElement methods
|
||||
|
||||
void
|
||||
nsSVGScriptElement::DidChangeString(PRUint8 aAttrEnum)
|
||||
{
|
||||
nsSVGScriptElementBase::DidChangeString(aAttrEnum);
|
||||
|
||||
if (aAttrEnum == HREF) {
|
||||
MaybeProcessScript();
|
||||
}
|
||||
}
|
||||
|
||||
nsSVGElement::StringAttributesInfo
|
||||
nsSVGScriptElement::GetStringInfo()
|
||||
{
|
||||
|
@ -289,3 +278,13 @@ nsSVGScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGScriptElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, bool aNotify)
|
||||
{
|
||||
if (aNamespaceID == kNameSpaceID_XLink && aName == nsGkAtoms::href) {
|
||||
MaybeProcessScript();
|
||||
}
|
||||
return nsSVGScriptElementBase::AfterSetAttr(aNamespaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
|
|
@ -646,18 +646,16 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
|
|||
nsAutoString relVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
|
||||
if (!relVal.IsEmpty()) {
|
||||
// XXX seems overkill to generate this string array
|
||||
nsAutoTArray<nsString, 4> linkTypes;
|
||||
nsStyleLinkElement::ParseLinkTypes(relVal, linkTypes);
|
||||
bool hasPrefetch = linkTypes.Contains(NS_LITERAL_STRING("prefetch"));
|
||||
if (hasPrefetch || linkTypes.Contains(NS_LITERAL_STRING("next"))) {
|
||||
PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
|
||||
bool hasPrefetch = linkTypes & PREFETCH;
|
||||
if (hasPrefetch || (linkTypes & NEXT)) {
|
||||
nsAutoString hrefVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchHref(hrefVal, aContent, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes.Contains(NS_LITERAL_STRING("dns-prefetch"))) {
|
||||
if (linkTypes & DNS_PREFETCH) {
|
||||
nsAutoString hrefVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
|
|
|
@ -106,10 +106,4 @@ public:
|
|||
static double toDouble(const nsAString& aStr);
|
||||
};
|
||||
|
||||
// XXX These should go away eventually.
|
||||
#define TxObject txObject
|
||||
typedef txDouble Double;
|
||||
|
||||
// XXX
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,20 +50,20 @@
|
|||
*/
|
||||
|
||||
//-- Initialize Double related constants
|
||||
const dpun Double::NaN = DOUBLE_NaN;
|
||||
const dpun txDouble::NaN = DOUBLE_NaN;
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
const dpun Double::POSITIVE_INFINITY = {{DOUBLE_HI32_EXPMASK, 0}};
|
||||
const dpun Double::NEGATIVE_INFINITY = {{DOUBLE_HI32_EXPMASK | DOUBLE_HI32_SIGNBIT, 0}};
|
||||
const dpun txDouble::POSITIVE_INFINITY = {{DOUBLE_HI32_EXPMASK, 0}};
|
||||
const dpun txDouble::NEGATIVE_INFINITY = {{DOUBLE_HI32_EXPMASK | DOUBLE_HI32_SIGNBIT, 0}};
|
||||
#else
|
||||
const dpun Double::POSITIVE_INFINITY = {{0, DOUBLE_HI32_EXPMASK}};
|
||||
const dpun Double::NEGATIVE_INFINITY = {{0, DOUBLE_HI32_EXPMASK | DOUBLE_HI32_SIGNBIT}};
|
||||
const dpun txDouble::POSITIVE_INFINITY = {{0, DOUBLE_HI32_EXPMASK}};
|
||||
const dpun txDouble::NEGATIVE_INFINITY = {{0, DOUBLE_HI32_EXPMASK | DOUBLE_HI32_SIGNBIT}};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Determines whether the given double represents positive or negative
|
||||
* inifinity
|
||||
*/
|
||||
bool Double::isInfinite(double aDbl)
|
||||
bool txDouble::isInfinite(double aDbl)
|
||||
{
|
||||
return ((DOUBLE_HI32(aDbl) & ~DOUBLE_HI32_SIGNBIT) == DOUBLE_HI32_EXPMASK &&
|
||||
!DOUBLE_LO32(aDbl));
|
||||
|
@ -72,7 +72,7 @@ bool Double::isInfinite(double aDbl)
|
|||
/*
|
||||
* Determines whether the given double is NaN
|
||||
*/
|
||||
bool Double::isNaN(double aDbl)
|
||||
bool txDouble::isNaN(double aDbl)
|
||||
{
|
||||
return DOUBLE_IS_NaN(aDbl);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ bool Double::isNaN(double aDbl)
|
|||
/*
|
||||
* Determines whether the given double is negative
|
||||
*/
|
||||
bool Double::isNeg(double aDbl)
|
||||
bool txDouble::isNeg(double aDbl)
|
||||
{
|
||||
return (DOUBLE_HI32(aDbl) & DOUBLE_HI32_SIGNBIT) != 0;
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ public:
|
|||
{
|
||||
if (mState == eIllegal || mBuffer.IsEmpty() ||
|
||||
(mBuffer.Length() == 1 && mBuffer[0] == '.')) {
|
||||
return Double::NaN;
|
||||
return txDouble::NaN;
|
||||
}
|
||||
return mSign*PR_strtod(mBuffer.get(), 0);
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ private:
|
|||
} mSign;
|
||||
};
|
||||
|
||||
double Double::toDouble(const nsAString& aSrc)
|
||||
double txDouble::toDouble(const nsAString& aSrc)
|
||||
{
|
||||
txStringToDouble sink;
|
||||
nsAString::const_iterator fromBegin, fromEnd;
|
||||
|
@ -202,7 +202,7 @@ double Double::toDouble(const nsAString& aSrc)
|
|||
* The result into the destination String.
|
||||
* @return the given dest string
|
||||
*/
|
||||
void Double::toString(double aValue, nsAString& aDest)
|
||||
void txDouble::toString(double aValue, nsAString& aDest)
|
||||
{
|
||||
|
||||
// check for special cases
|
||||
|
|
|
@ -46,7 +46,7 @@ class txListIterator;
|
|||
/**
|
||||
* Represents an ordered list of Object pointers. Modeled after a Java 2 List.
|
||||
**/
|
||||
class txList : public TxObject {
|
||||
class txList : public txObject {
|
||||
|
||||
friend class txListIterator;
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class ProcessingInstruction;
|
|||
// Abstract Class defining the interface for a Node. See NodeDefinition below
|
||||
// for the actual implementation of the WC3 node.
|
||||
//
|
||||
class Node : public TxObject
|
||||
class Node : public txObject
|
||||
{
|
||||
public:
|
||||
//Node type constants
|
||||
|
|
|
@ -396,8 +396,8 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// check for NaN or +/-Inf
|
||||
if (Double::isNaN(start) ||
|
||||
Double::isInfinite(start) ||
|
||||
if (txDouble::isNaN(start) ||
|
||||
txDouble::isInfinite(start) ||
|
||||
start >= src.Length() + 0.5) {
|
||||
aContext->recycler()->getEmptyStringResult(aResult);
|
||||
|
||||
|
@ -412,7 +412,7 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
end += start;
|
||||
if (Double::isNaN(end) || end < 0) {
|
||||
if (txDouble::isNaN(end) || end < 0) {
|
||||
aContext->recycler()->getEmptyStringResult(aResult);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -546,7 +546,7 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
nsAutoString resultStr;
|
||||
txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
|
||||
resultStr);
|
||||
res = Double::toDouble(resultStr);
|
||||
res = txDouble::toDouble(resultStr);
|
||||
}
|
||||
return aContext->recycler()->getNumberResult(res, aResult);
|
||||
}
|
||||
|
@ -556,8 +556,8 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
rv = evaluateToNumber(mParams[0], aContext, &dbl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) {
|
||||
if (Double::isNeg(dbl) && dbl >= -0.5) {
|
||||
if (!txDouble::isNaN(dbl) && !txDouble::isInfinite(dbl)) {
|
||||
if (txDouble::isNeg(dbl) && dbl >= -0.5) {
|
||||
dbl *= 0;
|
||||
}
|
||||
else {
|
||||
|
@ -573,9 +573,9 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
rv = evaluateToNumber(mParams[0], aContext, &dbl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!Double::isNaN(dbl) &&
|
||||
!Double::isInfinite(dbl) &&
|
||||
!(dbl == 0 && Double::isNeg(dbl))) {
|
||||
if (!txDouble::isNaN(dbl) &&
|
||||
!txDouble::isInfinite(dbl) &&
|
||||
!(dbl == 0 && txDouble::isNeg(dbl))) {
|
||||
dbl = floor(dbl);
|
||||
}
|
||||
|
||||
|
@ -587,8 +587,8 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
rv = evaluateToNumber(mParams[0], aContext, &dbl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) {
|
||||
if (Double::isNeg(dbl) && dbl > -1) {
|
||||
if (!txDouble::isNaN(dbl) && !txDouble::isInfinite(dbl)) {
|
||||
if (txDouble::isNeg(dbl) && dbl > -1) {
|
||||
dbl *= 0;
|
||||
}
|
||||
else {
|
||||
|
@ -610,7 +610,7 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
for (i = 0; i < nodes->size(); ++i) {
|
||||
nsAutoString resultStr;
|
||||
txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
|
||||
res += Double::toDouble(resultStr);
|
||||
res += txDouble::toDouble(resultStr);
|
||||
}
|
||||
return aContext->recycler()->getNumberResult(res, aResult);
|
||||
}
|
||||
|
|
|
@ -419,7 +419,7 @@ txExprParser::createFilterOrStep(txExprLexer& lexer, txIParseContext* aContext,
|
|||
break;
|
||||
case Token::NUMBER:
|
||||
{
|
||||
expr = new txLiteralExpr(Double::toDouble(tok->Value()));
|
||||
expr = new txLiteralExpr(txDouble::toDouble(tok->Value()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -103,7 +103,7 @@ txLiteralExpr::toString(nsAString& aStr)
|
|||
}
|
||||
case txAExprResult::NUMBER:
|
||||
{
|
||||
Double::toString(mValue->numberValue(), aStr);
|
||||
txDouble::toString(mValue->numberValue(), aStr);
|
||||
return;
|
||||
}
|
||||
case txAExprResult::STRING:
|
||||
|
|
|
@ -501,7 +501,7 @@ txNodeSet::numberValue()
|
|||
nsAutoString str;
|
||||
stringValue(str);
|
||||
|
||||
return Double::toDouble(str);
|
||||
return txDouble::toDouble(str);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -86,7 +86,7 @@ txNodeSetAdaptor::ItemAsNumber(PRUint32 aIndex, double *aResult)
|
|||
nsAutoString result;
|
||||
txXPathNodeUtils::appendNodeValue(NodeSet()->get(aIndex), result);
|
||||
|
||||
*aResult = Double::toDouble(result);
|
||||
*aResult = txDouble::toDouble(result);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -70,16 +70,16 @@ txNumberExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
if (rightDbl == 0) {
|
||||
#if defined(XP_WIN)
|
||||
/* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
if (Double::isNaN(rightDbl))
|
||||
result = Double::NaN;
|
||||
if (txDouble::isNaN(rightDbl))
|
||||
result = txDouble::NaN;
|
||||
else
|
||||
#endif
|
||||
if (leftDbl == 0 || Double::isNaN(leftDbl))
|
||||
result = Double::NaN;
|
||||
else if (Double::isNeg(leftDbl) ^ Double::isNeg(rightDbl))
|
||||
result = Double::NEGATIVE_INFINITY;
|
||||
if (leftDbl == 0 || txDouble::isNaN(leftDbl))
|
||||
result = txDouble::NaN;
|
||||
else if (txDouble::isNeg(leftDbl) ^ txDouble::isNeg(rightDbl))
|
||||
result = txDouble::NEGATIVE_INFINITY;
|
||||
else
|
||||
result = Double::POSITIVE_INFINITY;
|
||||
result = txDouble::POSITIVE_INFINITY;
|
||||
}
|
||||
else
|
||||
result = leftDbl / rightDbl;
|
||||
|
@ -87,12 +87,12 @@ txNumberExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|||
|
||||
case MODULUS:
|
||||
if (rightDbl == 0) {
|
||||
result = Double::NaN;
|
||||
result = txDouble::NaN;
|
||||
}
|
||||
else {
|
||||
#if defined(XP_WIN)
|
||||
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
|
||||
if (!Double::isInfinite(leftDbl) && Double::isInfinite(rightDbl))
|
||||
if (!txDouble::isInfinite(leftDbl) && txDouble::isInfinite(rightDbl))
|
||||
result = leftDbl;
|
||||
else
|
||||
#endif
|
||||
|
|
|
@ -67,7 +67,7 @@ short NumberResult::getResultType() {
|
|||
void
|
||||
NumberResult::stringValue(nsString& aResult)
|
||||
{
|
||||
Double::toString(value, aResult);
|
||||
txDouble::toString(value, aResult);
|
||||
}
|
||||
|
||||
const nsString*
|
||||
|
@ -80,7 +80,7 @@ bool NumberResult::booleanValue() {
|
|||
// OG+
|
||||
// As per the XPath spec, the boolean value of a number is true if and only if
|
||||
// it is neither positive 0 nor negative 0 nor NaN
|
||||
return (bool)(value != 0.0 && !Double::isNaN(value));
|
||||
return (bool)(value != 0.0 && !txDouble::isNaN(value));
|
||||
// OG-
|
||||
} //-- booleanValue
|
||||
|
||||
|
|
|
@ -84,6 +84,6 @@ bool StringResult::booleanValue() {
|
|||
} //-- booleanValue
|
||||
|
||||
double StringResult::numberValue() {
|
||||
return Double::toDouble(mValue);
|
||||
return txDouble::toDouble(mValue);
|
||||
} //-- numberValue
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ double
|
|||
txUnionNodeTest::getDefaultPriority()
|
||||
{
|
||||
NS_ERROR("Don't call getDefaultPriority on txUnionPattern");
|
||||
return Double::NaN;
|
||||
return txDouble::NaN;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -611,7 +611,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
|
|||
|
||||
if (nodes->isEmpty()) {
|
||||
return aContext->recycler()->
|
||||
getNumberResult(Double::NaN, aResult);
|
||||
getNumberResult(txDouble::NaN, aResult);
|
||||
}
|
||||
|
||||
bool findMax = mType == MAX;
|
||||
|
@ -622,9 +622,9 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
|
|||
for (i = 0; i < len; ++i) {
|
||||
nsAutoString str;
|
||||
txXPathNodeUtils::appendNodeValue(nodes->get(i), str);
|
||||
double val = Double::toDouble(str);
|
||||
if (Double::isNaN(val)) {
|
||||
res = Double::NaN;
|
||||
double val = txDouble::toDouble(str);
|
||||
if (txDouble::isNaN(val)) {
|
||||
res = txDouble::NaN;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -661,8 +661,8 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
|
|||
nsAutoString str;
|
||||
const txXPathNode& node = nodes->get(i);
|
||||
txXPathNodeUtils::appendNodeValue(node, str);
|
||||
double val = Double::toDouble(str);
|
||||
if (Double::isNaN(val)) {
|
||||
double val = txDouble::toDouble(str);
|
||||
if (txDouble::isNaN(val)) {
|
||||
resultSet->clear();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -112,16 +112,16 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext,
|
|||
}
|
||||
|
||||
// Special cases
|
||||
if (Double::isNaN(value)) {
|
||||
if (txDouble::isNaN(value)) {
|
||||
return aContext->recycler()->getStringResult(format->mNaN, aResult);
|
||||
}
|
||||
|
||||
if (value == Double::POSITIVE_INFINITY) {
|
||||
if (value == txDouble::POSITIVE_INFINITY) {
|
||||
return aContext->recycler()->getStringResult(format->mInfinity,
|
||||
aResult);
|
||||
}
|
||||
|
||||
if (value == Double::NEGATIVE_INFINITY) {
|
||||
if (value == txDouble::NEGATIVE_INFINITY) {
|
||||
nsAutoString res;
|
||||
res.Append(format->mMinusSign);
|
||||
res.Append(format->mInfinity);
|
||||
|
@ -143,7 +143,7 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext,
|
|||
|
||||
// Get right subexpression
|
||||
inQuote = false;
|
||||
if (Double::isNeg(value)) {
|
||||
if (txDouble::isNeg(value)) {
|
||||
while (pos < formatLen &&
|
||||
(inQuote ||
|
||||
formatStr.CharAt(pos) != format->mPatternSeparator)) {
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
class nsIAtom;
|
||||
class txExecutionState;
|
||||
|
||||
class txInstruction : public TxObject
|
||||
class txInstruction : public txObject
|
||||
{
|
||||
public:
|
||||
txInstruction()
|
||||
|
|
|
@ -180,8 +180,8 @@ txNodeSorter::sortNodeSet(txNodeSet* aNodes, txExecutionState* aEs,
|
|||
PRUint32 len = static_cast<PRUint32>(aNodes->size());
|
||||
|
||||
// Limit resource use to something sane.
|
||||
PRUint32 itemSize = sizeof(PRUint32) + mNKeys * sizeof(TxObject*);
|
||||
if (mNKeys > (PR_UINT32_MAX - sizeof(PRUint32)) / sizeof(TxObject*) ||
|
||||
PRUint32 itemSize = sizeof(PRUint32) + mNKeys * sizeof(txObject*);
|
||||
if (mNKeys > (PR_UINT32_MAX - sizeof(PRUint32)) / sizeof(txObject*) ||
|
||||
len >= PR_UINT32_MAX / itemSize) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -190,13 +190,13 @@ txNodeSorter::sortNodeSet(txNodeSet* aNodes, txExecutionState* aEs,
|
|||
NS_ENSURE_TRUE(mem, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PRUint32* indexes = static_cast<PRUint32*>(mem);
|
||||
TxObject** sortValues = reinterpret_cast<TxObject**>(indexes + len);
|
||||
txObject** sortValues = reinterpret_cast<txObject**>(indexes + len);
|
||||
|
||||
PRUint32 i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
indexes[i] = i;
|
||||
}
|
||||
memset(sortValues, 0, len * mNKeys * sizeof(TxObject*));
|
||||
memset(sortValues, 0, len * mNKeys * sizeof(txObject*));
|
||||
|
||||
// Sort the indexarray
|
||||
SortData sortData;
|
||||
|
@ -248,9 +248,9 @@ txNodeSorter::compareNodes(const void* aIndexA, const void* aIndexB,
|
|||
txListIterator iter(&sortData->mNodeSorter->mSortKeys);
|
||||
PRUint32 indexA = *static_cast<const PRUint32*>(aIndexA);
|
||||
PRUint32 indexB = *static_cast<const PRUint32*>(aIndexB);
|
||||
TxObject** sortValuesA = sortData->mSortValues +
|
||||
txObject** sortValuesA = sortData->mSortValues +
|
||||
indexA * sortData->mNodeSorter->mNKeys;
|
||||
TxObject** sortValuesB = sortData->mSortValues +
|
||||
txObject** sortValuesB = sortData->mSortValues +
|
||||
indexB * sortData->mNodeSorter->mNKeys;
|
||||
|
||||
unsigned int i;
|
||||
|
@ -280,7 +280,7 @@ txNodeSorter::compareNodes(const void* aIndexA, const void* aIndexB,
|
|||
|
||||
//static
|
||||
bool
|
||||
txNodeSorter::calcSortValue(TxObject*& aSortValue, SortKey* aKey,
|
||||
txNodeSorter::calcSortValue(txObject*& aSortValue, SortKey* aKey,
|
||||
SortData* aSortData, PRUint32 aNodeIndex)
|
||||
{
|
||||
aSortData->mContext->setPosition(aNodeIndex + 1); // position is 1-based
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
class Expr;
|
||||
class txExecutionState;
|
||||
class txNodeSet;
|
||||
class TxObject;
|
||||
class txObject;
|
||||
class txXPathResultComparator;
|
||||
class txIEvalContext;
|
||||
class txNodeSetContext;
|
||||
|
@ -72,7 +72,7 @@ private:
|
|||
{
|
||||
txNodeSorter* mNodeSorter;
|
||||
txNodeSetContext* mContext;
|
||||
TxObject** mSortValues;
|
||||
txObject** mSortValues;
|
||||
nsresult mRv;
|
||||
};
|
||||
struct SortKey
|
||||
|
@ -83,8 +83,8 @@ private:
|
|||
|
||||
static int compareNodes(const void* aIndexA, const void* aIndexB,
|
||||
void* aSortData);
|
||||
static bool calcSortValue(TxObject*& aSortValue, SortKey* aKey,
|
||||
SortData* aSortData, PRUint32 aNodeIndex);
|
||||
static bool calcSortValue(txObject*& aSortValue, SortKey* aKey,
|
||||
SortData* aSortData, PRUint32 aNodeIndex);
|
||||
txList mSortKeys;
|
||||
unsigned int mNKeys;
|
||||
};
|
||||
|
|
|
@ -77,7 +77,7 @@ double txResultTreeFragment::numberValue()
|
|||
return 0;
|
||||
}
|
||||
|
||||
return Double::toDouble(mBuffer->mStringValue);
|
||||
return txDouble::toDouble(mBuffer->mStringValue);
|
||||
}
|
||||
|
||||
nsresult txResultTreeFragment::flushToHandler(txAXMLEventHandler* aHandler)
|
||||
|
|
|
@ -442,9 +442,9 @@ txStylesheet::addTemplate(txTemplateItem* aTemplate,
|
|||
PRUint32 unionPos = 1; // only used when unionPattern is set
|
||||
while (simple) {
|
||||
double priority = aTemplate->mPrio;
|
||||
if (Double::isNaN(priority)) {
|
||||
if (txDouble::isNaN(priority)) {
|
||||
priority = simple->getDefaultPriority();
|
||||
NS_ASSERTION(!Double::isNaN(priority),
|
||||
NS_ASSERTION(!txDouble::isNaN(priority),
|
||||
"simple pattern without default priority");
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ public:
|
|||
ImportFrame* mFirstNotImported;
|
||||
};
|
||||
|
||||
class GlobalVariable : public TxObject {
|
||||
class GlobalVariable : public txObject {
|
||||
public:
|
||||
GlobalVariable(nsAutoPtr<Expr> aExpr,
|
||||
nsAutoPtr<txInstruction> aFirstInstruction,
|
||||
|
|
|
@ -303,7 +303,7 @@ getNumberAttr(txStylesheetAttr* aAttributes,
|
|||
txStylesheetCompilerState& aState,
|
||||
double& aNumber)
|
||||
{
|
||||
aNumber = Double::NaN;
|
||||
aNumber = txDouble::NaN;
|
||||
txStylesheetAttr* attr = nsnull;
|
||||
nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
|
||||
aName, aRequired, &attr);
|
||||
|
@ -311,8 +311,8 @@ getNumberAttr(txStylesheetAttr* aAttributes,
|
|||
return rv;
|
||||
}
|
||||
|
||||
aNumber = Double::toDouble(attr->mValue);
|
||||
if (Double::isNaN(aNumber) && (aRequired || !aState.fcp())) {
|
||||
aNumber = txDouble::toDouble(attr->mValue);
|
||||
if (txDouble::isNaN(aNumber) && (aRequired || !aState.fcp())) {
|
||||
// XXX ErrorReport: number parse failure
|
||||
return NS_ERROR_XSLT_PARSE_FAILURE;
|
||||
}
|
||||
|
@ -552,7 +552,7 @@ txFnStartLREStylesheet(PRInt32 aNamespaceID,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
txExpandedName nullExpr;
|
||||
double prio = Double::NaN;
|
||||
double prio = txDouble::NaN;
|
||||
|
||||
nsAutoPtr<txPattern> match(new txRootPattern());
|
||||
NS_ENSURE_TRUE(match, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -1145,7 +1145,7 @@ txFnStartTemplate(PRInt32 aNamespaceID,
|
|||
aState, mode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
double prio = Double::NaN;
|
||||
double prio = txDouble::NaN;
|
||||
rv = getNumberAttr(aAttributes, aAttrCount, nsGkAtoms::priority,
|
||||
false, aState, prio);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -688,15 +688,15 @@ txStylesheetCompilerState::popChooseGotoList()
|
|||
}
|
||||
|
||||
nsresult
|
||||
txStylesheetCompilerState::pushObject(TxObject* aObject)
|
||||
txStylesheetCompilerState::pushObject(txObject* aObject)
|
||||
{
|
||||
return mObjectStack.push(aObject);
|
||||
}
|
||||
|
||||
TxObject*
|
||||
txObject*
|
||||
txStylesheetCompilerState::popObject()
|
||||
{
|
||||
return static_cast<TxObject*>(mObjectStack.pop());
|
||||
return static_cast<txObject*>(mObjectStack.pop());
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -60,7 +60,7 @@ class txPushNewContext;
|
|||
class txStylesheetCompiler;
|
||||
class txInScopeVariable;
|
||||
|
||||
class txElementContext : public TxObject
|
||||
class txElementContext : public txObject
|
||||
{
|
||||
public:
|
||||
txElementContext(const nsAString& aBaseURI);
|
||||
|
@ -122,8 +122,8 @@ public:
|
|||
void popSorter();
|
||||
nsresult pushChooseGotoList();
|
||||
void popChooseGotoList();
|
||||
nsresult pushObject(TxObject* aObject);
|
||||
TxObject* popObject();
|
||||
nsresult pushObject(txObject* aObject);
|
||||
txObject* popObject();
|
||||
nsresult pushPtr(void* aPtr);
|
||||
void* popPtr();
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ txResultStringComparator::createSortableValue(Expr *aExpr,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
int txResultStringComparator::compareValues(TxObject* aVal1, TxObject* aVal2)
|
||||
int txResultStringComparator::compareValues(txObject* aVal1, txObject* aVal2)
|
||||
{
|
||||
StringValue* strval1 = (StringValue*)aVal1;
|
||||
StringValue* strval2 = (StringValue*)aVal2;
|
||||
|
@ -223,7 +223,7 @@ txResultNumberComparator::txResultNumberComparator(bool aAscending)
|
|||
nsresult
|
||||
txResultNumberComparator::createSortableValue(Expr *aExpr,
|
||||
txIEvalContext *aContext,
|
||||
TxObject *&aResult)
|
||||
txObject *&aResult)
|
||||
{
|
||||
nsAutoPtr<NumberValue> numval(new NumberValue);
|
||||
if (!numval) {
|
||||
|
@ -241,15 +241,15 @@ txResultNumberComparator::createSortableValue(Expr *aExpr,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
int txResultNumberComparator::compareValues(TxObject* aVal1, TxObject* aVal2)
|
||||
int txResultNumberComparator::compareValues(txObject* aVal1, txObject* aVal2)
|
||||
{
|
||||
double dval1 = ((NumberValue*)aVal1)->mVal;
|
||||
double dval2 = ((NumberValue*)aVal2)->mVal;
|
||||
|
||||
if (Double::isNaN(dval1))
|
||||
return Double::isNaN(dval2) ? 0 : -mAscending;
|
||||
if (txDouble::isNaN(dval1))
|
||||
return txDouble::isNaN(dval2) ? 0 : -mAscending;
|
||||
|
||||
if (Double::isNaN(dval2))
|
||||
if (txDouble::isNaN(dval2))
|
||||
return mAscending;
|
||||
|
||||
if (dval1 == dval2)
|
||||
|
|
|
@ -62,13 +62,13 @@ public:
|
|||
* Compares two XPath results. Returns -1 if val1 < val2,
|
||||
* 1 if val1 > val2 and 0 if val1 == val2.
|
||||
*/
|
||||
virtual int compareValues(TxObject* val1, TxObject* val2) = 0;
|
||||
virtual int compareValues(txObject* val1, txObject* val2) = 0;
|
||||
|
||||
/*
|
||||
* Create a sortable value.
|
||||
*/
|
||||
virtual nsresult createSortableValue(Expr *aExpr, txIEvalContext *aContext,
|
||||
TxObject *&aResult) = 0;
|
||||
txObject *&aResult) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -80,9 +80,9 @@ public:
|
|||
txResultStringComparator(bool aAscending, bool aUpperFirst,
|
||||
const nsAFlatString& aLanguage);
|
||||
|
||||
int compareValues(TxObject* aVal1, TxObject* aVal2);
|
||||
int compareValues(txObject* aVal1, txObject* aVal2);
|
||||
nsresult createSortableValue(Expr *aExpr, txIEvalContext *aContext,
|
||||
TxObject *&aResult);
|
||||
txObject *&aResult);
|
||||
private:
|
||||
nsCOMPtr<nsICollation> mCollation;
|
||||
nsresult init(const nsAFlatString& aLanguage);
|
||||
|
@ -92,7 +92,7 @@ private:
|
|||
PRUint32* aLength);
|
||||
int mSorting;
|
||||
|
||||
class StringValue : public TxObject
|
||||
class StringValue : public txObject
|
||||
{
|
||||
public:
|
||||
StringValue();
|
||||
|
@ -112,14 +112,14 @@ class txResultNumberComparator : public txXPathResultComparator
|
|||
public:
|
||||
txResultNumberComparator(bool aAscending);
|
||||
|
||||
int compareValues(TxObject* aVal1, TxObject* aVal2);
|
||||
int compareValues(txObject* aVal1, txObject* aVal2);
|
||||
nsresult createSortableValue(Expr *aExpr, txIEvalContext *aContext,
|
||||
TxObject *&aResult);
|
||||
txObject *&aResult);
|
||||
|
||||
private:
|
||||
int mAscending;
|
||||
|
||||
class NumberValue : public TxObject
|
||||
class NumberValue : public txObject
|
||||
{
|
||||
public:
|
||||
double mVal;
|
||||
|
|
|
@ -122,9 +122,9 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
|
|||
|
||||
double value = result->numberValue();
|
||||
|
||||
if (Double::isInfinite(value) || Double::isNaN(value) ||
|
||||
if (txDouble::isInfinite(value) || txDouble::isNaN(value) ||
|
||||
value < 0.5) {
|
||||
Double::toString(value, aValueString);
|
||||
txDouble::toString(value, aValueString);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -318,7 +318,7 @@ txXSLTNumber::getCounters(Expr* aGroupSize, Expr* aGroupSeparator,
|
|||
rv = aGroupSize->evaluateToString(aContext, sizeStr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
double size = Double::toDouble(sizeStr);
|
||||
double size = txDouble::toDouble(sizeStr);
|
||||
groupSize = (PRInt32)size;
|
||||
if ((double)groupSize != size) {
|
||||
groupSize = 0;
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
double txUnionPattern::getDefaultPriority()
|
||||
{
|
||||
NS_ERROR("Don't call getDefaultPriority on txUnionPattern");
|
||||
return Double::NaN;
|
||||
return txDouble::NaN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -203,7 +203,7 @@ WifiGeoPositionProvider.prototype = {
|
|||
|
||||
let accessToken = this.getAccessTokenForURL(providerUrlBase);
|
||||
if (accessToken !== "")
|
||||
providerUrl = providerUrl + "&access_token="+access_token;
|
||||
providerUrl = providerUrl + "&access_token="+accessToken;
|
||||
|
||||
function sort(a, b) {
|
||||
return b.signal - a.signal;
|
||||
|
|
|
@ -5170,6 +5170,7 @@ nsEditor::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
|
|||
|
||||
// Init selection
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
// If the computed selection root isn't root content, we should set it
|
||||
// as selection ancestor limit. However, if that is root element, it means
|
||||
|
|
|
@ -0,0 +1,527 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla gfx.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/gfx/Blur.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "CheckedInt.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
/**
|
||||
* Box blur involves looking at one pixel, and setting its value to the average
|
||||
* of its neighbouring pixels.
|
||||
* @param aInput The input buffer.
|
||||
* @param aOutput The output buffer.
|
||||
* @param aLeftLobe The number of pixels to blend on the left.
|
||||
* @param aRightLobe The number of pixels to blend on the right.
|
||||
* @param aWidth The number of columns in the buffers.
|
||||
* @param aRows The number of rows in the buffers.
|
||||
* @param aSkipRect An area to skip blurring in.
|
||||
* XXX shouldn't we pass stride in separately here?
|
||||
*/
|
||||
static void
|
||||
BoxBlurHorizontal(unsigned char* aInput,
|
||||
unsigned char* aOutput,
|
||||
int32_t aLeftLobe,
|
||||
int32_t aRightLobe,
|
||||
int32_t aWidth,
|
||||
int32_t aRows,
|
||||
const IntRect& aSkipRect)
|
||||
{
|
||||
MOZ_ASSERT(aWidth > 0);
|
||||
|
||||
int32_t boxSize = aLeftLobe + aRightLobe + 1;
|
||||
bool skipRectCoversWholeRow = 0 >= aSkipRect.x &&
|
||||
aWidth <= aSkipRect.XMost();
|
||||
|
||||
for (int32_t y = 0; y < aRows; y++) {
|
||||
// Check whether the skip rect intersects this row. If the skip
|
||||
// rect covers the whole surface in this row, we can avoid
|
||||
// this row entirely (and any others along the skip rect).
|
||||
bool inSkipRectY = y >= aSkipRect.y &&
|
||||
y < aSkipRect.YMost();
|
||||
if (inSkipRectY && skipRectCoversWholeRow) {
|
||||
y = aSkipRect.YMost() - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t alphaSum = 0;
|
||||
for (int32_t i = 0; i < boxSize; i++) {
|
||||
int32_t pos = i - aLeftLobe;
|
||||
// See assertion above; if aWidth is zero, then we would have no
|
||||
// valid position to clamp to.
|
||||
pos = max(pos, 0);
|
||||
pos = min(pos, aWidth - 1);
|
||||
alphaSum += aInput[aWidth * y + pos];
|
||||
}
|
||||
for (int32_t x = 0; x < aWidth; x++) {
|
||||
// Check whether we are within the skip rect. If so, go
|
||||
// to the next point outside the skip rect.
|
||||
if (inSkipRectY && x >= aSkipRect.x &&
|
||||
x < aSkipRect.XMost()) {
|
||||
x = aSkipRect.XMost();
|
||||
if (x >= aWidth)
|
||||
break;
|
||||
|
||||
// Recalculate the neighbouring alpha values for
|
||||
// our new point on the surface.
|
||||
alphaSum = 0;
|
||||
for (int32_t i = 0; i < boxSize; i++) {
|
||||
int32_t pos = x + i - aLeftLobe;
|
||||
// See assertion above; if aWidth is zero, then we would have no
|
||||
// valid position to clamp to.
|
||||
pos = max(pos, 0);
|
||||
pos = min(pos, aWidth - 1);
|
||||
alphaSum += aInput[aWidth * y + pos];
|
||||
}
|
||||
}
|
||||
int32_t tmp = x - aLeftLobe;
|
||||
int32_t last = max(tmp, 0);
|
||||
int32_t next = min(tmp + boxSize, aWidth - 1);
|
||||
|
||||
aOutput[aWidth * y + x] = alphaSum / boxSize;
|
||||
|
||||
alphaSum += aInput[aWidth * y + next] -
|
||||
aInput[aWidth * y + last];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to BoxBlurHorizontal, except it blurs top and bottom instead of
|
||||
* left and right.
|
||||
* XXX shouldn't we pass stride in separately here?
|
||||
*/
|
||||
static void
|
||||
BoxBlurVertical(unsigned char* aInput,
|
||||
unsigned char* aOutput,
|
||||
int32_t aTopLobe,
|
||||
int32_t aBottomLobe,
|
||||
int32_t aWidth,
|
||||
int32_t aRows,
|
||||
const IntRect& aSkipRect)
|
||||
{
|
||||
MOZ_ASSERT(aRows > 0);
|
||||
|
||||
int32_t boxSize = aTopLobe + aBottomLobe + 1;
|
||||
bool skipRectCoversWholeColumn = 0 >= aSkipRect.y &&
|
||||
aRows <= aSkipRect.YMost();
|
||||
|
||||
for (int32_t x = 0; x < aWidth; x++) {
|
||||
bool inSkipRectX = x >= aSkipRect.x &&
|
||||
x < aSkipRect.XMost();
|
||||
if (inSkipRectX && skipRectCoversWholeColumn) {
|
||||
x = aSkipRect.XMost() - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t alphaSum = 0;
|
||||
for (int32_t i = 0; i < boxSize; i++) {
|
||||
int32_t pos = i - aTopLobe;
|
||||
// See assertion above; if aRows is zero, then we would have no
|
||||
// valid position to clamp to.
|
||||
pos = max(pos, 0);
|
||||
pos = min(pos, aRows - 1);
|
||||
alphaSum += aInput[aWidth * pos + x];
|
||||
}
|
||||
for (int32_t y = 0; y < aRows; y++) {
|
||||
if (inSkipRectX && y >= aSkipRect.y &&
|
||||
y < aSkipRect.YMost()) {
|
||||
y = aSkipRect.YMost();
|
||||
if (y >= aRows)
|
||||
break;
|
||||
|
||||
alphaSum = 0;
|
||||
for (int32_t i = 0; i < boxSize; i++) {
|
||||
int32_t pos = y + i - aTopLobe;
|
||||
// See assertion above; if aRows is zero, then we would have no
|
||||
// valid position to clamp to.
|
||||
pos = max(pos, 0);
|
||||
pos = min(pos, aRows - 1);
|
||||
alphaSum += aInput[aWidth * pos + x];
|
||||
}
|
||||
}
|
||||
int32_t tmp = y - aTopLobe;
|
||||
int32_t last = max(tmp, 0);
|
||||
int32_t next = min(tmp + boxSize, aRows - 1);
|
||||
|
||||
aOutput[aWidth * y + x] = alphaSum/boxSize;
|
||||
|
||||
alphaSum += aInput[aWidth * next + x] -
|
||||
aInput[aWidth * last + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ComputeLobes(int32_t aRadius, int32_t aLobes[3][2])
|
||||
{
|
||||
int32_t major, minor, final;
|
||||
|
||||
/* See http://www.w3.org/TR/SVG/filters.html#feGaussianBlur for
|
||||
* some notes about approximating the Gaussian blur with box-blurs.
|
||||
* The comments below are in the terminology of that page.
|
||||
*/
|
||||
int32_t z = aRadius / 3;
|
||||
switch (aRadius % 3) {
|
||||
case 0:
|
||||
// aRadius = z*3; choose d = 2*z + 1
|
||||
major = minor = final = z;
|
||||
break;
|
||||
case 1:
|
||||
// aRadius = z*3 + 1
|
||||
// This is a tricky case since there is no value of d which will
|
||||
// yield a radius of exactly aRadius. If d is odd, i.e. d=2*k + 1
|
||||
// for some integer k, then the radius will be 3*k. If d is even,
|
||||
// i.e. d=2*k, then the radius will be 3*k - 1.
|
||||
// So we have to choose values that don't match the standard
|
||||
// algorithm.
|
||||
major = z + 1;
|
||||
minor = final = z;
|
||||
break;
|
||||
case 2:
|
||||
// aRadius = z*3 + 2; choose d = 2*z + 2
|
||||
major = final = z + 1;
|
||||
minor = z;
|
||||
break;
|
||||
default:
|
||||
// Mathematical impossibility!
|
||||
MOZ_ASSERT(false);
|
||||
major = minor = final = 0;
|
||||
}
|
||||
MOZ_ASSERT(major + minor + final == aRadius);
|
||||
|
||||
aLobes[0][0] = major;
|
||||
aLobes[0][1] = minor;
|
||||
aLobes[1][0] = minor;
|
||||
aLobes[1][1] = major;
|
||||
aLobes[2][0] = final;
|
||||
aLobes[2][1] = final;
|
||||
}
|
||||
|
||||
static void
|
||||
SpreadHorizontal(unsigned char* aInput,
|
||||
unsigned char* aOutput,
|
||||
int32_t aRadius,
|
||||
int32_t aWidth,
|
||||
int32_t aRows,
|
||||
int32_t aStride,
|
||||
const IntRect& aSkipRect)
|
||||
{
|
||||
if (aRadius == 0) {
|
||||
memcpy(aOutput, aInput, aStride * aRows);
|
||||
return;
|
||||
}
|
||||
|
||||
bool skipRectCoversWholeRow = 0 >= aSkipRect.x &&
|
||||
aWidth <= aSkipRect.XMost();
|
||||
for (int32_t y = 0; y < aRows; y++) {
|
||||
// Check whether the skip rect intersects this row. If the skip
|
||||
// rect covers the whole surface in this row, we can avoid
|
||||
// this row entirely (and any others along the skip rect).
|
||||
bool inSkipRectY = y >= aSkipRect.y &&
|
||||
y < aSkipRect.YMost();
|
||||
if (inSkipRectY && skipRectCoversWholeRow) {
|
||||
y = aSkipRect.YMost() - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int32_t x = 0; x < aWidth; x++) {
|
||||
// Check whether we are within the skip rect. If so, go
|
||||
// to the next point outside the skip rect.
|
||||
if (inSkipRectY && x >= aSkipRect.x &&
|
||||
x < aSkipRect.XMost()) {
|
||||
x = aSkipRect.XMost();
|
||||
if (x >= aWidth)
|
||||
break;
|
||||
}
|
||||
|
||||
int32_t sMin = max(x - aRadius, 0);
|
||||
int32_t sMax = min(x + aRadius, aWidth - 1);
|
||||
int32_t v = 0;
|
||||
for (int32_t s = sMin; s <= sMax; ++s) {
|
||||
v = max<int32_t>(v, aInput[aStride * y + s]);
|
||||
}
|
||||
aOutput[aStride * y + x] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SpreadVertical(unsigned char* aInput,
|
||||
unsigned char* aOutput,
|
||||
int32_t aRadius,
|
||||
int32_t aWidth,
|
||||
int32_t aRows,
|
||||
int32_t aStride,
|
||||
const IntRect& aSkipRect)
|
||||
{
|
||||
if (aRadius == 0) {
|
||||
memcpy(aOutput, aInput, aStride * aRows);
|
||||
return;
|
||||
}
|
||||
|
||||
bool skipRectCoversWholeColumn = 0 >= aSkipRect.y &&
|
||||
aRows <= aSkipRect.YMost();
|
||||
for (int32_t x = 0; x < aWidth; x++) {
|
||||
bool inSkipRectX = x >= aSkipRect.x &&
|
||||
x < aSkipRect.XMost();
|
||||
if (inSkipRectX && skipRectCoversWholeColumn) {
|
||||
x = aSkipRect.XMost() - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int32_t y = 0; y < aRows; y++) {
|
||||
// Check whether we are within the skip rect. If so, go
|
||||
// to the next point outside the skip rect.
|
||||
if (inSkipRectX && y >= aSkipRect.y &&
|
||||
y < aSkipRect.YMost()) {
|
||||
y = aSkipRect.YMost();
|
||||
if (y >= aRows)
|
||||
break;
|
||||
}
|
||||
|
||||
int32_t sMin = max(y - aRadius, 0);
|
||||
int32_t sMax = min(y + aRadius, aRows - 1);
|
||||
int32_t v = 0;
|
||||
for (int32_t s = sMin; s <= sMax; ++s) {
|
||||
v = max<int32_t>(v, aInput[aStride * s + x]);
|
||||
}
|
||||
aOutput[aStride * y + x] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static CheckedInt<int32_t>
|
||||
RoundUpToMultipleOf4(int32_t aVal)
|
||||
{
|
||||
CheckedInt<int32_t> val(aVal);
|
||||
|
||||
val += 3;
|
||||
val /= 4;
|
||||
val *= 4;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
|
||||
const IntSize& aSpreadRadius,
|
||||
const IntSize& aBlurRadius,
|
||||
const Rect* aDirtyRect,
|
||||
const Rect* aSkipRect)
|
||||
: mSpreadRadius(aSpreadRadius),
|
||||
mBlurRadius(aBlurRadius),
|
||||
mData(NULL)
|
||||
{
|
||||
Rect rect(aRect);
|
||||
rect.Inflate(Size(aBlurRadius + aSpreadRadius));
|
||||
rect.RoundOut();
|
||||
|
||||
if (aDirtyRect) {
|
||||
// If we get passed a dirty rect from layout, we can minimize the
|
||||
// shadow size and make painting faster.
|
||||
mHasDirtyRect = true;
|
||||
mDirtyRect = *aDirtyRect;
|
||||
Rect requiredBlurArea = mDirtyRect.Intersect(rect);
|
||||
requiredBlurArea.Inflate(Size(aBlurRadius + aSpreadRadius));
|
||||
rect = requiredBlurArea.Intersect(rect);
|
||||
} else {
|
||||
mHasDirtyRect = false;
|
||||
}
|
||||
|
||||
if (rect.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aSkipRect) {
|
||||
// If we get passed a skip rect, we can lower the amount of
|
||||
// blurring/spreading we need to do. We convert it to IntRect to avoid
|
||||
// expensive int<->float conversions if we were to use Rect instead.
|
||||
Rect skipRect = *aSkipRect;
|
||||
skipRect.RoundIn();
|
||||
skipRect.Deflate(Size(aBlurRadius + aSpreadRadius));
|
||||
mSkipRect = IntRect(skipRect.x, skipRect.y, skipRect.width, skipRect.height);
|
||||
|
||||
IntRect shadowIntRect(rect.x, rect.y, rect.width, rect.height);
|
||||
mSkipRect.IntersectRect(mSkipRect, shadowIntRect);
|
||||
|
||||
if (mSkipRect.IsEqualInterior(shadowIntRect))
|
||||
return;
|
||||
|
||||
mSkipRect -= shadowIntRect.TopLeft();
|
||||
} else {
|
||||
mSkipRect = IntRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
mRect = IntRect(rect.x, rect.y, rect.width, rect.height);
|
||||
|
||||
CheckedInt<int32_t> stride = RoundUpToMultipleOf4(mRect.width);
|
||||
if (stride.valid()) {
|
||||
mStride = stride.value();
|
||||
|
||||
CheckedInt<int32_t> size = CheckedInt<int32_t>(mStride) * mRect.height *
|
||||
sizeof(unsigned char);
|
||||
if (size.valid()) {
|
||||
mData = static_cast<unsigned char*>(malloc(size.value()));
|
||||
memset(mData, 0, size.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlphaBoxBlur::~AlphaBoxBlur()
|
||||
{
|
||||
free(mData);
|
||||
}
|
||||
|
||||
unsigned char*
|
||||
AlphaBoxBlur::GetData()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
IntSize
|
||||
AlphaBoxBlur::GetSize()
|
||||
{
|
||||
IntSize size(mRect.width, mRect.height);
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t
|
||||
AlphaBoxBlur::GetStride()
|
||||
{
|
||||
return mStride;
|
||||
}
|
||||
|
||||
IntRect
|
||||
AlphaBoxBlur::GetRect()
|
||||
{
|
||||
return mRect;
|
||||
}
|
||||
|
||||
Rect*
|
||||
AlphaBoxBlur::GetDirtyRect()
|
||||
{
|
||||
if (mHasDirtyRect) {
|
||||
return &mDirtyRect;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
AlphaBoxBlur::Blur()
|
||||
{
|
||||
if (!mData) {
|
||||
return;
|
||||
}
|
||||
|
||||
// no need to do all this if not blurring or spreading
|
||||
if (mBlurRadius != IntSize(0,0) || mSpreadRadius != IntSize(0,0)) {
|
||||
int32_t stride = GetStride();
|
||||
|
||||
// No need to use CheckedInt here - we have validated it in the constructor.
|
||||
size_t szB = stride * GetSize().height * sizeof(unsigned char);
|
||||
unsigned char* tmpData = static_cast<unsigned char*>(malloc(szB));
|
||||
if (!tmpData)
|
||||
return; // OOM
|
||||
|
||||
memset(tmpData, 0, szB);
|
||||
|
||||
if (mSpreadRadius.width > 0 || mSpreadRadius.height > 0) {
|
||||
SpreadHorizontal(mData, tmpData, mSpreadRadius.width, GetSize().width, GetSize().height, stride, mSkipRect);
|
||||
SpreadVertical(tmpData, mData, mSpreadRadius.height, GetSize().width, GetSize().height, stride, mSkipRect);
|
||||
}
|
||||
|
||||
if (mBlurRadius.width > 0) {
|
||||
int32_t lobes[3][2];
|
||||
ComputeLobes(mBlurRadius.width, lobes);
|
||||
BoxBlurHorizontal(mData, tmpData, lobes[0][0], lobes[0][1], stride, GetSize().height, mSkipRect);
|
||||
BoxBlurHorizontal(tmpData, mData, lobes[1][0], lobes[1][1], stride, GetSize().height, mSkipRect);
|
||||
BoxBlurHorizontal(mData, tmpData, lobes[2][0], lobes[2][1], stride, GetSize().height, mSkipRect);
|
||||
} else {
|
||||
memcpy(tmpData, mData, stride * GetSize().height);
|
||||
}
|
||||
|
||||
if (mBlurRadius.height > 0) {
|
||||
int32_t lobes[3][2];
|
||||
ComputeLobes(mBlurRadius.height, lobes);
|
||||
BoxBlurVertical(tmpData, mData, lobes[0][0], lobes[0][1], stride, GetSize().height, mSkipRect);
|
||||
BoxBlurVertical(mData, tmpData, lobes[1][0], lobes[1][1], stride, GetSize().height, mSkipRect);
|
||||
BoxBlurVertical(tmpData, mData, lobes[2][0], lobes[2][1], stride, GetSize().height, mSkipRect);
|
||||
} else {
|
||||
memcpy(mData, tmpData, stride * GetSize().height);
|
||||
}
|
||||
|
||||
free(tmpData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the box blur size (which we're calling the blur radius) from
|
||||
* the standard deviation.
|
||||
*
|
||||
* Much of this, the 3 * sqrt(2 * pi) / 4, is the known value for
|
||||
* approximating a Gaussian using box blurs. This yields quite a good
|
||||
* approximation for a Gaussian. Then we multiply this by 1.5 since our
|
||||
* code wants the radius of the entire triple-box-blur kernel instead of
|
||||
* the diameter of an individual box blur. For more details, see:
|
||||
* http://www.w3.org/TR/SVG11/filters.html#feGaussianBlurElement
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=590039#c19
|
||||
*/
|
||||
static const Float GAUSSIAN_SCALE_FACTOR = (3 * sqrt(2 * M_PI) / 4) * 1.5;
|
||||
|
||||
IntSize
|
||||
AlphaBoxBlur::CalculateBlurRadius(const Point& aStd)
|
||||
{
|
||||
IntSize size(static_cast<int32_t>(floor(aStd.x * GAUSSIAN_SCALE_FACTOR + 0.5)),
|
||||
static_cast<int32_t>(floor(aStd.y * GAUSSIAN_SCALE_FACTOR + 0.5)));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla gfx.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MOZILLA_GFX_BLUR_H_
|
||||
#define MOZILLA_GFX_BLUR_H_
|
||||
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
/**
|
||||
* Implementation of a triple box blur approximation of a Gaussian blur.
|
||||
*
|
||||
* A Gaussian blur is good for blurring because, when done independently
|
||||
* in the horizontal and vertical directions, it matches the result that
|
||||
* would be obtained using a different (rotated) set of axes. A triple
|
||||
* box blur is a very close approximation of a Gaussian.
|
||||
*
|
||||
* Creates an 8-bit alpha channel context for callers to draw in,
|
||||
* spreads the contents of that context, and blurs the contents.
|
||||
*
|
||||
* A spread N makes each output pixel the maximum value of all source
|
||||
* pixels within a square of side length 2N+1 centered on the output pixel.
|
||||
*
|
||||
* A temporary surface is created in the Init function. The caller then draws
|
||||
* any desired content onto the context acquired through GetContext, and lastly
|
||||
* calls Paint to apply the blurred content as an alpha mask.
|
||||
*/
|
||||
class AlphaBoxBlur
|
||||
{
|
||||
public:
|
||||
|
||||
/** Constructs a box blur and initializes the backing surface.
|
||||
*
|
||||
* @param aRect The coordinates of the surface to create in device units.
|
||||
*
|
||||
* @param aBlurRadius The blur radius in pixels. This is the radius of the
|
||||
* entire (triple) kernel function. Each individual box blur has radius
|
||||
* approximately 1/3 this value, or diameter approximately 2/3 this value.
|
||||
* This parameter should nearly always be computed using CalculateBlurRadius,
|
||||
* below.
|
||||
*
|
||||
* @param aDirtyRect A pointer to a dirty rect, measured in device units, if
|
||||
* available. This will be used for optimizing the blur operation. It is
|
||||
* safe to pass NULL here.
|
||||
*
|
||||
* @param aSkipRect A pointer to a rect, measured in device units, that
|
||||
* represents an area where blurring is unnecessary and shouldn't be done for
|
||||
* speed reasons. It is safe to pass NULL here.
|
||||
*/
|
||||
AlphaBoxBlur(const Rect& aRect,
|
||||
const IntSize& aSpreadRadius,
|
||||
const IntSize& aBlurRadius,
|
||||
const Rect* aDirtyRect,
|
||||
const Rect* aSkipRect);
|
||||
|
||||
~AlphaBoxBlur();
|
||||
|
||||
/**
|
||||
* Return the pointer to memory allocated by the constructor for the 8-bit
|
||||
* alpha surface you need to be blurred. After you draw to this surface, call
|
||||
* Blur(), below, to have its contents blurred.
|
||||
*/
|
||||
unsigned char* GetData();
|
||||
|
||||
/**
|
||||
* Return the size, in pixels, of the 8-bit alpha surface backed by the
|
||||
* pointer returned by GetData().
|
||||
*/
|
||||
IntSize GetSize();
|
||||
|
||||
/**
|
||||
* Return the stride, in bytes, of the 8-bit alpha surface backed by the
|
||||
* pointer returned by GetData().
|
||||
*/
|
||||
int32_t GetStride();
|
||||
|
||||
/**
|
||||
* Returns the device-space rectangle the 8-bit alpha surface covers.
|
||||
*/
|
||||
IntRect GetRect();
|
||||
|
||||
/**
|
||||
* Return a pointer to a dirty rect, as passed in to the constructor, or NULL
|
||||
* if none was passed in.
|
||||
*/
|
||||
Rect* GetDirtyRect();
|
||||
|
||||
/**
|
||||
* Perform the blur in-place on the surface backed by the pointer returned by
|
||||
* GetData().
|
||||
*/
|
||||
void Blur();
|
||||
|
||||
/**
|
||||
* Calculates a blur radius that, when used with box blur, approximates a
|
||||
* Gaussian blur with the given standard deviation. The result of this
|
||||
* function should be used as the aBlurRadius parameter to AlphaBoxBlur's
|
||||
* constructor, above.
|
||||
*/
|
||||
static IntSize CalculateBlurRadius(const Point& aStandardDeviation);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* A rect indicating the area where blurring is unnecessary, and the blur
|
||||
* algorithm should skip over it.
|
||||
*/
|
||||
IntRect mSkipRect;
|
||||
|
||||
/**
|
||||
* The device-space rectangle the the backing 8-bit alpha surface covers.
|
||||
*/
|
||||
IntRect mRect;
|
||||
|
||||
/**
|
||||
* A copy of the dirty rect passed to the constructor. This will only be valid if
|
||||
* mHasDirtyRect is true.
|
||||
*/
|
||||
Rect mDirtyRect;
|
||||
|
||||
/**
|
||||
* The spread radius, in pixels.
|
||||
*/
|
||||
IntSize mSpreadRadius;
|
||||
|
||||
/**
|
||||
* The blur radius, in pixels.
|
||||
*/
|
||||
IntSize mBlurRadius;
|
||||
|
||||
/**
|
||||
* A pointer to the backing 8-bit alpha surface.
|
||||
*/
|
||||
unsigned char* mData;
|
||||
|
||||
/**
|
||||
* The stride of the data contained in mData.
|
||||
*/
|
||||
int32_t mStride;
|
||||
|
||||
/**
|
||||
* Whether mDirtyRect contains valid data.
|
||||
*/
|
||||
bool mHasDirtyRect;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_GFX_BLUR_H_ */
|
|
@ -56,6 +56,7 @@ EXPORTS_mozilla/gfx = \
|
|||
BaseMargin.h \
|
||||
BaseRect.h \
|
||||
BaseSize.h \
|
||||
Blur.h \
|
||||
PathHelpers.h \
|
||||
Point.h \
|
||||
Matrix.h \
|
||||
|
@ -68,6 +69,7 @@ CPPSRCS = \
|
|||
Matrix.cpp \
|
||||
DrawTargetCairo.cpp \
|
||||
SourceSurfaceCairo.cpp \
|
||||
Blur.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ ifdef MOZ_TREE_CAIRO
|
|||
DIRS = cairo
|
||||
endif
|
||||
|
||||
DIRS += 2d ycbcr angle src qcms layers harfbuzz/src ots/src thebes ipc
|
||||
DIRS += 2d ycbcr angle src qcms gl layers harfbuzz/src ots/src thebes ipc
|
||||
|
||||
ifeq (,$(filter-out cocoa android windows,$(MOZ_WIDGET_TOOLKIT)))
|
||||
DIRS += skia
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
This is the ANGLE project, from http://code.google.com/p/angleproject/
|
||||
|
||||
Current revision: r809
|
||||
Current revision: r885
|
||||
|
||||
== Applied local patches ==
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# HG changeset patch
|
||||
# Parent b5604c321da4e3b5d6b0a940d18022a827061579
|
||||
# Parent d9b887da80f5bc18854fb3e5e43637c18d2a25ae
|
||||
diff --git a/gfx/angle/src/libGLESv2/Texture.cpp b/gfx/angle/src/libGLESv2/Texture.cpp
|
||||
--- a/gfx/angle/src/libGLESv2/Texture.cpp
|
||||
+++ b/gfx/angle/src/libGLESv2/Texture.cpp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# HG changeset patch
|
||||
# Parent 0239f15c7212413b5cffe66aee9ae5a4feb28f16
|
||||
# Parent eae39c479485f310e937d8550afc6596aec20159
|
||||
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
|
||||
--- a/gfx/angle/Makefile.in
|
||||
+++ b/gfx/angle/Makefile.in
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# HG changeset patch
|
||||
# Parent fecc64a6df53a9056b21958affad38c80ca38496
|
||||
# Parent 85ffde53712cab3c217bbbf0c1ec9b7ec2ae8ea6
|
||||
|
||||
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
|
||||
--- a/gfx/angle/Makefile.in
|
||||
|
@ -7,7 +7,7 @@ diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
|
|||
@@ -127,16 +127,18 @@ CSRCS = \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -DANGLE_USE_NSPR -DANGLE_BUILD
|
||||
DEFINES += -DANGLE_USE_NSPR -DANGLE_BUILD -DCOMPILER_IMPLEMENTATION
|
||||
|
||||
#these defines are from ANGLE's build_angle.gyp
|
||||
DEFINES += -DANGLE_DISABLE_TRACE
|
||||
|
@ -27,13 +27,13 @@ diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla
|
|||
--- a/gfx/angle/README.mozilla
|
||||
+++ b/gfx/angle/README.mozilla
|
||||
@@ -3,16 +3,17 @@ This is the ANGLE project, from http://c
|
||||
Current revision: r774
|
||||
Current revision: r885
|
||||
|
||||
== Applied local patches ==
|
||||
|
||||
In this order:
|
||||
angle-renaming.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
|
||||
angle-instrinsic-msvc2005.patch - work around a MSVC 2005 compile error
|
||||
angle-renaming-debug.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
|
||||
angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
|
||||
angle-limit-identifiers-to-250-chars.patch - see bug 675625
|
||||
+ angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands.
|
||||
|
||||
|
@ -44,20 +44,6 @@ diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla
|
|||
1. Unapply patches
|
||||
2. Apply diff with new ANGLE version
|
||||
3. Reapply patches.
|
||||
diff --git a/gfx/angle/angle-limit-identifiers-to-250-chars.patch b/gfx/angle/angle-limit-identifiers-to-250-chars.patch
|
||||
--- a/gfx/angle/angle-limit-identifiers-to-250-chars.patch
|
||||
+++ b/gfx/angle/angle-limit-identifiers-to-250-chars.patch
|
||||
@@ -1,8 +1,10 @@
|
||||
+# HG changeset patch
|
||||
+# Parent f9415c10c3ebd27856500cca7a0ee0f28a16f53c
|
||||
diff --git a/gfx/angle/src/compiler/preprocessor/scanner.h b/gfx/angle/src/compiler/preprocessor/scanner.h
|
||||
--- a/gfx/angle/src/compiler/preprocessor/scanner.h
|
||||
+++ b/gfx/angle/src/compiler/preprocessor/scanner.h
|
||||
@@ -44,17 +44,19 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILI
|
||||
//
|
||||
// scanner.h
|
||||
//
|
||||
|
||||
diff --git a/gfx/angle/src/compiler/preprocessor/atom.c b/gfx/angle/src/compiler/preprocessor/atom.c
|
||||
--- a/gfx/angle/src/compiler/preprocessor/atom.c
|
||||
+++ b/gfx/angle/src/compiler/preprocessor/atom.c
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
Name
|
||||
|
||||
ANGLE_texture_usage
|
||||
|
||||
Name Strings
|
||||
|
||||
GL_ANGLE_texture_usage
|
||||
|
||||
Contributors
|
||||
|
||||
Nicolas Capens, TransGaming
|
||||
Daniel Koch, TransGaming
|
||||
|
||||
Contact
|
||||
|
||||
Daniel Koch, TransGaming (daniel 'at' transgaming.com)
|
||||
|
||||
Status
|
||||
|
||||
Complete
|
||||
|
||||
Version
|
||||
|
||||
Last Modified Date: November 10, 2011
|
||||
Version: 2
|
||||
|
||||
Number
|
||||
|
||||
TBD
|
||||
|
||||
Dependencies
|
||||
|
||||
This extension is written against the OpenGL ES 2.0 Specification.
|
||||
|
||||
Overview
|
||||
|
||||
In some implementations it is advantageous to know the expected
|
||||
usage of a texture before the backing storage for it is allocated.
|
||||
This can help to inform the implementation's choice of format
|
||||
and type of memory used for the allocation. If the usage is not
|
||||
known in advance, the implementation essentially has to make a
|
||||
guess as to how it will be used. If it is later proven wrong,
|
||||
it may need to perform costly re-allocations and/or reformatting
|
||||
of the texture data, resulting in reduced performance.
|
||||
|
||||
This extension adds a texture usage flag that is specified via
|
||||
the TEXTURE_USAGE_ANGLE TexParameter. This can be used to
|
||||
indicate that the application knows that this texture will be
|
||||
used for rendering.
|
||||
|
||||
IP Status
|
||||
|
||||
No known IP claims.
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
None
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted as a value for <pname> for the TexParameter{if} and
|
||||
TexParameter{if}v commands and for the <value> parameter of
|
||||
GetTexParameter{if}v:
|
||||
|
||||
TEXTURE_USAGE_ANGLE 0x93A2
|
||||
|
||||
Accepted as a value to <param> for the TexParameter{if} and
|
||||
to <params> for the TexParameter{if}v commands with a <pname> of
|
||||
TEXTURE_USAGE_ANGLE; returned as possible values for <data> when
|
||||
GetTexParameter{if}v is queried with a <value> of TEXTURE_USAGE_ANGLE:
|
||||
|
||||
NONE 0x0000
|
||||
FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
|
||||
|
||||
Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
|
||||
|
||||
None
|
||||
|
||||
Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
|
||||
|
||||
Add a new row to Table 3.10 (Texture parameters and their values):
|
||||
|
||||
Name | Type | Legal Values
|
||||
------------------------------------------------------------
|
||||
TEXTURE_USAGE_ANGLE | enum | NONE, FRAMEBUFFER_ATTACHMENT_ANGLE
|
||||
|
||||
Add a new section 3.7.x (Texture Usage) before section 3.7.12 and
|
||||
renumber the subsequent sections:
|
||||
|
||||
"3.7.x Texture Usage
|
||||
|
||||
Texture usage can be specified via the TEXTURE_USAGE_ANGLE value
|
||||
for the <pname> argument to TexParameter{if}[v]. In order to take effect,
|
||||
the texture usage must be specified before the texture contents are
|
||||
defined either via TexImage2D or TexStorage2DEXT.
|
||||
|
||||
The usage values can impact the layout and type of memory used for the
|
||||
texture data. Specifying incorrect usage values may result in reduced
|
||||
functionality and/or significantly degraded performance.
|
||||
|
||||
Possible values for <params> when <pname> is TEXTURE_USAGE_ANGLE are:
|
||||
|
||||
NONE - the default. No particular usage has been specified and it is
|
||||
up to the implementation to determine the usage of the texture.
|
||||
Leaving the usage unspecified means that the implementation may
|
||||
have to reallocate the texture data as the texture is used in
|
||||
various ways.
|
||||
|
||||
FRAMEBUFFER_ATTACHMENT_ANGLE - this texture will be attached to a
|
||||
framebuffer object and used as a desination for rendering or blits."
|
||||
|
||||
Modify section 3.7.12 (Texture State) and place the last 3 sentences
|
||||
with the following:
|
||||
|
||||
"Next, there are the three sets of texture properties; each consists of
|
||||
the selected minification and magnification filters, the wrap modes for
|
||||
<s> and <t>, and the usage flags. In the initial state, the value assigned
|
||||
to TEXTURE_MIN_FILTER is NEAREST_MIPMAP_LINEAR, and the value for
|
||||
TEXTURE_MAG_FILTER is LINEAR. <s> and <t> wrap modes are both set to
|
||||
REPEAT. The initial value for TEXTURE_USAGE_ANGLE is NONE."
|
||||
|
||||
|
||||
Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
|
||||
Operations and the Framebuffer)
|
||||
|
||||
None
|
||||
|
||||
Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special
|
||||
Functions):
|
||||
|
||||
None
|
||||
|
||||
Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and
|
||||
State Requests)
|
||||
|
||||
None
|
||||
|
||||
Dependencies on EXT_texture_storage
|
||||
|
||||
If EXT_texture_storage is not supported, omit any references to
|
||||
TexStorage2DEXT.
|
||||
|
||||
Errors
|
||||
|
||||
If TexParameter{if} or TexParamter{if}v is called with a <pname>
|
||||
of TEXTURE_USAGE_ANGLE and the value of <param> or <params> is not
|
||||
NONE or FRAMEBUFFER_ATTACHMENT_ANGLE the error INVALID_VALUE is
|
||||
generated.
|
||||
|
||||
Usage Example
|
||||
|
||||
/* create and bind texture */
|
||||
glGenTextures(1, &texture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
/* specify texture parameters */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_*, ...); /* as before */
|
||||
|
||||
/* specify that we'll be rendering to the texture */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
|
||||
|
||||
glTexStorage2DEXT(GL_TEXTURE_2D, levels, ...); // Allocation
|
||||
for(int level = 0; level < levels; ++level)
|
||||
glTexSubImage2D(GL_TEXTURE_2D, level, ...); // Initialisation
|
||||
|
||||
Issues
|
||||
|
||||
1. Should there be a dynamic usage value?
|
||||
|
||||
DISCUSSION: We could accept a dynamic flag to indicate that a texture will
|
||||
be updated frequently. We could map this to D3D9 dynamic textures. This would
|
||||
allow us to avoid creating temporary surfaces when updating the texture.
|
||||
However renderable textures cannot be dynamic in D3D9, which eliminates the
|
||||
primary use case for this. Furthermore, the memory usage of dynamic textures
|
||||
typically increases threefold when you lock it.
|
||||
|
||||
2. Should the texture usage be an enum or a bitfield?
|
||||
|
||||
UNRESOLVED. Using a bitfield would allow combination of values to be specified.
|
||||
On the other hand, if combinations are really required, additional <pnames>
|
||||
could be added as necessary. Querying a bitfield via the GetTexParameter command
|
||||
feels a bit odd.
|
||||
|
||||
3. What should happen if TEXTURE_USAGE_ANGLE is set/changed after the texture
|
||||
contents have been specified?
|
||||
|
||||
RESOLVED: It will have no effect. However, if the texture is redefined (for
|
||||
example by TexImage2D) the new allocation will use the updated usage.
|
||||
GetTexParameter is used to query the value of the TEXTURE_USAGE_ANGLE
|
||||
state that was last set by TexParameter for the currently bound texture, or
|
||||
the default value if it has never been set. There is no way to determine the
|
||||
usage that was in effect at the time the texture was defined.
|
||||
|
||||
Revision History
|
||||
|
||||
Rev. Date Author Changes
|
||||
---- ----------- --------- ----------------------------------------
|
||||
1 10 Nov 2011 dgkoch Initial revision
|
||||
2 10 Nov 2011 dgkoch Add overview
|
||||
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
Name
|
||||
|
||||
EXT_create_context_robustness
|
||||
|
||||
Name Strings
|
||||
|
||||
EGL_EXT_create_context_robustness
|
||||
|
||||
Contributors
|
||||
|
||||
Daniel Koch, TransGaming
|
||||
Contributors to EGL_KHR_create_context
|
||||
|
||||
Contact
|
||||
|
||||
Greg Roth (groth 'at' nvidia.com)
|
||||
|
||||
Status
|
||||
|
||||
Complete.
|
||||
|
||||
Version
|
||||
|
||||
Version 3, 2011/10/31
|
||||
|
||||
Number
|
||||
|
||||
TBD
|
||||
|
||||
Dependencies
|
||||
|
||||
Requires EGL 1.4
|
||||
|
||||
Written against the EGL 1.4 specification.
|
||||
|
||||
An OpenGL implementation supporting GL_ARB_robustness, an OpenGL ES
|
||||
implementation supporting GL_EXT_robustness, or an implementation
|
||||
supporting equivalent functionality is required.
|
||||
|
||||
Overview
|
||||
|
||||
This extension allows creating an OpenGL or OpenGL ES context
|
||||
supporting robust buffer access behavior and a specified graphics
|
||||
reset notification behavior.
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
None
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted as an attribute name in the <*attrib_list> argument to
|
||||
eglCreateContext:
|
||||
|
||||
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
|
||||
EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
|
||||
|
||||
Accepted as an attribute value for EGL_CONTEXT_RESET_NOTIFICATION_-
|
||||
STRATEGY_EXT in the <*attrib_list> argument to eglCreateContext:
|
||||
|
||||
EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
|
||||
EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
|
||||
|
||||
Additions to the EGL 1.4 Specification
|
||||
|
||||
Replace section 3.7.1 "Creating Rendering Contexts" from the
|
||||
fifth paragraph through the seventh paragraph:
|
||||
|
||||
<attrib_list> specifies a list of attributes for the context. The
|
||||
list has the same structure as described for eglChooseConfig. If an
|
||||
attribute is not specified in <attrib_list>, then the default value
|
||||
specified below is used instead. <attrib_list> may be NULL or empty
|
||||
(first attribute is EGL_NONE), in which case attributes assume their
|
||||
default values as described below. Most attributes are only meaningful
|
||||
for specific client APIs, and will generate an EGL_BAD_ATTRIBUTE
|
||||
error when specified to create for another client API context.
|
||||
|
||||
Context Versions
|
||||
----------------
|
||||
|
||||
EGL_CONTEXT_CLIENT_VERSION determines which version of an OpenGL ES
|
||||
context to create. This attribute may only be specified when creating
|
||||
an OpenGL ES context (e.g. when the current rendering API is
|
||||
EGL_OPENGL_ES_API). An attribute value of 1 specifies creation of an
|
||||
OpenGL ES 1.x context. An attribute value of 2 specifies creation of an
|
||||
Open GL ES 2.x context. The default value for EGL_CONTEXT_CLIENT_VERSION
|
||||
is 1.
|
||||
|
||||
Context Robust Access
|
||||
-------------
|
||||
|
||||
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT indicates whether <robust buffer
|
||||
access> should be enabled for the OpenGL ES context. Robust buffer
|
||||
access is defined in the GL_EXT_robustness extension specification,
|
||||
and the resulting context must support GL_EXT_robustness and robust
|
||||
buffer access as described therein. The default value of
|
||||
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT is EGL_FALSE.
|
||||
|
||||
Context Reset Notification
|
||||
--------------------------
|
||||
|
||||
The attribute name EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_-
|
||||
EXT specifies the <reset notification behavior> of the rendering
|
||||
context. This attribute is only meaningful for OpenGL ES contexts,
|
||||
and specifying it for other types of contexts will generate an
|
||||
EGL_BAD_ATTRIBUTE error.
|
||||
|
||||
Reset notification behavior is defined in the GL_EXT_robustness
|
||||
extension for OpenGL ES, and the resulting context must support
|
||||
GL_EXT_robustness and the specified reset strategy. The attribute
|
||||
value may be either EGL_NO_RESET_NOTIFICATION_EXT or EGL_LOSE_-
|
||||
CONTEXT_ON_RESET_EXT, which respectively result in disabling
|
||||
delivery of reset notifications or the loss of all context state
|
||||
upon reset notification as described by the GL_EXT_robustness. The
|
||||
default value for EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT
|
||||
is EGL_NO_RESET_NOTIFICATION_EXT.
|
||||
|
||||
Add to the eglCreateContext context creation errors:
|
||||
|
||||
* If <config> does not support a client API context compatible
|
||||
with the requested context flags and context reset notification
|
||||
behavior (for client API types where these attributes are
|
||||
supported), then an EGL_BAD_CONFIG error is generated.
|
||||
|
||||
* If the reset notification behavior of <share_context> and the
|
||||
newly created context are different then an EGL_BAD_MATCH error is
|
||||
generated.
|
||||
|
||||
|
||||
Errors
|
||||
|
||||
EGL_BAD_CONFIG is generated if EGL_CONTEXT_OPENGL_ROBUST_ACCESS_-
|
||||
EXT is set to EGL_TRUE and no GL context supporting the GL_EXT_-
|
||||
robustness extension and robust access as described therein can be
|
||||
created.
|
||||
|
||||
EGL_BAD_CONFIG is generated if no GL context supporting the
|
||||
GL_EXT_robustness extension and the specified reset notification
|
||||
behavior (the value of attribute EGL_CONTEXT_RESET_NOTIFICATION_-
|
||||
STRATEGY_EXT) can be created.
|
||||
|
||||
BAD_MATCH is generated if the reset notification behavior of
|
||||
<share_context> does not match the reset notification behavior of
|
||||
the context being created.
|
||||
|
||||
New State
|
||||
|
||||
None
|
||||
|
||||
Conformance Tests
|
||||
|
||||
TBD
|
||||
|
||||
Sample Code
|
||||
|
||||
TBD
|
||||
|
||||
Issues
|
||||
|
||||
None
|
||||
|
||||
Revision History
|
||||
|
||||
Rev. Date Author Changes
|
||||
---- ------------ --------- ----------------------------------------
|
||||
3 31 Oct 2011 groth Reverted to attribute for robust access. Now it's a
|
||||
companion to rather than subset of KHR_create_context
|
||||
2 11 Oct 2011 groth Merged ANGLE and NV extensions.
|
||||
1 15 July 2011 groth Initial version
|
|
@ -0,0 +1,365 @@
|
|||
Name
|
||||
|
||||
EXT_robustness
|
||||
|
||||
Name Strings
|
||||
|
||||
GL_EXT_robustness
|
||||
|
||||
Contributors
|
||||
|
||||
Daniel Koch, TransGaming
|
||||
Nicolas Capens, TransGaming
|
||||
Contributors to ARB_robustness
|
||||
|
||||
Contact
|
||||
|
||||
Greg Roth, NVIDIA (groth 'at' nvidia.com)
|
||||
|
||||
Status
|
||||
|
||||
Complete.
|
||||
|
||||
Version
|
||||
|
||||
Version 3, 2011/10/31
|
||||
|
||||
Number
|
||||
|
||||
TBD
|
||||
|
||||
Dependencies
|
||||
|
||||
This extension is written against the OpenGL ES 2.0 Specification
|
||||
but can apply to OpenGL ES 1.1 and up.
|
||||
|
||||
EGL_EXT_create_context_robustness is used to determine if a context
|
||||
implementing this extension supports robust buffer access, and if it
|
||||
supports reset notification.
|
||||
|
||||
Overview
|
||||
|
||||
Several recent trends in how OpenGL integrates into modern computer
|
||||
systems have created new requirements for robustness and security
|
||||
for OpenGL rendering contexts.
|
||||
|
||||
Additionally GPU architectures now support hardware fault detection;
|
||||
for example, video memory supporting ECC (error correcting codes)
|
||||
and error detection. OpenGL contexts should be capable of recovering
|
||||
from hardware faults such as uncorrectable memory errors. Along with
|
||||
recovery from such hardware faults, the recovery mechanism can
|
||||
also allow recovery from video memory access exceptions and system
|
||||
software failures. System software failures can be due to device
|
||||
changes or driver failures.
|
||||
|
||||
OpenGL queries that that return (write) some number of bytes to a
|
||||
buffer indicated by a pointer parameter introduce risk of buffer
|
||||
overflows that might be exploitable by malware. To address this,
|
||||
queries with return value sizes that are not expressed directly by
|
||||
the parameters to the query itself are given additional API
|
||||
functions with an additional parameter that specifies the number of
|
||||
bytes in the buffer and never writing bytes beyond that limit. This
|
||||
is particularly useful for multi-threaded usage of OpenGL contexts
|
||||
in a "share group" where one context can change objects in ways that
|
||||
can cause buffer overflows for another context's OpenGL queries.
|
||||
|
||||
The original ARB_vertex_buffer_object extension includes an issue
|
||||
that explicitly states program termination is allowed when
|
||||
out-of-bounds vertex buffer object fetches occur. Modern graphics
|
||||
hardware is capable well-defined behavior in the case of out-of-
|
||||
bounds vertex buffer object fetches. Older hardware may require
|
||||
extra checks to enforce well-defined (and termination free)
|
||||
behavior, but this expense is warranted when processing potentially
|
||||
untrusted content.
|
||||
|
||||
The intent of this extension is to address some specific robustness
|
||||
goals:
|
||||
|
||||
* For all existing OpenGL queries, provide additional "safe" APIs
|
||||
that limit data written to user pointers to a buffer size in
|
||||
bytes that is an explicit additional parameter of the query.
|
||||
|
||||
* Provide a mechanism for an OpenGL application to learn about
|
||||
graphics resets that affect the context. When a graphics reset
|
||||
occurs, the OpenGL context becomes unusable and the application
|
||||
must create a new context to continue operation. Detecting a
|
||||
graphics reset happens through an inexpensive query.
|
||||
|
||||
* Provide an enable to guarantee that out-of-bounds buffer object
|
||||
accesses by the GPU will have deterministic behavior and preclude
|
||||
application instability or termination due to an incorrect buffer
|
||||
access. Such accesses include vertex buffer fetches of
|
||||
attributes and indices, and indexed reads of uniforms or
|
||||
parameters from buffers.
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
enum GetGraphicsResetStatusEXT();
|
||||
|
||||
void ReadnPixelsEXT(int x, int y, sizei width, sizei height,
|
||||
enum format, enum type, sizei bufSize,
|
||||
void *data);
|
||||
|
||||
void GetnUniformfvEXT(uint program, int location, sizei bufSize,
|
||||
float *params);
|
||||
void GetnUniformivEXT(uint program, int location, sizei bufSize,
|
||||
int *params);
|
||||
|
||||
New Tokens
|
||||
|
||||
Returned by GetGraphicsResetStatusEXT:
|
||||
|
||||
NO_ERROR 0x0000
|
||||
GUILTY_CONTEXT_RESET_EXT 0x8253
|
||||
INNOCENT_CONTEXT_RESET_EXT 0x8254
|
||||
UNKNOWN_CONTEXT_RESET_EXT 0x8255
|
||||
|
||||
Accepted by the <value> parameter of GetBooleanv, GetIntegerv,
|
||||
and GetFloatv:
|
||||
|
||||
CONTEXT_ROBUST_ACCESS_EXT 0x90F3
|
||||
RESET_NOTIFICATION_STRATEGY_EXT 0x8256
|
||||
|
||||
Returned by GetIntegerv and related simple queries when <value> is
|
||||
RESET_NOTIFICATION_STRATEGY_EXT :
|
||||
|
||||
LOSE_CONTEXT_ON_RESET_EXT 0x8252
|
||||
NO_RESET_NOTIFICATION_EXT 0x8261
|
||||
|
||||
Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
|
||||
|
||||
Add a new subsection after 2.5 "GL Errors" and renumber subsequent
|
||||
sections accordingly.
|
||||
|
||||
2.6 "Graphics Reset Recovery"
|
||||
|
||||
Certain events can result in a reset of the GL context. Such a reset
|
||||
causes all context state to be lost. Recovery from such events
|
||||
requires recreation of all objects in the affected context. The
|
||||
current status of the graphics reset state is returned by
|
||||
|
||||
enum GetGraphicsResetStatusEXT();
|
||||
|
||||
The symbolic constant returned indicates if the GL context has been
|
||||
in a reset state at any point since the last call to
|
||||
GetGraphicsResetStatusEXT. NO_ERROR indicates that the GL context
|
||||
has not been in a reset state since the last call.
|
||||
GUILTY_CONTEXT_RESET_EXT indicates that a reset has been detected
|
||||
that is attributable to the current GL context.
|
||||
INNOCENT_CONTEXT_RESET_EXT indicates a reset has been detected that
|
||||
is not attributable to the current GL context.
|
||||
UNKNOWN_CONTEXT_RESET_EXT indicates a detected graphics reset whose
|
||||
cause is unknown.
|
||||
|
||||
If a reset status other than NO_ERROR is returned and subsequent
|
||||
calls return NO_ERROR, the context reset was encountered and
|
||||
completed. If a reset status is repeatedly returned, the context may
|
||||
be in the process of resetting.
|
||||
|
||||
Reset notification behavior is determined at context creation time,
|
||||
and may be queried by calling GetIntegerv with the symbolic constant
|
||||
RESET_NOTIFICATION_STRATEGY_EXT.
|
||||
|
||||
If the reset notification behavior is NO_RESET_NOTIFICATION_EXT,
|
||||
then the implementation will never deliver notification of reset
|
||||
events, and GetGraphicsResetStatusEXT will always return
|
||||
NO_ERROR[fn1].
|
||||
[fn1: In this case it is recommended that implementations should
|
||||
not allow loss of context state no matter what events occur.
|
||||
However, this is only a recommendation, and cannot be relied
|
||||
upon by applications.]
|
||||
|
||||
If the behavior is LOSE_CONTEXT_ON_RESET_EXT, a graphics reset will
|
||||
result in the loss of all context state, requiring the recreation of
|
||||
all associated objects. In this case GetGraphicsResetStatusEXT may
|
||||
return any of the values described above.
|
||||
|
||||
If a graphics reset notification occurs in a context, a notification
|
||||
must also occur in all other contexts which share objects with that
|
||||
context[fn2].
|
||||
[fn2: The values returned by GetGraphicsResetStatusEXT in the
|
||||
different contexts may differ.]
|
||||
|
||||
Add to Section 2.8 "Vertex Arrays" before subsection "Transferring
|
||||
Array Elements"
|
||||
|
||||
Robust buffer access is enabled by creating a context with robust
|
||||
access enabled through the window system binding APIs. When enabled,
|
||||
indices within the vertex array that lie outside the arrays defined
|
||||
for enabled attributes result in undefined values for the
|
||||
corresponding attributes, but cannot result in application failure.
|
||||
Robust buffer access behavior may be queried by calling GetIntegerv
|
||||
with the symbolic constant CONTEXT_ROBUST_ACCESS_EXT.
|
||||
|
||||
Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
|
||||
Operations and the Frame Buffer)
|
||||
|
||||
Modify section 4.3.1 "Reading Pixels"
|
||||
|
||||
Pixels are read using
|
||||
|
||||
void ReadPixels(int x, int y, sizei width, sizei height,
|
||||
enum format, enum type, void *data);
|
||||
void ReadnPixelsEXT(int x, int y, sizei width, sizei height,
|
||||
enum format, enum type, sizei bufSize,
|
||||
void *data);
|
||||
|
||||
Add to the description of ReadPixels:
|
||||
|
||||
ReadnPixelsEXT behaves identically to ReadPixels except that it does
|
||||
not write more than <bufSize> bytes into <data>. If the buffer size
|
||||
required to fill all the requested data is greater than <bufSize> an
|
||||
INVALID_OPERATION error is generated and <data> is not altered.
|
||||
|
||||
Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special
|
||||
Functions):
|
||||
|
||||
None
|
||||
|
||||
Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and
|
||||
State Requests)
|
||||
|
||||
Modify Section 6.1.8 "Shader and Program Queries"
|
||||
|
||||
The commands
|
||||
|
||||
void GetUniformfv(uint program, int location, float *params);
|
||||
void GetnUniformfvEXT(uint program, int location, sizei bufSize,
|
||||
float *params);
|
||||
void GetUniformiv(uint program, int location, int *params);
|
||||
void GetnUniformivEXT(uint program, int location, sizei bufSize,
|
||||
int *params);
|
||||
|
||||
return the value or values of the uniform at location <location>
|
||||
for program object <program> in the array <params>. Calling
|
||||
GetnUniformfvEXT or GetnUniformivEXT ensures that no more than
|
||||
<bufSize> bytes are written into <params>. If the buffer size
|
||||
required to fill all the requested data is greater than <bufSize> an
|
||||
INVALID_OPERATION error is generated and <params> is not altered.
|
||||
...
|
||||
|
||||
Additions to The OpenGL ES Shading Language Specification, Version 1.
|
||||
|
||||
Append to the third paragraph of section 4.1.9 "Arrays"
|
||||
|
||||
If robust buffer access is enabled via the OpenGL ES API, such
|
||||
indexing must not result in abnormal program termination. The
|
||||
results are still undefined, but implementations are encouraged to
|
||||
produce zero values for such accesses.
|
||||
|
||||
Interactions with EGL_EXT_create_context_robustness
|
||||
|
||||
If the EGL window-system binding API is used to create a context,
|
||||
the EGL_EXT_create_context_robustness extension is supported, and
|
||||
the attribute EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT is set to
|
||||
EGL_TRUE when eglCreateContext is called, the resulting context will
|
||||
perform robust buffer access as described above in section 2.8, and
|
||||
the CONTEXT_ROBUST_ACCESS_EXT query will return GL_TRUE as described
|
||||
above in section 6.1.5.
|
||||
|
||||
If the EGL window-system binding API is used to create a context and
|
||||
the EGL_EXT_create_context_robustness extension is supported, then
|
||||
the value of attribute EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT
|
||||
determines the reset notification behavior and the value of
|
||||
RESET_NOTIFICATION_STRATEGY_EXT, as described in section 2.6.
|
||||
|
||||
Errors
|
||||
|
||||
ReadnPixelsEXT, GetnUniformfvEXT, and GetnUniformivEXT share all the
|
||||
errors of their unsized buffer query counterparts with the addition
|
||||
that INVALID_OPERATION is generated if the buffer size required to
|
||||
fill all the requested data is greater than <bufSize>.
|
||||
|
||||
New Implementation Dependent State
|
||||
|
||||
Get Value Type Get Command Minimum Value Description Sec. Attribute
|
||||
--------- ---- ----------- ------------- --------------------------- ----- ---------
|
||||
CONTEXT_ROBUST_ACCESS_EXT B GetIntegerv - Robust access enabled 6.1.5 -
|
||||
RESET_NOTIFICATION_STRATEGY_EXT Z_2 GetIntegerv See sec. 2.6 Reset notification behavior 2.6 -
|
||||
|
||||
Issues
|
||||
|
||||
|
||||
1. What should this extension be called?
|
||||
|
||||
RESOLVED: EXT_robustness
|
||||
|
||||
Since this is intended to be a version of ARB_robustness for
|
||||
OpenGL ES, it should be named accordingly.
|
||||
|
||||
2. How does this extension differ from Desktop GL's ARB_robustness?
|
||||
|
||||
RESOLVED: Because EGL_EXT_create_context_robustness uses a
|
||||
separate attribute to enable robust buffer access, a
|
||||
corresponding query is added here.
|
||||
|
||||
3. Should we provide a context creation mechanism to enable this extension?
|
||||
|
||||
RESOLVED. Yes.
|
||||
|
||||
Currently, EGL_EXT_create_context_robustness provides this
|
||||
mechanism via two unique attributes. These attributes differ
|
||||
from those specified by KHR_create_context to allow for
|
||||
differences in what functionality those attributes define.
|
||||
|
||||
4. What can cause a graphics reset?
|
||||
|
||||
Either user or implementor errors may result in a graphics reset.
|
||||
If the application attempts to perform a rendering that takes too long
|
||||
whether due to an infinite loop in a shader or even just a rendering
|
||||
operation that takes too long on the given hardware. Implementation
|
||||
errors may produce badly formed hardware commands. Memory access errors
|
||||
may result from user or implementor mistakes. On some systems, power
|
||||
management events such as system sleep, screen saver activation, or
|
||||
pre-emption may also context resets to occur. Any of these events may
|
||||
result in a graphics reset event that will be detectable by the
|
||||
mechanism described in this extension.
|
||||
|
||||
5. How should the application react to a reset context event?
|
||||
|
||||
RESOLVED: For this extension, the application is expected to query
|
||||
the reset status until NO_ERROR is returned. If a reset is encountered,
|
||||
at least one *RESET* status will be returned. Once NO_ERROR is again
|
||||
encountered, the application can safely destroy the old context and
|
||||
create a new one.
|
||||
|
||||
After a reset event, apps should not use a context for any purpose
|
||||
other than determining its reset status, and then destroying it. If a
|
||||
context receives a reset event, all other contexts in its share group
|
||||
will also receive reset events, and should be destroyed and
|
||||
recreated.
|
||||
|
||||
Apps should be cautious in interpreting the GUILTY and INNOCENT reset
|
||||
statuses. These are guidelines to the immediate cause of a reset, but
|
||||
not guarantees of the ultimate cause.
|
||||
|
||||
6. If a graphics reset occurs in a shared context, what happens in
|
||||
shared contexts?
|
||||
|
||||
RESOLVED: A reset in one context will result in a reset in all other
|
||||
contexts in its share group.
|
||||
|
||||
7. How can an application query for robust buffer access support,
|
||||
since this is now determined at context creation time?
|
||||
|
||||
RESOLVED. The application can query the value of ROBUST_ACCESS_EXT
|
||||
using GetIntegerv. If true, this functionality is enabled.
|
||||
|
||||
8. How is the reset notification behavior controlled?
|
||||
|
||||
RESOLVED: Reset notification behavior is determined at context
|
||||
creation time using EGL/GLX/WGL/etc. mechanisms. In order that shared
|
||||
objects be handled predictably, a context cannot share with
|
||||
another context unless both have the same reset notification
|
||||
behavior.
|
||||
|
||||
|
||||
Revision History
|
||||
|
||||
Rev. Date Author Changes
|
||||
---- ------------ --------- ----------------------------------------
|
||||
3 31 Oct 2011 groth Reverted to attribute for robust access. Now it's a
|
||||
companion to rather than subset of KHR_create_context
|
||||
2 11 Oct 2011 groth Merged ANGLE and NV extensions.
|
||||
Convert to using flag to indicate robust access.
|
||||
1 15 July 2011 groth Initial version
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -318,6 +318,14 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay
|
|||
#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
|
||||
#endif
|
||||
|
||||
#ifndef EGL_EXT_create_context_robustness
|
||||
#define EGL_EXT_create_context_robustness 1
|
||||
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
|
||||
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
|
||||
#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
|
||||
#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64 /* EGLTimeKHR requires 64-bit uint support */
|
||||
#ifndef EGL_NV_system_time
|
||||
#define EGL_NV_system_time 1
|
||||
|
|
|
@ -222,6 +222,12 @@ typedef void* GLeglImageOES;
|
|||
#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
|
||||
#endif
|
||||
|
||||
/* GL_ANGLE_texture_usage */
|
||||
#ifndef GL_ANGLE_texture_usage
|
||||
#define GL_TEXTURE_USAGE_ANGLE 0x93A2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* APPLE extension tokens
|
||||
*------------------------------------------------------------------------*/
|
||||
|
@ -325,6 +331,42 @@ typedef void* GLeglImageOES;
|
|||
#define GL_UNPACK_SKIP_PIXELS 0x0CF4
|
||||
#endif
|
||||
|
||||
/* GL_EXT_robustness */
|
||||
#ifndef GL_EXT_robustness
|
||||
#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
|
||||
#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
|
||||
#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
|
||||
#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
|
||||
#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
|
||||
#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
|
||||
#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
|
||||
#endif
|
||||
|
||||
/* GL_EXT_texture_storage */
|
||||
#ifndef GL_EXT_texture_storage
|
||||
#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
|
||||
#define GL_ALPHA8_EXT 0x803C
|
||||
#define GL_LUMINANCE8_EXT 0x8040
|
||||
#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
|
||||
/* OES_texture_float dependent internal formats */
|
||||
#define GL_RGBA32F_EXT 0x8814 /* reuse tokens from ARB_texture_float */
|
||||
#define GL_RGB32F_EXT 0x8815
|
||||
#define GL_ALPHA32F_EXT 0x8816
|
||||
#define GL_LUMINANCE32F_EXT 0x8818
|
||||
#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
|
||||
/* OES_texture_half_float dependent internal formats */
|
||||
#define GL_RGBA16F_EXT 0x881A /* reuse tokens from ARB_texture_float */
|
||||
#define GL_RGB16F_EXT 0x881B
|
||||
#define GL_ALPHA16F_EXT 0x881C
|
||||
#define GL_LUMINANCE16F_EXT 0x881E
|
||||
#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
|
||||
/* EXT_texture_type_2_10_10_10_REV dependent internal formats */
|
||||
#define GL_RGB10_A2_EXT 0x8059 /* reuse tokens from EXT_texture */
|
||||
#define GL_RGB10_EXT 0x8052
|
||||
/* EXT_texture_format_BGRA8888 dependent internal formats */
|
||||
#define GL_BGRA8_EXT 0x93A1
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* DMP extension tokens
|
||||
*------------------------------------------------------------------------*/
|
||||
|
@ -824,6 +866,11 @@ GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLs
|
|||
typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
|
||||
#endif
|
||||
|
||||
/* GL_ANGLE_texture_usage */
|
||||
#ifndef GL_ANGLE_texture_usage
|
||||
#define GL_ANGLE_texture_usage 1
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* APPLE extension functions
|
||||
*------------------------------------------------------------------------*/
|
||||
|
@ -931,6 +978,30 @@ typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GL
|
|||
#define GL_EXT_unpack_subimage 1
|
||||
#endif
|
||||
|
||||
/* GL_EXT_robustness */
|
||||
#ifndef GL_EXT_robustness
|
||||
#define GL_EXT_robustness 1
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
|
||||
GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
|
||||
GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
|
||||
#endif /* GL_GLEXT_PROTOTYPES */
|
||||
typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
|
||||
typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
|
||||
typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
|
||||
#endif
|
||||
|
||||
/* GL_EXT_texture_storage */
|
||||
#ifndef GL_EXT_texture_storage
|
||||
#define GL_EXT_texture_storage 1
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GL_APICALL void GL_APIENTRY TexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
#endif /* GL_GLEXT_PROTOTYPES */
|
||||
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXT) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* DMP extension functions
|
||||
*------------------------------------------------------------------------*/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#define MAJOR_VERSION 0
|
||||
#define MINOR_VERSION 0
|
||||
#define BUILD_VERSION 0
|
||||
#define BUILD_REVISION 809
|
||||
#define BUILD_REVISION 885
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define MACRO_STRINGIFY(x) STRINGIFY(x)
|
||||
|
|
|
@ -624,7 +624,7 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
|
|||
switch(type) {
|
||||
case SH_FRAGMENT_SHADER: {
|
||||
// Set up gl_FragData. The array size.
|
||||
TType fragData(EbtFloat, EbpMedium, EvqFragColor, 4, false, true);
|
||||
TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true);
|
||||
fragData.setArraySize(resources.MaxDrawBuffers);
|
||||
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@ Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool softwar
|
|||
mMaxSwapInterval = 1;
|
||||
mSoftwareDevice = software;
|
||||
mDisplayId = displayId;
|
||||
mDeviceLost = false;
|
||||
}
|
||||
|
||||
Display::~Display()
|
||||
|
@ -304,7 +305,7 @@ void Display::terminate()
|
|||
if (mDevice)
|
||||
{
|
||||
// If the device is lost, reset it first to prevent leaving the driver in an unstable state
|
||||
if (isDeviceLost())
|
||||
if (testDeviceLost())
|
||||
{
|
||||
resetDevice();
|
||||
}
|
||||
|
@ -457,23 +458,44 @@ bool Display::createDevice()
|
|||
bool Display::resetDevice()
|
||||
{
|
||||
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
|
||||
HRESULT result;
|
||||
|
||||
do
|
||||
HRESULT result = D3D_OK;
|
||||
bool lost = testDeviceLost();
|
||||
int attempts = 3;
|
||||
|
||||
while (lost && attempts > 0)
|
||||
{
|
||||
Sleep(0); // Give the graphics driver some CPU time
|
||||
if (mDeviceEx)
|
||||
{
|
||||
Sleep(500); // Give the graphics driver some CPU time
|
||||
result = mDeviceEx->ResetEx(&presentParameters, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = mDevice->TestCooperativeLevel();
|
||||
|
||||
result = mDevice->Reset(&presentParameters);
|
||||
while (result == D3DERR_DEVICELOST)
|
||||
{
|
||||
Sleep(100); // Give the graphics driver some CPU time
|
||||
result = mDevice->TestCooperativeLevel();
|
||||
}
|
||||
|
||||
if (result == D3DERR_DEVICENOTRESET)
|
||||
{
|
||||
result = mDevice->Reset(&presentParameters);
|
||||
}
|
||||
}
|
||||
|
||||
lost = testDeviceLost();
|
||||
attempts --;
|
||||
}
|
||||
while (result == D3DERR_DEVICELOST);
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
|
||||
return error(EGL_BAD_ALLOC, false);
|
||||
}
|
||||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -515,7 +537,8 @@ EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGL
|
|||
return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
|
||||
}
|
||||
|
||||
if (isDeviceLost()) {
|
||||
if (testDeviceLost())
|
||||
{
|
||||
if (!restoreLostDevice())
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
@ -627,7 +650,8 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
|
|||
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
|
||||
}
|
||||
|
||||
if (isDeviceLost()) {
|
||||
if (testDeviceLost())
|
||||
{
|
||||
if (!restoreLostDevice())
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
@ -645,7 +669,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
|
|||
return success(surface);
|
||||
}
|
||||
|
||||
EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
|
||||
EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
|
||||
{
|
||||
if (!mDevice)
|
||||
{
|
||||
|
@ -654,7 +678,7 @@ EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *sha
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (isDeviceLost()) // Lost device
|
||||
else if (testDeviceLost()) // Lost device
|
||||
{
|
||||
if (!restoreLostDevice())
|
||||
return NULL;
|
||||
|
@ -662,14 +686,21 @@ EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *sha
|
|||
|
||||
const egl::Config *config = mConfigSet.get(configHandle);
|
||||
|
||||
gl::Context *context = glCreateContext(config, shareContext);
|
||||
gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess);
|
||||
mContextSet.insert(context);
|
||||
mDeviceLost = false;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
bool Display::restoreLostDevice()
|
||||
{
|
||||
for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
|
||||
{
|
||||
if ((*ctx)->isResetNotificationEnabled())
|
||||
return false; // If reset notifications have been requested, application must delete all contexts first
|
||||
}
|
||||
|
||||
// Release surface resources to make the Reset() succeed
|
||||
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
|
||||
{
|
||||
|
@ -703,6 +734,21 @@ void Display::destroyContext(gl::Context *context)
|
|||
mContextSet.erase(context);
|
||||
}
|
||||
|
||||
void Display::notifyDeviceLost()
|
||||
{
|
||||
for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
|
||||
{
|
||||
(*context)->markContextLost();
|
||||
}
|
||||
mDeviceLost = true;
|
||||
error(EGL_CONTEXT_LOST);
|
||||
}
|
||||
|
||||
bool Display::isDeviceLost()
|
||||
{
|
||||
return mDeviceLost;
|
||||
}
|
||||
|
||||
bool Display::isInitialized() const
|
||||
{
|
||||
return mD3d9 != NULL && mConfigSet.size() > 0;
|
||||
|
@ -769,13 +815,13 @@ D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier()
|
|||
return &mAdapterIdentifier;
|
||||
}
|
||||
|
||||
bool Display::isDeviceLost()
|
||||
bool Display::testDeviceLost()
|
||||
{
|
||||
if (mDeviceEx)
|
||||
{
|
||||
return FAILED(mDeviceEx->CheckDeviceState(NULL));
|
||||
}
|
||||
else if(mDevice)
|
||||
else if (mDevice)
|
||||
{
|
||||
return FAILED(mDevice->TestCooperativeLevel());
|
||||
}
|
||||
|
@ -783,6 +829,29 @@ bool Display::isDeviceLost()
|
|||
return false; // No device yet, so no reset required
|
||||
}
|
||||
|
||||
bool Display::testDeviceResettable()
|
||||
{
|
||||
HRESULT status = D3D_OK;
|
||||
|
||||
if (mDeviceEx)
|
||||
{
|
||||
status = mDeviceEx->CheckDeviceState(NULL);
|
||||
}
|
||||
else if (mDevice)
|
||||
{
|
||||
status = mDevice->TestCooperativeLevel();
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case D3DERR_DEVICENOTRESET:
|
||||
case D3DERR_DEVICEHUNG:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
|
||||
{
|
||||
for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
|
||||
|
@ -818,7 +887,7 @@ bool Display::getDXT5TextureSupport()
|
|||
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
|
||||
}
|
||||
|
||||
bool Display::getFloatTextureSupport(bool *filtering, bool *renderable)
|
||||
bool Display::getFloat32TextureSupport(bool *filtering, bool *renderable)
|
||||
{
|
||||
D3DDISPLAYMODE currentDisplayMode;
|
||||
mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode);
|
||||
|
@ -846,7 +915,7 @@ bool Display::getFloatTextureSupport(bool *filtering, bool *renderable)
|
|||
}
|
||||
}
|
||||
|
||||
bool Display::getHalfFloatTextureSupport(bool *filtering, bool *renderable)
|
||||
bool Display::getFloat16TextureSupport(bool *filtering, bool *renderable)
|
||||
{
|
||||
D3DDISPLAYMODE currentDisplayMode;
|
||||
mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode);
|
||||
|
@ -907,6 +976,23 @@ D3DPOOL Display::getBufferPool(DWORD usage) const
|
|||
return D3DPOOL_DEFAULT;
|
||||
}
|
||||
|
||||
D3DPOOL Display::getTexturePool(bool renderable) const
|
||||
{
|
||||
if (mD3d9Ex != NULL)
|
||||
{
|
||||
return D3DPOOL_DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!renderable)
|
||||
{
|
||||
return D3DPOOL_MANAGED;
|
||||
}
|
||||
}
|
||||
|
||||
return D3DPOOL_DEFAULT;
|
||||
}
|
||||
|
||||
bool Display::getEventQuerySupport()
|
||||
{
|
||||
IDirect3DQuery9 *query;
|
||||
|
@ -948,6 +1034,10 @@ void Display::initExtensionString()
|
|||
|
||||
mExtensionString = "";
|
||||
|
||||
// Multi-vendor (EXT) extensions
|
||||
mExtensionString += "EGL_EXT_create_context_robustness ";
|
||||
|
||||
// ANGLE-specific extensions
|
||||
if (isd3d9ex) {
|
||||
mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class Display
|
|||
|
||||
EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList);
|
||||
EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
|
||||
EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);
|
||||
EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
|
||||
|
||||
void destroySurface(egl::Surface *surface);
|
||||
void destroyContext(gl::Context *context);
|
||||
|
@ -61,19 +61,24 @@ class Display
|
|||
virtual IDirect3DDevice9 *getDevice();
|
||||
virtual D3DCAPS9 getDeviceCaps();
|
||||
virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier();
|
||||
bool isDeviceLost();
|
||||
virtual bool testDeviceLost();
|
||||
virtual bool testDeviceResettable();
|
||||
virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
|
||||
virtual bool getDXT1TextureSupport();
|
||||
virtual bool getDXT3TextureSupport();
|
||||
virtual bool getDXT5TextureSupport();
|
||||
virtual bool getEventQuerySupport();
|
||||
virtual bool getFloatTextureSupport(bool *filtering, bool *renderable);
|
||||
virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable);
|
||||
virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
|
||||
virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
|
||||
virtual bool getLuminanceTextureSupport();
|
||||
virtual bool getLuminanceAlphaTextureSupport();
|
||||
virtual bool getVertexTextureSupport() const;
|
||||
virtual bool getNonPower2TextureSupport() const;
|
||||
virtual D3DPOOL getBufferPool(DWORD usage) const;
|
||||
virtual D3DPOOL getTexturePool(bool renderable) const;
|
||||
|
||||
virtual void notifyDeviceLost();
|
||||
bool isDeviceLost();
|
||||
|
||||
bool isD3d9ExDevice() { return mD3d9Ex != NULL; }
|
||||
const char *getExtensionString() const;
|
||||
|
@ -114,6 +119,7 @@ class Display
|
|||
|
||||
typedef std::set<gl::Context*> ContextSet;
|
||||
ContextSet mContextSet;
|
||||
bool mDeviceLost;
|
||||
|
||||
bool createDevice();
|
||||
bool resetDevice();
|
||||
|
|
|
@ -106,7 +106,7 @@ bool Surface::initialize()
|
|||
|
||||
result = DwmSetPresentParameters(mWindow, &presentParams);
|
||||
if (FAILED(result))
|
||||
ERR("Unable to set present parameters: %081X", result);
|
||||
ERR("Unable to set present parameters: 0x%08X", result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,11 +250,20 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
|
|||
|
||||
if (FAILED(result))
|
||||
{
|
||||
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
|
||||
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
|
||||
|
||||
ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
|
||||
release();
|
||||
return error(EGL_BAD_ALLOC, false);
|
||||
|
||||
if(isDeviceLostError(result))
|
||||
{
|
||||
mDisplay->notifyDeviceLost();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return error(EGL_BAD_ALLOC, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
|
||||
|
@ -268,7 +277,7 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
|
|||
{
|
||||
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
|
||||
|
||||
ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
|
||||
ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
|
||||
release();
|
||||
return error(EGL_BAD_ALLOC, false);
|
||||
}
|
||||
|
@ -413,14 +422,15 @@ bool Surface::swap()
|
|||
|
||||
HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0);
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
return error(EGL_BAD_ALLOC, false);
|
||||
}
|
||||
|
||||
if (result == D3DERR_DEVICELOST || result == D3DERR_DEVICEHUNG || result == D3DERR_DEVICEREMOVED)
|
||||
if (isDeviceLostError(result))
|
||||
{
|
||||
return error(EGL_CONTEXT_LOST, false);
|
||||
mDisplay->notifyDeviceLost();
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
|
|
@ -715,7 +715,10 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
|
|||
return error(EGL_BAD_MATCH, EGL_FALSE);
|
||||
}
|
||||
|
||||
glBindTexImage(eglSurface);
|
||||
if (!glBindTexImage(eglSurface))
|
||||
{
|
||||
return error(EGL_BAD_MATCH, EGL_FALSE);
|
||||
}
|
||||
|
||||
return success(EGL_TRUE);
|
||||
}
|
||||
|
@ -814,16 +817,34 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
|
|||
{
|
||||
// Get the requested client version (default is 1) and check it is two.
|
||||
EGLint client_version = 1;
|
||||
bool reset_notification = false;
|
||||
bool robust_access = false;
|
||||
|
||||
if (attrib_list)
|
||||
{
|
||||
for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
|
||||
{
|
||||
if (attribute[0] == EGL_CONTEXT_CLIENT_VERSION)
|
||||
switch (attribute[0])
|
||||
{
|
||||
case EGL_CONTEXT_CLIENT_VERSION:
|
||||
client_version = attribute[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
|
||||
if (attribute[1] == EGL_TRUE)
|
||||
{
|
||||
return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented
|
||||
robust_access = true;
|
||||
}
|
||||
else if (attribute[1] != EGL_FALSE)
|
||||
return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
|
||||
break;
|
||||
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
|
||||
if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
|
||||
reset_notification = true;
|
||||
else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
|
||||
return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
|
||||
break;
|
||||
default:
|
||||
return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
|
||||
}
|
||||
}
|
||||
|
@ -834,6 +855,11 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
|
|||
return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
if (share_context && static_cast<gl::Context*>(share_context)->isResetNotificationEnabled() != reset_notification)
|
||||
{
|
||||
return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
egl::Display *display = static_cast<egl::Display*>(dpy);
|
||||
|
||||
if (!validateConfig(display, config))
|
||||
|
@ -841,9 +867,12 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
|
|||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context));
|
||||
EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
|
||||
|
||||
return success(context);
|
||||
if (context)
|
||||
return success(context);
|
||||
else
|
||||
return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
|
||||
}
|
||||
catch(std::bad_alloc&)
|
||||
{
|
||||
|
@ -895,7 +924,13 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
|
|||
gl::Context *context = static_cast<gl::Context*>(ctx);
|
||||
IDirect3DDevice9 *device = display->getDevice();
|
||||
|
||||
if (!device || display->isDeviceLost())
|
||||
if (!device || display->testDeviceLost())
|
||||
{
|
||||
display->notifyDeviceLost();
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (display->isDeviceLost())
|
||||
{
|
||||
return error(EGL_CONTEXT_LOST, EGL_FALSE);
|
||||
}
|
||||
|
@ -1077,6 +1112,11 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
|
|||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (display->isDeviceLost())
|
||||
{
|
||||
return error(EGL_CONTEXT_LOST, EGL_FALSE);
|
||||
}
|
||||
|
||||
if (surface == EGL_NO_SURFACE)
|
||||
{
|
||||
return error(EGL_BAD_SURFACE, EGL_FALSE);
|
||||
|
@ -1109,6 +1149,11 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ
|
|||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (display->isDeviceLost())
|
||||
{
|
||||
return error(EGL_CONTEXT_LOST, EGL_FALSE);
|
||||
}
|
||||
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
|
||||
return success(0);
|
||||
|
|
|
@ -38,8 +38,10 @@ namespace
|
|||
|
||||
namespace gl
|
||||
{
|
||||
Context::Context(const egl::Config *config, const gl::Context *shareContext) : mConfig(config)
|
||||
Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config)
|
||||
{
|
||||
ASSERT(robustAccess == false); // Unimplemented
|
||||
|
||||
mDisplay = NULL;
|
||||
mDevice = NULL;
|
||||
|
||||
|
@ -158,6 +160,10 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) : m
|
|||
mInvalidFramebufferOperation = false;
|
||||
|
||||
mHasBeenCurrent = false;
|
||||
mContextLost = false;
|
||||
mResetStatus = GL_NO_ERROR;
|
||||
mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
|
||||
mRobustAccess = robustAccess;
|
||||
|
||||
mSupportsDXT1Textures = false;
|
||||
mSupportsDXT3Textures = false;
|
||||
|
@ -290,8 +296,8 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
|
|||
mSupportsDXT1Textures = mDisplay->getDXT1TextureSupport();
|
||||
mSupportsDXT3Textures = mDisplay->getDXT3TextureSupport();
|
||||
mSupportsDXT5Textures = mDisplay->getDXT5TextureSupport();
|
||||
mSupportsFloatTextures = mDisplay->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures);
|
||||
mSupportsHalfFloatTextures = mDisplay->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures);
|
||||
mSupportsFloat32Textures = mDisplay->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures);
|
||||
mSupportsFloat16Textures = mDisplay->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures);
|
||||
mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport();
|
||||
mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport();
|
||||
|
||||
|
@ -389,6 +395,18 @@ void Context::markAllStateDirty()
|
|||
mCachedCurrentProgram = NULL;
|
||||
}
|
||||
|
||||
void Context::markContextLost()
|
||||
{
|
||||
if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
|
||||
mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
|
||||
mContextLost = true;
|
||||
}
|
||||
|
||||
bool Context::isContextLost()
|
||||
{
|
||||
return mContextLost;
|
||||
}
|
||||
|
||||
void Context::setClearColor(float red, float green, float blue, float alpha)
|
||||
{
|
||||
mState.colorClearValue.red = red;
|
||||
|
@ -1158,24 +1176,25 @@ bool Context::getBooleanv(GLenum pname, GLboolean *params)
|
|||
{
|
||||
switch (pname)
|
||||
{
|
||||
case GL_SHADER_COMPILER: *params = GL_TRUE; break;
|
||||
case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
|
||||
case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
|
||||
case GL_SHADER_COMPILER: *params = GL_TRUE; break;
|
||||
case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
|
||||
case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
|
||||
case GL_COLOR_WRITEMASK:
|
||||
params[0] = mState.colorMaskRed;
|
||||
params[1] = mState.colorMaskGreen;
|
||||
params[2] = mState.colorMaskBlue;
|
||||
params[3] = mState.colorMaskAlpha;
|
||||
break;
|
||||
case GL_CULL_FACE: *params = mState.cullFace; break;
|
||||
case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break;
|
||||
case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break;
|
||||
case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
|
||||
case GL_SCISSOR_TEST: *params = mState.scissorTest; break;
|
||||
case GL_STENCIL_TEST: *params = mState.stencilTest; break;
|
||||
case GL_DEPTH_TEST: *params = mState.depthTest; break;
|
||||
case GL_BLEND: *params = mState.blend; break;
|
||||
case GL_DITHER: *params = mState.dither; break;
|
||||
case GL_CULL_FACE: *params = mState.cullFace; break;
|
||||
case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break;
|
||||
case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break;
|
||||
case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
|
||||
case GL_SCISSOR_TEST: *params = mState.scissorTest; break;
|
||||
case GL_STENCIL_TEST: *params = mState.stencilTest; break;
|
||||
case GL_DEPTH_TEST: *params = mState.depthTest; break;
|
||||
case GL_BLEND: *params = mState.blend; break;
|
||||
case GL_DITHER: *params = mState.dither; break;
|
||||
case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -1375,7 +1394,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
|
|||
case GL_ALPHA_BITS:
|
||||
{
|
||||
gl::Framebuffer *framebuffer = getDrawFramebuffer();
|
||||
gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
|
||||
gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
|
||||
|
||||
if (colorbuffer)
|
||||
{
|
||||
|
@ -1396,7 +1415,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
|
|||
case GL_DEPTH_BITS:
|
||||
{
|
||||
gl::Framebuffer *framebuffer = getDrawFramebuffer();
|
||||
gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
|
||||
gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
|
||||
|
||||
if (depthbuffer)
|
||||
{
|
||||
|
@ -1411,7 +1430,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
|
|||
case GL_STENCIL_BITS:
|
||||
{
|
||||
gl::Framebuffer *framebuffer = getDrawFramebuffer();
|
||||
gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
|
||||
gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
|
||||
|
||||
if (stencilbuffer)
|
||||
{
|
||||
|
@ -1445,6 +1464,9 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
|
|||
*params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
|
||||
}
|
||||
break;
|
||||
case GL_RESET_NOTIFICATION_STRATEGY_EXT:
|
||||
*params = mResetStrategy;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -1534,6 +1556,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
|
|||
case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
|
||||
case GL_TEXTURE_BINDING_2D:
|
||||
case GL_TEXTURE_BINDING_CUBE_MAP:
|
||||
case GL_RESET_NOTIFICATION_STRATEGY_EXT:
|
||||
{
|
||||
*type = GL_INT;
|
||||
*numParams = 1;
|
||||
|
@ -1577,6 +1600,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
|
|||
case GL_DEPTH_TEST:
|
||||
case GL_BLEND:
|
||||
case GL_DITHER:
|
||||
case GL_CONTEXT_ROBUST_ACCESS_EXT:
|
||||
{
|
||||
*type = GL_BOOL;
|
||||
*numParams = 1;
|
||||
|
@ -1730,7 +1754,7 @@ bool Context::applyRenderTarget(bool ignoreViewport)
|
|||
return false; // Nothing to render
|
||||
}
|
||||
|
||||
if (!mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0)
|
||||
if (renderTargetChanged || !mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0)
|
||||
{
|
||||
mDevice->SetViewport(&viewport);
|
||||
mSetViewport = viewport;
|
||||
|
@ -1911,7 +1935,7 @@ void Context::applyState(GLenum drawMode)
|
|||
}
|
||||
|
||||
// get the maximum size of the stencil ref
|
||||
gl::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
|
||||
gl::Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
|
||||
GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
|
||||
|
||||
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
|
||||
|
@ -1978,7 +2002,7 @@ void Context::applyState(GLenum drawMode)
|
|||
{
|
||||
if (mState.polygonOffsetFill)
|
||||
{
|
||||
gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
|
||||
gl::Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer();
|
||||
if (depthbuffer)
|
||||
{
|
||||
mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
|
||||
|
@ -2127,13 +2151,13 @@ void Context::applyTextures(SamplerType type)
|
|||
|
||||
Texture *texture = getSamplerTexture(textureUnit, textureType);
|
||||
|
||||
if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter() || texture->isDirtyImage())
|
||||
if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyParameters() || texture->hasDirtyImages())
|
||||
{
|
||||
IDirect3DBaseTexture9 *d3dTexture = texture->getTexture();
|
||||
|
||||
if (d3dTexture)
|
||||
{
|
||||
if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter())
|
||||
if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyParameters())
|
||||
{
|
||||
GLenum wrapS = texture->getWrapS();
|
||||
GLenum wrapT = texture->getWrapT();
|
||||
|
@ -2150,7 +2174,7 @@ void Context::applyTextures(SamplerType type)
|
|||
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
|
||||
}
|
||||
|
||||
if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyImage())
|
||||
if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyImages())
|
||||
{
|
||||
mDevice->SetTexture(d3dSampler, d3dTexture);
|
||||
}
|
||||
|
@ -2160,7 +2184,7 @@ void Context::applyTextures(SamplerType type)
|
|||
mDevice->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture());
|
||||
}
|
||||
|
||||
appliedTextureSerial[samplerIndex] = texture->getSerial();
|
||||
appliedTextureSerial[samplerIndex] = texture->getTextureSerial();
|
||||
texture->resetDirty();
|
||||
}
|
||||
}
|
||||
|
@ -2184,7 +2208,8 @@ void Context::applyTextures(SamplerType type)
|
|||
}
|
||||
}
|
||||
|
||||
void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
|
||||
void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
|
||||
{
|
||||
Framebuffer *framebuffer = getReadFramebuffer();
|
||||
|
||||
|
@ -2198,6 +2223,17 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||
return error(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
|
||||
// sized query sanity check
|
||||
if (bufSize)
|
||||
{
|
||||
int requiredSize = outputPitch * height;
|
||||
if (requiredSize > *bufSize)
|
||||
{
|
||||
return error(GL_INVALID_OPERATION);
|
||||
}
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
|
||||
|
||||
if (!renderTarget)
|
||||
|
@ -2229,18 +2265,16 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||
{
|
||||
systemSurface->Release();
|
||||
|
||||
switch (result)
|
||||
{
|
||||
// It turns out that D3D will sometimes produce more error
|
||||
// codes than those documented.
|
||||
case D3DERR_DRIVERINTERNALERROR:
|
||||
case D3DERR_DEVICELOST:
|
||||
case D3DERR_DEVICEHUNG:
|
||||
// It turns out that D3D will sometimes produce more error
|
||||
// codes than those documented.
|
||||
if (checkDeviceLost(result))
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
default:
|
||||
else
|
||||
{
|
||||
UNREACHABLE();
|
||||
return; // No sensible error to generate
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT lock;
|
||||
|
@ -2264,7 +2298,6 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||
unsigned char *dest = (unsigned char*)pixels;
|
||||
unsigned short *dest16 = (unsigned short*)pixels;
|
||||
int inputPitch = -lock.Pitch;
|
||||
GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
|
||||
|
||||
for (int j = 0; j < rect.bottom - rect.top; j++)
|
||||
{
|
||||
|
@ -2826,7 +2859,7 @@ void Context::sync(bool block)
|
|||
|
||||
eventQuery->Release();
|
||||
|
||||
if (result == D3DERR_DEVICELOST)
|
||||
if (checkDeviceLost(result))
|
||||
{
|
||||
error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
|
@ -2994,6 +3027,36 @@ GLenum Context::getError()
|
|||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum Context::getResetStatus()
|
||||
{
|
||||
if (mResetStatus == GL_NO_ERROR)
|
||||
{
|
||||
bool lost = mDisplay->testDeviceLost();
|
||||
|
||||
if (lost)
|
||||
{
|
||||
mDisplay->notifyDeviceLost(); // Sets mResetStatus
|
||||
}
|
||||
}
|
||||
|
||||
GLenum status = mResetStatus;
|
||||
|
||||
if (mResetStatus != GL_NO_ERROR)
|
||||
{
|
||||
if (mDisplay->testDeviceResettable())
|
||||
{
|
||||
mResetStatus = GL_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Context::isResetNotificationEnabled()
|
||||
{
|
||||
return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
|
||||
}
|
||||
|
||||
bool Context::supportsShaderModel3() const
|
||||
{
|
||||
return mSupportsShaderModel3;
|
||||
|
@ -3068,34 +3131,34 @@ bool Context::supportsDXT5Textures() const
|
|||
return mSupportsDXT5Textures;
|
||||
}
|
||||
|
||||
bool Context::supportsFloatTextures() const
|
||||
bool Context::supportsFloat32Textures() const
|
||||
{
|
||||
return mSupportsFloatTextures;
|
||||
return mSupportsFloat32Textures;
|
||||
}
|
||||
|
||||
bool Context::supportsFloatLinearFilter() const
|
||||
bool Context::supportsFloat32LinearFilter() const
|
||||
{
|
||||
return mSupportsFloatLinearFilter;
|
||||
return mSupportsFloat32LinearFilter;
|
||||
}
|
||||
|
||||
bool Context::supportsFloatRenderableTextures() const
|
||||
bool Context::supportsFloat32RenderableTextures() const
|
||||
{
|
||||
return mSupportsFloatRenderableTextures;
|
||||
return mSupportsFloat32RenderableTextures;
|
||||
}
|
||||
|
||||
bool Context::supportsHalfFloatTextures() const
|
||||
bool Context::supportsFloat16Textures() const
|
||||
{
|
||||
return mSupportsHalfFloatTextures;
|
||||
return mSupportsFloat16Textures;
|
||||
}
|
||||
|
||||
bool Context::supportsHalfFloatLinearFilter() const
|
||||
bool Context::supportsFloat16LinearFilter() const
|
||||
{
|
||||
return mSupportsHalfFloatLinearFilter;
|
||||
return mSupportsFloat16LinearFilter;
|
||||
}
|
||||
|
||||
bool Context::supportsHalfFloatRenderableTextures() const
|
||||
bool Context::supportsFloat16RenderableTextures() const
|
||||
{
|
||||
return mSupportsHalfFloatRenderableTextures;
|
||||
return mSupportsFloat16RenderableTextures;
|
||||
}
|
||||
|
||||
int Context::getMaximumRenderbufferDimension() const
|
||||
|
@ -3344,19 +3407,19 @@ void Context::initExtensionString()
|
|||
mExtensionString += "GL_OES_rgb8_rgba8 ";
|
||||
mExtensionString += "GL_OES_standard_derivatives ";
|
||||
|
||||
if (supportsHalfFloatTextures())
|
||||
if (supportsFloat16Textures())
|
||||
{
|
||||
mExtensionString += "GL_OES_texture_half_float ";
|
||||
}
|
||||
if (supportsHalfFloatLinearFilter())
|
||||
if (supportsFloat16LinearFilter())
|
||||
{
|
||||
mExtensionString += "GL_OES_texture_half_float_linear ";
|
||||
}
|
||||
if (supportsFloatTextures())
|
||||
if (supportsFloat32Textures())
|
||||
{
|
||||
mExtensionString += "GL_OES_texture_float ";
|
||||
}
|
||||
if (supportsFloatLinearFilter())
|
||||
if (supportsFloat32LinearFilter())
|
||||
{
|
||||
mExtensionString += "GL_OES_texture_float_linear ";
|
||||
}
|
||||
|
@ -3368,6 +3431,7 @@ void Context::initExtensionString()
|
|||
|
||||
// Multi-vendor (EXT) extensions
|
||||
mExtensionString += "GL_EXT_read_format_bgra ";
|
||||
mExtensionString += "GL_EXT_robustness ";
|
||||
|
||||
if (supportsDXT1Textures())
|
||||
{
|
||||
|
@ -3375,6 +3439,7 @@ void Context::initExtensionString()
|
|||
}
|
||||
|
||||
mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
|
||||
mExtensionString += "GL_EXT_texture_storage ";
|
||||
|
||||
// ANGLE-specific extensions
|
||||
mExtensionString += "GL_ANGLE_framebuffer_blit ";
|
||||
|
@ -3391,6 +3456,8 @@ void Context::initExtensionString()
|
|||
{
|
||||
mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
|
||||
}
|
||||
|
||||
mExtensionString += "GL_ANGLE_texture_usage ";
|
||||
mExtensionString += "GL_ANGLE_translated_shader_source ";
|
||||
|
||||
// Other vendor-specific extensions
|
||||
|
@ -3616,8 +3683,8 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
|
|||
|
||||
if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
|
||||
{
|
||||
DepthStencilbuffer *readDSBuffer = NULL;
|
||||
DepthStencilbuffer *drawDSBuffer = NULL;
|
||||
Renderbuffer *readDSBuffer = NULL;
|
||||
Renderbuffer *drawDSBuffer = NULL;
|
||||
|
||||
// We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
|
||||
// both a depth and stencil buffer, it will be the same buffer.
|
||||
|
@ -3805,9 +3872,9 @@ void VertexDeclarationCache::markStateDirty()
|
|||
|
||||
extern "C"
|
||||
{
|
||||
gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
|
||||
gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
|
||||
{
|
||||
return new gl::Context(config, shareContext);
|
||||
return new gl::Context(config, shareContext, notifyResets, robustAccess);
|
||||
}
|
||||
|
||||
void glDestroyContext(gl::Context *context)
|
||||
|
|
|
@ -258,7 +258,7 @@ class VertexDeclarationCache
|
|||
class Context
|
||||
{
|
||||
public:
|
||||
Context(const egl::Config *config, const gl::Context *shareContext);
|
||||
Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
|
||||
|
||||
~Context();
|
||||
|
||||
|
@ -266,6 +266,9 @@ class Context
|
|||
|
||||
void markAllStateDirty();
|
||||
|
||||
virtual void markContextLost();
|
||||
bool isContextLost();
|
||||
|
||||
// State manipulation
|
||||
void setClearColor(float red, float green, float blue, float alpha);
|
||||
|
||||
|
@ -417,7 +420,7 @@ class Context
|
|||
|
||||
bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
|
||||
|
||||
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
|
||||
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
|
||||
void clear(GLbitfield mask);
|
||||
void drawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
|
@ -434,6 +437,8 @@ class Context
|
|||
void recordInvalidFramebufferOperation();
|
||||
|
||||
GLenum getError();
|
||||
GLenum getResetStatus();
|
||||
virtual bool isResetNotificationEnabled();
|
||||
|
||||
bool supportsShaderModel3() const;
|
||||
int getMaximumVaryingVectors() const;
|
||||
|
@ -452,12 +457,12 @@ class Context
|
|||
bool supportsDXT1Textures() const;
|
||||
bool supportsDXT3Textures() const;
|
||||
bool supportsDXT5Textures() const;
|
||||
bool supportsFloatTextures() const;
|
||||
bool supportsFloatLinearFilter() const;
|
||||
bool supportsFloatRenderableTextures() const;
|
||||
bool supportsHalfFloatTextures() const;
|
||||
bool supportsHalfFloatLinearFilter() const;
|
||||
bool supportsHalfFloatRenderableTextures() const;
|
||||
bool supportsFloat32Textures() const;
|
||||
bool supportsFloat32LinearFilter() const;
|
||||
bool supportsFloat32RenderableTextures() const;
|
||||
bool supportsFloat16Textures() const;
|
||||
bool supportsFloat16LinearFilter() const;
|
||||
bool supportsFloat16RenderableTextures() const;
|
||||
bool supportsLuminanceTextures() const;
|
||||
bool supportsLuminanceAlphaTextures() const;
|
||||
bool supports32bitIndices() const;
|
||||
|
@ -531,7 +536,12 @@ class Context
|
|||
bool mOutOfMemory;
|
||||
bool mInvalidFramebufferOperation;
|
||||
|
||||
// Current/lost context flags
|
||||
bool mHasBeenCurrent;
|
||||
bool mContextLost;
|
||||
GLenum mResetStatus;
|
||||
GLenum mResetStrategy;
|
||||
bool mRobustAccess;
|
||||
|
||||
unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS];
|
||||
unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
|
||||
|
@ -562,12 +572,12 @@ class Context
|
|||
bool mSupportsDXT1Textures;
|
||||
bool mSupportsDXT3Textures;
|
||||
bool mSupportsDXT5Textures;
|
||||
bool mSupportsFloatTextures;
|
||||
bool mSupportsFloatLinearFilter;
|
||||
bool mSupportsFloatRenderableTextures;
|
||||
bool mSupportsHalfFloatTextures;
|
||||
bool mSupportsHalfFloatLinearFilter;
|
||||
bool mSupportsHalfFloatRenderableTextures;
|
||||
bool mSupportsFloat32Textures;
|
||||
bool mSupportsFloat32LinearFilter;
|
||||
bool mSupportsFloat32RenderableTextures;
|
||||
bool mSupportsFloat16Textures;
|
||||
bool mSupportsFloat16LinearFilter;
|
||||
bool mSupportsFloat16RenderableTextures;
|
||||
bool mSupportsLuminanceTextures;
|
||||
bool mSupportsLuminanceAlphaTextures;
|
||||
bool mSupports32bitIndices;
|
||||
|
@ -600,12 +610,12 @@ class Context
|
|||
extern "C"
|
||||
{
|
||||
// Exported functions for use by EGL
|
||||
gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext);
|
||||
gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
|
||||
void glDestroyContext(gl::Context *context);
|
||||
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
|
||||
gl::Context *glGetCurrentContext();
|
||||
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
|
||||
void __stdcall glBindTexImage(egl::Surface *surface);
|
||||
bool __stdcall glBindTexImage(egl::Surface *surface);
|
||||
}
|
||||
|
||||
#endif // INCLUDE_CONTEXT_H_
|
||||
|
|
|
@ -65,7 +65,7 @@ GLboolean Fence::testFence()
|
|||
|
||||
HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
||||
|
||||
if (result == D3DERR_DEVICELOST)
|
||||
if (checkDeviceLost(result))
|
||||
{
|
||||
return error(GL_OUT_OF_MEMORY, GL_TRUE);
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ void Fence::getFenceiv(GLenum pname, GLint *params)
|
|||
|
||||
HRESULT result = mQuery->GetData(NULL, 0, 0);
|
||||
|
||||
if (result == D3DERR_DEVICELOST)
|
||||
if (checkDeviceLost(result))
|
||||
{
|
||||
params[0] = GL_TRUE;
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
|
|
|
@ -181,46 +181,19 @@ unsigned int Framebuffer::getStencilbufferSerial()
|
|||
return 0;
|
||||
}
|
||||
|
||||
Colorbuffer *Framebuffer::getColorbuffer()
|
||||
Renderbuffer *Framebuffer::getColorbuffer()
|
||||
{
|
||||
Renderbuffer *rb = mColorbufferPointer.get();
|
||||
|
||||
if (rb != NULL && rb->isColorbuffer())
|
||||
{
|
||||
return static_cast<Colorbuffer*>(rb->getStorage());
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return mColorbufferPointer.get();
|
||||
}
|
||||
|
||||
DepthStencilbuffer *Framebuffer::getDepthbuffer()
|
||||
Renderbuffer *Framebuffer::getDepthbuffer()
|
||||
{
|
||||
Renderbuffer *rb = mDepthbufferPointer.get();
|
||||
|
||||
if (rb != NULL && rb->isDepthbuffer())
|
||||
{
|
||||
return static_cast<DepthStencilbuffer*>(rb->getStorage());
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return mDepthbufferPointer.get();
|
||||
}
|
||||
|
||||
DepthStencilbuffer *Framebuffer::getStencilbuffer()
|
||||
Renderbuffer *Framebuffer::getStencilbuffer()
|
||||
{
|
||||
Renderbuffer *rb = mStencilbufferPointer.get();
|
||||
|
||||
if (rb != NULL && rb->isStencilbuffer())
|
||||
{
|
||||
return static_cast<DepthStencilbuffer*>(rb->getStorage());
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return mStencilbufferPointer.get();
|
||||
}
|
||||
|
||||
GLenum Framebuffer::getColorbufferType()
|
||||
|
@ -257,7 +230,7 @@ bool Framebuffer::hasStencil()
|
|||
{
|
||||
if (mStencilbufferType != GL_NONE)
|
||||
{
|
||||
DepthStencilbuffer *stencilbufferObject = getStencilbuffer();
|
||||
Renderbuffer *stencilbufferObject = getStencilbuffer();
|
||||
|
||||
if (stencilbufferObject)
|
||||
{
|
||||
|
@ -276,7 +249,7 @@ GLenum Framebuffer::completeness()
|
|||
|
||||
if (mColorbufferType != GL_NONE)
|
||||
{
|
||||
Colorbuffer *colorbuffer = getColorbuffer();
|
||||
Renderbuffer *colorbuffer = getColorbuffer();
|
||||
|
||||
if (!colorbuffer)
|
||||
{
|
||||
|
@ -302,8 +275,8 @@ GLenum Framebuffer::completeness()
|
|||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if ((colorbuffer->getType() == GL_FLOAT && !getContext()->supportsFloatRenderableTextures()) ||
|
||||
(colorbuffer->getType() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatRenderableTextures()))
|
||||
if ((dx2es::IsFloat32Format(colorbuffer->getD3DFormat()) && !getContext()->supportsFloat32RenderableTextures()) ||
|
||||
(dx2es::IsFloat16Format(colorbuffer->getD3DFormat()) && !getContext()->supportsFloat16RenderableTextures()))
|
||||
{
|
||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
}
|
||||
|
@ -324,8 +297,8 @@ GLenum Framebuffer::completeness()
|
|||
return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
|
||||
}
|
||||
|
||||
DepthStencilbuffer *depthbuffer = NULL;
|
||||
DepthStencilbuffer *stencilbuffer = NULL;
|
||||
Renderbuffer *depthbuffer = NULL;
|
||||
Renderbuffer *stencilbuffer = NULL;
|
||||
|
||||
if (mDepthbufferType != GL_NONE)
|
||||
{
|
||||
|
@ -418,17 +391,17 @@ GLenum Framebuffer::completeness()
|
|||
return GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil)
|
||||
DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
|
||||
{
|
||||
mColorbufferType = GL_RENDERBUFFER;
|
||||
mDepthbufferType = (depthStencil->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
|
||||
mStencilbufferType = (depthStencil->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
|
||||
|
||||
mColorbufferPointer.set(new Renderbuffer(0, color));
|
||||
mColorbufferPointer.set(new Renderbuffer(0, colorbuffer));
|
||||
|
||||
Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
|
||||
mDepthbufferPointer.set(depthStencilRenderbuffer);
|
||||
mStencilbufferPointer.set(depthStencilRenderbuffer);
|
||||
|
||||
mColorbufferType = GL_RENDERBUFFER;
|
||||
mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
|
||||
mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
|
||||
}
|
||||
|
||||
int Framebuffer::getSamples()
|
||||
|
|
|
@ -46,9 +46,9 @@ class Framebuffer
|
|||
unsigned int getDepthbufferSerial();
|
||||
unsigned int getStencilbufferSerial();
|
||||
|
||||
Colorbuffer *getColorbuffer();
|
||||
DepthStencilbuffer *getDepthbuffer();
|
||||
DepthStencilbuffer *getStencilbuffer();
|
||||
Renderbuffer *getColorbuffer();
|
||||
Renderbuffer *getDepthbuffer();
|
||||
Renderbuffer *getStencilbuffer();
|
||||
|
||||
GLenum getColorbufferType();
|
||||
GLenum getDepthbufferType();
|
||||
|
@ -82,7 +82,7 @@ class Framebuffer
|
|||
class DefaultFramebuffer : public Framebuffer
|
||||
{
|
||||
public:
|
||||
DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil);
|
||||
DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
|
||||
|
||||
virtual GLenum completeness();
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ std::string str(int i)
|
|||
Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize)
|
||||
: type(type), _name(_name), name(Program::undecorateUniform(_name)), arraySize(arraySize)
|
||||
{
|
||||
int bytes = UniformTypeSize(type) * arraySize;
|
||||
int bytes = UniformInternalSize(type) * arraySize;
|
||||
data = new unsigned char[bytes];
|
||||
memset(data, 0, bytes);
|
||||
dirty = true;
|
||||
|
@ -560,7 +560,7 @@ void transposeMatrix(T *target, const GLfloat *value)
|
|||
{
|
||||
for (int y = 0; y < copyHeight; y++)
|
||||
{
|
||||
target[x * targetWidth + y] = value[y * srcWidth + x];
|
||||
target[x * targetWidth + y] = (T)value[y * srcWidth + x];
|
||||
}
|
||||
}
|
||||
// clear unfilled right side
|
||||
|
@ -568,7 +568,7 @@ void transposeMatrix(T *target, const GLfloat *value)
|
|||
{
|
||||
for (int x = srcWidth; x < targetWidth; x++)
|
||||
{
|
||||
target[y * targetWidth + x] = 0;
|
||||
target[y * targetWidth + x] = (T)0;
|
||||
}
|
||||
}
|
||||
// clear unfilled bottom.
|
||||
|
@ -576,7 +576,7 @@ void transposeMatrix(T *target, const GLfloat *value)
|
|||
{
|
||||
for (int x = 0; x < targetWidth; x++)
|
||||
{
|
||||
target[y * targetWidth + x] = 0;
|
||||
target[y * targetWidth + x] = (T)0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -911,7 +911,7 @@ bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Program::getUniformfv(GLint location, GLfloat *params)
|
||||
bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
|
||||
{
|
||||
if (location < 0 || location >= (int)mUniformIndex.size())
|
||||
{
|
||||
|
@ -920,6 +920,16 @@ bool Program::getUniformfv(GLint location, GLfloat *params)
|
|||
|
||||
Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
|
||||
|
||||
// sized queries -- ensure the provided buffer is large enough
|
||||
if (bufSize)
|
||||
{
|
||||
int requiredBytes = UniformExternalSize(targetUniform->type);
|
||||
if (*bufSize < requiredBytes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (targetUniform->type)
|
||||
{
|
||||
case GL_FLOAT_MAT2:
|
||||
|
@ -933,7 +943,7 @@ bool Program::getUniformfv(GLint location, GLfloat *params)
|
|||
break;
|
||||
default:
|
||||
{
|
||||
unsigned int count = UniformComponentCount(targetUniform->type);
|
||||
unsigned int count = UniformExternalComponentCount(targetUniform->type);
|
||||
unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
|
||||
|
||||
switch (UniformComponentType(targetUniform->type))
|
||||
|
@ -970,7 +980,7 @@ bool Program::getUniformfv(GLint location, GLfloat *params)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Program::getUniformiv(GLint location, GLint *params)
|
||||
bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
|
||||
{
|
||||
if (location < 0 || location >= (int)mUniformIndex.size())
|
||||
{
|
||||
|
@ -979,6 +989,16 @@ bool Program::getUniformiv(GLint location, GLint *params)
|
|||
|
||||
Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
|
||||
|
||||
// sized queries -- ensure the provided buffer is large enough
|
||||
if (bufSize)
|
||||
{
|
||||
int requiredBytes = UniformExternalSize(targetUniform->type);
|
||||
if (*bufSize < requiredBytes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (targetUniform->type)
|
||||
{
|
||||
case GL_FLOAT_MAT2:
|
||||
|
@ -998,7 +1018,7 @@ bool Program::getUniformiv(GLint location, GLint *params)
|
|||
break;
|
||||
default:
|
||||
{
|
||||
unsigned int count = UniformComponentCount(targetUniform->type);
|
||||
unsigned int count = UniformExternalComponentCount(targetUniform->type);
|
||||
unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
|
||||
|
||||
switch (UniformComponentType(targetUniform->type))
|
||||
|
@ -1834,10 +1854,15 @@ bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT
|
|||
{
|
||||
if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
|
||||
{
|
||||
for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++)
|
||||
for (unsigned int i = 0; i < constantDescription.RegisterCount; i++)
|
||||
{
|
||||
if (mConstantTablePS->GetConstantByName(NULL, constantDescription.Name) != NULL)
|
||||
D3DXHANDLE psConstant = mConstantTablePS->GetConstantByName(NULL, constantDescription.Name);
|
||||
D3DXHANDLE vsConstant = mConstantTableVS->GetConstantByName(NULL, constantDescription.Name);
|
||||
|
||||
if (psConstant)
|
||||
{
|
||||
unsigned int samplerIndex = mConstantTablePS->GetSamplerIndex(psConstant) + i;
|
||||
|
||||
if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
|
||||
{
|
||||
mSamplersPS[samplerIndex].active = true;
|
||||
|
@ -1852,8 +1877,10 @@ bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT
|
|||
}
|
||||
}
|
||||
|
||||
if (mConstantTableVS->GetConstantByName(NULL, constantDescription.Name) != NULL)
|
||||
if (vsConstant)
|
||||
{
|
||||
unsigned int samplerIndex = mConstantTableVS->GetSamplerIndex(vsConstant) + i;
|
||||
|
||||
if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
|
||||
{
|
||||
mSamplersVS[samplerIndex].active = true;
|
||||
|
|
|
@ -98,8 +98,8 @@ class Program
|
|||
bool setUniform3iv(GLint location, GLsizei count, const GLint *v);
|
||||
bool setUniform4iv(GLint location, GLsizei count, const GLint *v);
|
||||
|
||||
bool getUniformfv(GLint location, GLfloat *params);
|
||||
bool getUniformiv(GLint location, GLint *params);
|
||||
bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params);
|
||||
bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params);
|
||||
|
||||
GLint getDxDepthRangeLocation() const;
|
||||
GLint getDxDepthLocation() const;
|
||||
|
|
|
@ -18,103 +18,175 @@ namespace gl
|
|||
{
|
||||
unsigned int RenderbufferStorage::mCurrentSerial = 1;
|
||||
|
||||
Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *storage) : RefCountObject(id)
|
||||
RenderbufferInterface::RenderbufferInterface()
|
||||
{
|
||||
ASSERT(storage != NULL);
|
||||
mStorage = storage;
|
||||
}
|
||||
|
||||
GLuint RenderbufferInterface::getRedSize() const
|
||||
{
|
||||
return dx2es::GetRedSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferInterface::getGreenSize() const
|
||||
{
|
||||
return dx2es::GetGreenSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferInterface::getBlueSize() const
|
||||
{
|
||||
return dx2es::GetBlueSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferInterface::getAlphaSize() const
|
||||
{
|
||||
return dx2es::GetAlphaSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferInterface::getDepthSize() const
|
||||
{
|
||||
return dx2es::GetDepthSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferInterface::getStencilSize() const
|
||||
{
|
||||
return dx2es::GetStencilSize(getD3DFormat());
|
||||
}
|
||||
|
||||
RenderbufferTexture::RenderbufferTexture(Texture *texture, GLenum target) : mTexture(texture), mTarget(target)
|
||||
{
|
||||
}
|
||||
|
||||
RenderbufferTexture::~RenderbufferTexture()
|
||||
{
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *RenderbufferTexture::getRenderTarget()
|
||||
{
|
||||
return mTexture->getRenderTarget(mTarget);
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *RenderbufferTexture::getDepthStencil()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GLsizei RenderbufferTexture::getWidth() const
|
||||
{
|
||||
return mTexture->getWidth();
|
||||
}
|
||||
|
||||
GLsizei RenderbufferTexture::getHeight() const
|
||||
{
|
||||
return mTexture->getHeight();
|
||||
}
|
||||
|
||||
GLenum RenderbufferTexture::getInternalFormat() const
|
||||
{
|
||||
return mTexture->getInternalFormat();
|
||||
}
|
||||
|
||||
D3DFORMAT RenderbufferTexture::getD3DFormat() const
|
||||
{
|
||||
return mTexture->getD3DFormat();
|
||||
}
|
||||
|
||||
GLsizei RenderbufferTexture::getSamples() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int RenderbufferTexture::getSerial() const
|
||||
{
|
||||
return mTexture->getRenderTargetSerial(mTarget);
|
||||
}
|
||||
|
||||
Renderbuffer::Renderbuffer(GLuint id, RenderbufferInterface *instance) : RefCountObject(id)
|
||||
{
|
||||
ASSERT(instance != NULL);
|
||||
mInstance = instance;
|
||||
}
|
||||
|
||||
Renderbuffer::~Renderbuffer()
|
||||
{
|
||||
delete mStorage;
|
||||
}
|
||||
|
||||
bool Renderbuffer::isColorbuffer() const
|
||||
{
|
||||
return mStorage->isColorbuffer();
|
||||
}
|
||||
|
||||
bool Renderbuffer::isDepthbuffer() const
|
||||
{
|
||||
return mStorage->isDepthbuffer();
|
||||
}
|
||||
|
||||
bool Renderbuffer::isStencilbuffer() const
|
||||
{
|
||||
return mStorage->isStencilbuffer();
|
||||
delete mInstance;
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *Renderbuffer::getRenderTarget()
|
||||
{
|
||||
return mStorage->getRenderTarget();
|
||||
return mInstance->getRenderTarget();
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *Renderbuffer::getDepthStencil()
|
||||
{
|
||||
return mStorage->getDepthStencil();
|
||||
return mInstance->getDepthStencil();
|
||||
}
|
||||
|
||||
GLsizei Renderbuffer::getWidth() const
|
||||
{
|
||||
return mStorage->getWidth();
|
||||
return mInstance->getWidth();
|
||||
}
|
||||
|
||||
GLsizei Renderbuffer::getHeight() const
|
||||
{
|
||||
return mStorage->getHeight();
|
||||
return mInstance->getHeight();
|
||||
}
|
||||
|
||||
GLenum Renderbuffer::getInternalFormat() const
|
||||
{
|
||||
return mStorage->getInternalFormat();
|
||||
return mInstance->getInternalFormat();
|
||||
}
|
||||
|
||||
D3DFORMAT Renderbuffer::getD3DFormat() const
|
||||
{
|
||||
return mInstance->getD3DFormat();
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::getRedSize() const
|
||||
{
|
||||
return mStorage->getRedSize();
|
||||
return mInstance->getRedSize();
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::getGreenSize() const
|
||||
{
|
||||
return mStorage->getGreenSize();
|
||||
return mInstance->getGreenSize();
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::getBlueSize() const
|
||||
{
|
||||
return mStorage->getBlueSize();
|
||||
return mInstance->getBlueSize();
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::getAlphaSize() const
|
||||
{
|
||||
return mStorage->getAlphaSize();
|
||||
return mInstance->getAlphaSize();
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::getDepthSize() const
|
||||
{
|
||||
return mStorage->getDepthSize();
|
||||
return mInstance->getDepthSize();
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::getStencilSize() const
|
||||
{
|
||||
return mStorage->getStencilSize();
|
||||
return mInstance->getStencilSize();
|
||||
}
|
||||
|
||||
GLsizei Renderbuffer::getSamples() const
|
||||
{
|
||||
return mStorage->getSamples();
|
||||
return mInstance->getSamples();
|
||||
}
|
||||
|
||||
unsigned int Renderbuffer::getSerial() const
|
||||
{
|
||||
return mStorage->getSerial();
|
||||
return mInstance->getSerial();
|
||||
}
|
||||
|
||||
void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
|
||||
{
|
||||
ASSERT(newStorage != NULL);
|
||||
|
||||
delete mStorage;
|
||||
mStorage = newStorage;
|
||||
delete mInstance;
|
||||
mInstance = newStorage;
|
||||
}
|
||||
|
||||
RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial())
|
||||
|
@ -130,21 +202,6 @@ RenderbufferStorage::~RenderbufferStorage()
|
|||
{
|
||||
}
|
||||
|
||||
bool RenderbufferStorage::isColorbuffer() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RenderbufferStorage::isDepthbuffer() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RenderbufferStorage::isStencilbuffer() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *RenderbufferStorage::getRenderTarget()
|
||||
{
|
||||
return NULL;
|
||||
|
@ -170,34 +227,9 @@ GLenum RenderbufferStorage::getInternalFormat() const
|
|||
return mInternalFormat;
|
||||
}
|
||||
|
||||
GLuint RenderbufferStorage::getRedSize() const
|
||||
D3DFORMAT RenderbufferStorage::getD3DFormat() const
|
||||
{
|
||||
return dx2es::GetRedSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferStorage::getGreenSize() const
|
||||
{
|
||||
return dx2es::GetGreenSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferStorage::getBlueSize() const
|
||||
{
|
||||
return dx2es::GetBlueSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferStorage::getAlphaSize() const
|
||||
{
|
||||
return dx2es::GetAlphaSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferStorage::getDepthSize() const
|
||||
{
|
||||
return dx2es::GetDepthSize(getD3DFormat());
|
||||
}
|
||||
|
||||
GLuint RenderbufferStorage::getStencilSize() const
|
||||
{
|
||||
return dx2es::GetStencilSize(getD3DFormat());
|
||||
return mD3DFormat;
|
||||
}
|
||||
|
||||
GLsizei RenderbufferStorage::getSamples() const
|
||||
|
@ -205,11 +237,6 @@ GLsizei RenderbufferStorage::getSamples() const
|
|||
return mSamples;
|
||||
}
|
||||
|
||||
D3DFORMAT RenderbufferStorage::getD3DFormat() const
|
||||
{
|
||||
return mD3DFormat;
|
||||
}
|
||||
|
||||
unsigned int RenderbufferStorage::getSerial() const
|
||||
{
|
||||
return mSerial;
|
||||
|
@ -220,7 +247,14 @@ unsigned int RenderbufferStorage::issueSerial()
|
|||
return mCurrentSerial++;
|
||||
}
|
||||
|
||||
Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget), mTexture(NULL)
|
||||
unsigned int RenderbufferStorage::issueCubeSerials()
|
||||
{
|
||||
unsigned int firstSerial = mCurrentSerial;
|
||||
mCurrentSerial += 6;
|
||||
return firstSerial;
|
||||
}
|
||||
|
||||
Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
|
||||
{
|
||||
if (renderTarget)
|
||||
{
|
||||
|
@ -237,21 +271,7 @@ Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(render
|
|||
}
|
||||
}
|
||||
|
||||
Colorbuffer::Colorbuffer(Texture *texture, GLenum target) : mRenderTarget(NULL), mTexture(texture), mTarget(target)
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
mWidth = texture->getWidth();
|
||||
mHeight = texture->getHeight();
|
||||
mInternalFormat = texture->getInternalFormat();
|
||||
mD3DFormat = texture->getD3DFormat();
|
||||
mSamples = 0;
|
||||
|
||||
mRenderTarget = texture->getRenderTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL), mTexture(NULL)
|
||||
Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
|
@ -295,71 +315,11 @@ Colorbuffer::~Colorbuffer()
|
|||
}
|
||||
}
|
||||
|
||||
GLsizei Colorbuffer::getWidth() const
|
||||
{
|
||||
if (mTexture)
|
||||
{
|
||||
return mTexture->getWidth();
|
||||
}
|
||||
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
GLsizei Colorbuffer::getHeight() const
|
||||
{
|
||||
if (mTexture)
|
||||
{
|
||||
return mTexture->getHeight();
|
||||
}
|
||||
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
GLenum Colorbuffer::getInternalFormat() const
|
||||
{
|
||||
if (mTexture)
|
||||
{
|
||||
return mTexture->getInternalFormat();
|
||||
}
|
||||
|
||||
return mInternalFormat;
|
||||
}
|
||||
|
||||
GLenum Colorbuffer::getType() const
|
||||
{
|
||||
if (mTexture)
|
||||
{
|
||||
return mTexture->getType();
|
||||
}
|
||||
|
||||
return GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
D3DFORMAT Colorbuffer::getD3DFormat() const
|
||||
{
|
||||
if (mTexture)
|
||||
{
|
||||
return mTexture->getD3DFormat();
|
||||
}
|
||||
|
||||
return mD3DFormat;
|
||||
}
|
||||
|
||||
bool Colorbuffer::isColorbuffer() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *Colorbuffer::getRenderTarget()
|
||||
{
|
||||
if (mTexture)
|
||||
if (mRenderTarget)
|
||||
{
|
||||
if (mRenderTarget)
|
||||
{
|
||||
mRenderTarget->Release();
|
||||
}
|
||||
|
||||
mRenderTarget = mTexture->getRenderTarget(mTarget);
|
||||
mRenderTarget->AddRef();
|
||||
}
|
||||
|
||||
return mRenderTarget;
|
||||
|
@ -427,16 +387,6 @@ DepthStencilbuffer::~DepthStencilbuffer()
|
|||
}
|
||||
}
|
||||
|
||||
bool DepthStencilbuffer::isDepthbuffer() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DepthStencilbuffer::isStencilbuffer() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
|
||||
{
|
||||
return mDepthStencil;
|
||||
|
@ -454,7 +404,7 @@ Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(d
|
|||
|
||||
Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
|
||||
{
|
||||
if (getDepthStencil())
|
||||
if (mDepthStencil)
|
||||
{
|
||||
mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
|
||||
// will expect one of the valid renderbuffer formats for use in
|
||||
|
@ -466,16 +416,6 @@ Depthbuffer::~Depthbuffer()
|
|||
{
|
||||
}
|
||||
|
||||
bool Depthbuffer::isDepthbuffer() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Depthbuffer::isStencilbuffer() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
|
||||
{
|
||||
if (depthStencil)
|
||||
|
@ -488,7 +428,7 @@ Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuff
|
|||
|
||||
Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
|
||||
{
|
||||
if (getDepthStencil())
|
||||
if (mDepthStencil)
|
||||
{
|
||||
mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
|
||||
// will expect one of the valid renderbuffer formats for use in
|
||||
|
@ -500,13 +440,4 @@ Stencilbuffer::~Stencilbuffer()
|
|||
{
|
||||
}
|
||||
|
||||
bool Stencilbuffer::isDepthbuffer() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Stencilbuffer::isStencilbuffer() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,38 +22,86 @@
|
|||
namespace gl
|
||||
{
|
||||
class Texture;
|
||||
class Colorbuffer;
|
||||
class DepthStencilbuffer;
|
||||
|
||||
class RenderbufferInterface
|
||||
{
|
||||
public:
|
||||
RenderbufferInterface();
|
||||
|
||||
virtual ~RenderbufferInterface() {};
|
||||
|
||||
virtual IDirect3DSurface9 *getRenderTarget() = 0;
|
||||
virtual IDirect3DSurface9 *getDepthStencil() = 0;
|
||||
|
||||
virtual GLsizei getWidth() const = 0;
|
||||
virtual GLsizei getHeight() const = 0;
|
||||
virtual GLenum getInternalFormat() const = 0;
|
||||
virtual D3DFORMAT getD3DFormat() const = 0;
|
||||
virtual GLsizei getSamples() const = 0;
|
||||
|
||||
GLuint getRedSize() const;
|
||||
GLuint getGreenSize() const;
|
||||
GLuint getBlueSize() const;
|
||||
GLuint getAlphaSize() const;
|
||||
GLuint getDepthSize() const;
|
||||
GLuint getStencilSize() const;
|
||||
|
||||
virtual unsigned int getSerial() const = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface);
|
||||
};
|
||||
|
||||
class RenderbufferTexture : public RenderbufferInterface
|
||||
{
|
||||
public:
|
||||
RenderbufferTexture(Texture *texture, GLenum target);
|
||||
|
||||
virtual ~RenderbufferTexture();
|
||||
|
||||
IDirect3DSurface9 *getRenderTarget();
|
||||
IDirect3DSurface9 *getDepthStencil();
|
||||
|
||||
virtual GLsizei getWidth() const;
|
||||
virtual GLsizei getHeight() const;
|
||||
virtual GLenum getInternalFormat() const;
|
||||
virtual D3DFORMAT getD3DFormat() const;
|
||||
virtual GLsizei getSamples() const;
|
||||
|
||||
virtual unsigned int getSerial() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture);
|
||||
|
||||
Texture *mTexture;
|
||||
GLenum mTarget;
|
||||
};
|
||||
|
||||
// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
|
||||
// is called. The specific concrete type depends on whether the internal format is
|
||||
// colour depth, stencil or packed depth/stencil.
|
||||
class RenderbufferStorage
|
||||
class RenderbufferStorage : public RenderbufferInterface
|
||||
{
|
||||
public:
|
||||
RenderbufferStorage();
|
||||
|
||||
virtual ~RenderbufferStorage() = 0;
|
||||
|
||||
virtual bool isColorbuffer() const;
|
||||
virtual bool isDepthbuffer() const;
|
||||
virtual bool isStencilbuffer() const;
|
||||
|
||||
virtual IDirect3DSurface9 *getRenderTarget();
|
||||
virtual IDirect3DSurface9 *getDepthStencil();
|
||||
|
||||
virtual GLsizei getWidth() const;
|
||||
virtual GLsizei getHeight() const;
|
||||
virtual GLenum getInternalFormat() const;
|
||||
GLuint getRedSize() const;
|
||||
GLuint getGreenSize() const;
|
||||
GLuint getBlueSize() const;
|
||||
GLuint getAlphaSize() const;
|
||||
GLuint getDepthSize() const;
|
||||
GLuint getStencilSize() const;
|
||||
virtual D3DFORMAT getD3DFormat() const;
|
||||
virtual GLsizei getSamples() const;
|
||||
|
||||
virtual D3DFORMAT getD3DFormat() const;
|
||||
virtual unsigned int getSerial() const;
|
||||
|
||||
unsigned int getSerial() const;
|
||||
static unsigned int issueSerial();
|
||||
static unsigned int issueCubeSerials();
|
||||
|
||||
protected:
|
||||
GLsizei mWidth;
|
||||
|
@ -65,26 +113,20 @@ class RenderbufferStorage
|
|||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
|
||||
|
||||
static unsigned int issueSerial();
|
||||
|
||||
const unsigned int mSerial;
|
||||
|
||||
static unsigned int mCurrentSerial;
|
||||
};
|
||||
|
||||
// Renderbuffer implements the GL renderbuffer object.
|
||||
// It's only a proxy for a RenderbufferStorage instance; the internal object
|
||||
// It's only a proxy for a RenderbufferInterface instance; the internal object
|
||||
// can change whenever glRenderbufferStorage is called.
|
||||
class Renderbuffer : public RefCountObject
|
||||
{
|
||||
public:
|
||||
Renderbuffer(GLuint id, RenderbufferStorage *storage);
|
||||
Renderbuffer(GLuint id, RenderbufferInterface *storage);
|
||||
|
||||
~Renderbuffer();
|
||||
|
||||
bool isColorbuffer() const;
|
||||
bool isDepthbuffer() const;
|
||||
bool isStencilbuffer() const;
|
||||
virtual ~Renderbuffer();
|
||||
|
||||
IDirect3DSurface9 *getRenderTarget();
|
||||
IDirect3DSurface9 *getDepthStencil();
|
||||
|
@ -104,40 +146,27 @@ class Renderbuffer : public RefCountObject
|
|||
unsigned int getSerial() const;
|
||||
|
||||
void setStorage(RenderbufferStorage *newStorage);
|
||||
RenderbufferStorage *getStorage() { return mStorage; }
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
|
||||
|
||||
RenderbufferStorage *mStorage;
|
||||
RenderbufferInterface *mInstance;
|
||||
};
|
||||
|
||||
class Colorbuffer : public RenderbufferStorage
|
||||
{
|
||||
public:
|
||||
explicit Colorbuffer(IDirect3DSurface9 *renderTarget);
|
||||
Colorbuffer(Texture *texture, GLenum target);
|
||||
Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples);
|
||||
|
||||
virtual ~Colorbuffer();
|
||||
|
||||
virtual bool isColorbuffer() const;
|
||||
|
||||
virtual IDirect3DSurface9 *getRenderTarget();
|
||||
|
||||
virtual GLsizei getWidth() const;
|
||||
virtual GLsizei getHeight() const;
|
||||
virtual GLenum getInternalFormat() const;
|
||||
virtual GLenum getType() const;
|
||||
|
||||
virtual D3DFORMAT getD3DFormat() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
|
||||
|
||||
IDirect3DSurface9 *mRenderTarget;
|
||||
Texture *mTexture;
|
||||
GLenum mTarget;
|
||||
};
|
||||
|
||||
class DepthStencilbuffer : public RenderbufferStorage
|
||||
|
@ -148,14 +177,13 @@ class DepthStencilbuffer : public RenderbufferStorage
|
|||
|
||||
~DepthStencilbuffer();
|
||||
|
||||
virtual bool isDepthbuffer() const;
|
||||
virtual bool isStencilbuffer() const;
|
||||
|
||||
virtual IDirect3DSurface9 *getDepthStencil();
|
||||
|
||||
protected:
|
||||
IDirect3DSurface9 *mDepthStencil;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
|
||||
IDirect3DSurface9 *mDepthStencil;
|
||||
};
|
||||
|
||||
class Depthbuffer : public DepthStencilbuffer
|
||||
|
@ -166,9 +194,6 @@ class Depthbuffer : public DepthStencilbuffer
|
|||
|
||||
virtual ~Depthbuffer();
|
||||
|
||||
virtual bool isDepthbuffer() const;
|
||||
virtual bool isStencilbuffer() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
|
||||
};
|
||||
|
@ -181,9 +206,6 @@ class Stencilbuffer : public DepthStencilbuffer
|
|||
|
||||
virtual ~Stencilbuffer();
|
||||
|
||||
virtual bool isDepthbuffer() const;
|
||||
virtual bool isStencilbuffer() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
|
||||
};
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -43,6 +43,126 @@ enum
|
|||
IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE
|
||||
};
|
||||
|
||||
class Image
|
||||
{
|
||||
public:
|
||||
Image();
|
||||
~Image();
|
||||
|
||||
bool redefine(GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRelease);
|
||||
void markDirty() {mDirty = true;}
|
||||
void markClean() {mDirty = false;}
|
||||
|
||||
HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
|
||||
void unlock();
|
||||
|
||||
bool isRenderable() const;
|
||||
D3DFORMAT getD3DFormat() const;
|
||||
|
||||
GLsizei getWidth() const {return mWidth;}
|
||||
GLsizei getHeight() const {return mHeight;}
|
||||
GLenum getFormat() const {return mFormat;}
|
||||
GLenum getType() const {return mType;}
|
||||
bool isDirty() const {return mSurface && mDirty;}
|
||||
IDirect3DSurface9 *getSurface();
|
||||
|
||||
void setManagedSurface(IDirect3DSurface9 *surface);
|
||||
void updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
|
||||
|
||||
void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum type,
|
||||
GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output) const;
|
||||
|
||||
void loadAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadLuminanceData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
|
||||
void loadLuminanceFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadLuminanceHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadLuminanceAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
|
||||
void loadLuminanceAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadLuminanceAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGB565Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBAUByteDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBAUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBA4444Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBA5551Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBAFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBAHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadBGRAData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadDXT1Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadDXT3Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadDXT5Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
|
||||
void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Image);
|
||||
|
||||
void createSurface();
|
||||
|
||||
GLsizei mWidth;
|
||||
GLsizei mHeight;
|
||||
GLenum mFormat;
|
||||
GLenum mType;
|
||||
|
||||
bool mDirty;
|
||||
bool mManaged;
|
||||
|
||||
IDirect3DSurface9 *mSurface;
|
||||
};
|
||||
|
||||
class TextureStorage
|
||||
{
|
||||
public:
|
||||
explicit TextureStorage(bool renderable);
|
||||
|
||||
virtual ~TextureStorage();
|
||||
|
||||
bool isRenderable() const;
|
||||
bool isManaged() const;
|
||||
unsigned int getTextureSerial() const;
|
||||
virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TextureStorage);
|
||||
|
||||
const bool mRenderable;
|
||||
const bool mManaged;
|
||||
|
||||
const unsigned int mTextureSerial;
|
||||
static unsigned int issueTextureSerial();
|
||||
|
||||
static unsigned int mCurrentTextureSerial;
|
||||
};
|
||||
|
||||
class Texture : public RefCountObject
|
||||
{
|
||||
public:
|
||||
|
@ -56,11 +176,13 @@ class Texture : public RefCountObject
|
|||
bool setMagFilter(GLenum filter);
|
||||
bool setWrapS(GLenum wrap);
|
||||
bool setWrapT(GLenum wrap);
|
||||
bool setUsage(GLenum usage);
|
||||
|
||||
GLenum getMinFilter() const;
|
||||
GLenum getMagFilter() const;
|
||||
GLenum getWrapS() const;
|
||||
GLenum getWrapT() const;
|
||||
GLenum getUsage() const;
|
||||
|
||||
virtual GLsizei getWidth() const = 0;
|
||||
virtual GLsizei getHeight() const = 0;
|
||||
|
@ -68,7 +190,7 @@ class Texture : public RefCountObject
|
|||
virtual GLenum getType() const = 0;
|
||||
virtual D3DFORMAT getD3DFormat() const = 0;
|
||||
|
||||
virtual bool isComplete() const = 0;
|
||||
virtual bool isSamplerComplete() const = 0;
|
||||
virtual bool isCompressed() const = 0;
|
||||
|
||||
IDirect3DBaseTexture9 *getTexture();
|
||||
|
@ -77,43 +199,26 @@ class Texture : public RefCountObject
|
|||
virtual void generateMipmaps() = 0;
|
||||
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;
|
||||
|
||||
bool isDirtyParameter() const;
|
||||
bool isDirtyImage() const;
|
||||
bool hasDirtyParameters() const;
|
||||
bool hasDirtyImages() const;
|
||||
void resetDirty();
|
||||
unsigned int getSerial() const;
|
||||
unsigned int getTextureSerial() const;
|
||||
unsigned int getRenderTargetSerial(GLenum target) const;
|
||||
|
||||
bool isImmutable() const;
|
||||
|
||||
static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
|
||||
|
||||
protected:
|
||||
friend class Colorbuffer;
|
||||
|
||||
// Helper structure representing a single image layer
|
||||
struct Image
|
||||
{
|
||||
Image();
|
||||
~Image();
|
||||
|
||||
bool isRenderable() const;
|
||||
D3DFORMAT getD3DFormat() const;
|
||||
|
||||
GLsizei width;
|
||||
GLsizei height;
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
|
||||
bool dirty;
|
||||
|
||||
IDirect3DSurface9 *surface;
|
||||
};
|
||||
friend class RenderbufferTexture;
|
||||
|
||||
void setImage(GLint unpackAlignment, const void *pixels, Image *image);
|
||||
bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image);
|
||||
void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
|
||||
bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image);
|
||||
void copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
|
||||
|
||||
GLint creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const;
|
||||
GLint creationLevels(GLsizei size, GLint maxlevel) const;
|
||||
GLint creationLevels(GLsizei width, GLsizei height) const;
|
||||
GLint creationLevels(GLsizei size) const;
|
||||
|
||||
virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
|
||||
virtual void createTexture() = 0;
|
||||
|
@ -121,82 +226,46 @@ class Texture : public RefCountObject
|
|||
virtual void convertToRenderTarget() = 0;
|
||||
virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0;
|
||||
|
||||
void createSurface(Image *image);
|
||||
|
||||
Blit *getBlitter();
|
||||
|
||||
int levelCount() const;
|
||||
|
||||
static Blit *getBlitter();
|
||||
static bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
|
||||
|
||||
GLenum mMinFilter;
|
||||
GLenum mMagFilter;
|
||||
GLenum mWrapS;
|
||||
GLenum mWrapT;
|
||||
bool mDirtyParameter;
|
||||
bool mDirtyParameters;
|
||||
GLenum mUsage;
|
||||
|
||||
bool mDirtyImage;
|
||||
bool mDirtyImages;
|
||||
|
||||
bool mIsRenderable;
|
||||
bool mImmutable;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Texture);
|
||||
|
||||
void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
|
||||
GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output, D3DSURFACE_DESC *description) const;
|
||||
virtual TextureStorage *getStorage() const = 0;
|
||||
};
|
||||
|
||||
void loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
|
||||
void loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
|
||||
void loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBAUByteImageDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadDXT1ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadDXT3ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
void loadDXT5ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
int inputPitch, const void *input, size_t outputPitch, void *output) const;
|
||||
class TextureStorage2D : public TextureStorage
|
||||
{
|
||||
public:
|
||||
explicit TextureStorage2D(IDirect3DTexture9 *surfaceTexture);
|
||||
TextureStorage2D(int levels, D3DFORMAT format, int width, int height, bool renderable);
|
||||
|
||||
static unsigned int issueSerial();
|
||||
virtual ~TextureStorage2D();
|
||||
|
||||
const unsigned int mSerial;
|
||||
IDirect3DSurface9 *getSurfaceLevel(int level);
|
||||
IDirect3DBaseTexture9 *getBaseTexture() const;
|
||||
|
||||
static unsigned int mCurrentSerial;
|
||||
virtual unsigned int getRenderTargetSerial(GLenum target) const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TextureStorage2D);
|
||||
|
||||
IDirect3DTexture9 *mTexture;
|
||||
const unsigned int mRenderTargetSerial;
|
||||
};
|
||||
|
||||
class Texture2D : public Texture
|
||||
|
@ -219,9 +288,10 @@ class Texture2D : public Texture
|
|||
void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
|
||||
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
|
||||
void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
|
||||
void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
|
||||
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
|
||||
void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
|
||||
virtual bool isComplete() const;
|
||||
virtual bool isSamplerComplete() const;
|
||||
virtual bool isCompressed() const;
|
||||
virtual void bindTexImage(egl::Surface *surface);
|
||||
virtual void releaseTexImage();
|
||||
|
@ -238,18 +308,40 @@ class Texture2D : public Texture
|
|||
virtual void updateTexture();
|
||||
virtual void convertToRenderTarget();
|
||||
virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
|
||||
virtual TextureStorage *getStorage() const;
|
||||
|
||||
void redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool force);
|
||||
bool isMipmapComplete() const;
|
||||
|
||||
void redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
|
||||
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
|
||||
|
||||
Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
|
||||
|
||||
IDirect3DTexture9 *mTexture;
|
||||
TextureStorage2D *mTexture;
|
||||
egl::Surface *mSurface;
|
||||
|
||||
BindingPointer<Renderbuffer> mColorbufferProxy;
|
||||
};
|
||||
|
||||
class TextureStorageCubeMap : public TextureStorage
|
||||
{
|
||||
public:
|
||||
TextureStorageCubeMap(int levels, D3DFORMAT format, int size, bool renderable);
|
||||
|
||||
virtual ~TextureStorageCubeMap();
|
||||
|
||||
IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level);
|
||||
IDirect3DBaseTexture9 *getBaseTexture() const;
|
||||
|
||||
virtual unsigned int getRenderTargetSerial(GLenum target) const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TextureStorageCubeMap);
|
||||
|
||||
IDirect3DCubeTexture9 *mTexture;
|
||||
const unsigned int mFirstRenderTargetSerial;
|
||||
};
|
||||
|
||||
class TextureCubeMap : public Texture
|
||||
{
|
||||
public:
|
||||
|
@ -278,14 +370,17 @@ class TextureCubeMap : public Texture
|
|||
void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
|
||||
void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
|
||||
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
|
||||
void storage(GLsizei levels, GLenum internalformat, GLsizei size);
|
||||
|
||||
virtual bool isComplete() const;
|
||||
virtual bool isSamplerComplete() const;
|
||||
virtual bool isCompressed() const;
|
||||
|
||||
virtual void generateMipmaps();
|
||||
|
||||
virtual Renderbuffer *getRenderbuffer(GLenum target);
|
||||
|
||||
static unsigned int faceIndex(GLenum face);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
|
||||
|
||||
|
@ -294,22 +389,18 @@ class TextureCubeMap : public Texture
|
|||
virtual void updateTexture();
|
||||
virtual void convertToRenderTarget();
|
||||
virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
|
||||
|
||||
// face is one of the GL_TEXTURE_CUBE_MAP_* enumerants.
|
||||
// Returns NULL if the call underlying Direct3D call fails.
|
||||
IDirect3DSurface9 *getCubeMapSurface(GLenum face, unsigned int level);
|
||||
|
||||
static unsigned int faceIndex(GLenum face);
|
||||
virtual TextureStorage *getStorage() const;
|
||||
|
||||
bool isCubeComplete() const;
|
||||
bool isMipmapCubeComplete() const;
|
||||
|
||||
void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
|
||||
void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
|
||||
void redefineTexture(int faceIndex, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
|
||||
void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
|
||||
void redefineImage(int faceIndex, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
|
||||
|
||||
Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];
|
||||
|
||||
IDirect3DCubeTexture9 *mTexture;
|
||||
TextureStorageCubeMap *mTexture;
|
||||
|
||||
BindingPointer<Renderbuffer> mFaceProxies[6];
|
||||
};
|
||||
|
|
|
@ -29,6 +29,12 @@ namespace gl
|
|||
{
|
||||
unsigned int VertexBuffer::mCurrentSerial = 1;
|
||||
|
||||
int elementsInBuffer(const VertexAttribute &attribute, int size)
|
||||
{
|
||||
int stride = attribute.stride();
|
||||
return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
|
||||
}
|
||||
|
||||
VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device)
|
||||
{
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
|
@ -137,7 +143,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
|
|||
{
|
||||
if (staticBuffer->size() == 0)
|
||||
{
|
||||
int totalCount = buffer->size() / attribs[i].stride();
|
||||
int totalCount = elementsInBuffer(attribs[i], buffer->size());
|
||||
staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount));
|
||||
}
|
||||
else if (staticBuffer->lookupAttribute(attribs[i]) == -1)
|
||||
|
@ -216,7 +222,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
|
|||
if (streamOffset == -1)
|
||||
{
|
||||
// Convert the entire buffer
|
||||
int totalCount = buffer->size() / attribs[i].stride();
|
||||
int totalCount = elementsInBuffer(attribs[i], buffer->size());
|
||||
int startIndex = attribs[i].mOffset / attribs[i].stride();
|
||||
|
||||
streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i]);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -155,6 +155,11 @@ EXPORTS
|
|||
glSetFenceNV @156
|
||||
glTestFenceNV @157
|
||||
glGetTranslatedShaderSourceANGLE @159
|
||||
glTexStorage2DEXT @160
|
||||
glGetGraphicsResetStatusEXT @161
|
||||
glReadnPixelsEXT @162
|
||||
glGetnUniformfvEXT @163
|
||||
glGetnUniformivEXT @164
|
||||
|
||||
; EGL dependencies
|
||||
glCreateContext @144 NONAME
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
// main.cpp: DLL entry point and management of thread-local data.
|
||||
|
||||
#include "libGLESv2/main.h"
|
||||
#include "libGLESv2/utilities.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "libEGL/Surface.h"
|
||||
|
@ -93,6 +94,16 @@ Context *getContext()
|
|||
return current->context;
|
||||
}
|
||||
|
||||
Context *getNonLostContext()
|
||||
{
|
||||
Context *context = getContext();
|
||||
|
||||
if (context && !context->isContextLost())
|
||||
return context;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
egl::Display *getDisplay()
|
||||
{
|
||||
Current *current = (Current*)TlsGetValue(currentTLS);
|
||||
|
@ -106,6 +117,19 @@ IDirect3DDevice9 *getDevice()
|
|||
|
||||
return display->getDevice();
|
||||
}
|
||||
|
||||
bool checkDeviceLost(HRESULT errorCode)
|
||||
{
|
||||
egl::Display *display = NULL;
|
||||
|
||||
if (isDeviceLostError(errorCode))
|
||||
{
|
||||
display = gl::getDisplay();
|
||||
display->notifyDeviceLost();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Records an error code
|
||||
|
|
|
@ -29,9 +29,12 @@ struct Current
|
|||
void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface);
|
||||
|
||||
Context *getContext();
|
||||
Context *getNonLostContext();
|
||||
egl::Display *getDisplay();
|
||||
|
||||
IDirect3DDevice9 *getDevice();
|
||||
|
||||
bool checkDeviceLost(HRESULT errorCode);
|
||||
}
|
||||
|
||||
void error(GLenum errorCode);
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
namespace gl
|
||||
{
|
||||
|
||||
int UniformComponentCount(GLenum type)
|
||||
// This is how much data the application expects for a uniform
|
||||
int UniformExternalComponentCount(GLenum type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
@ -125,7 +126,7 @@ size_t UniformComponentSize(GLenum type)
|
|||
{
|
||||
switch(type)
|
||||
{
|
||||
case GL_BOOL: return sizeof(GLboolean);
|
||||
case GL_BOOL: return sizeof(GLint);
|
||||
case GL_FLOAT: return sizeof(GLfloat);
|
||||
case GL_INT: return sizeof(GLint);
|
||||
default: UNREACHABLE();
|
||||
|
@ -134,11 +135,16 @@ size_t UniformComponentSize(GLenum type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t UniformTypeSize(GLenum type)
|
||||
size_t UniformInternalSize(GLenum type)
|
||||
{
|
||||
return UniformComponentSize(UniformComponentType(type)) * UniformInternalComponentCount(type);
|
||||
}
|
||||
|
||||
size_t UniformExternalSize(GLenum type)
|
||||
{
|
||||
return UniformComponentSize(UniformComponentType(type)) * UniformExternalComponentCount(type);
|
||||
}
|
||||
|
||||
int VariableRowCount(GLenum type)
|
||||
{
|
||||
switch (type)
|
||||
|
@ -374,6 +380,68 @@ bool CheckTextureFormatType(GLenum format, GLenum type)
|
|||
}
|
||||
}
|
||||
|
||||
GLenum ExtractFormat(GLenum internalformat)
|
||||
{
|
||||
switch (internalformat)
|
||||
{
|
||||
case GL_RGB565: return GL_RGB;
|
||||
case GL_RGBA4: return GL_RGBA;
|
||||
case GL_RGB5_A1: return GL_RGBA;
|
||||
case GL_RGB8_OES: return GL_RGB;
|
||||
case GL_RGBA8_OES: return GL_RGBA;
|
||||
case GL_LUMINANCE8_ALPHA8_EXT: return GL_LUMINANCE_ALPHA;
|
||||
case GL_LUMINANCE8_EXT: return GL_LUMINANCE;
|
||||
case GL_ALPHA8_EXT: return GL_ALPHA;
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
|
||||
case GL_RGBA32F_EXT: return GL_RGBA;
|
||||
case GL_RGB32F_EXT: return GL_RGB;
|
||||
case GL_ALPHA32F_EXT: return GL_ALPHA;
|
||||
case GL_LUMINANCE32F_EXT: return GL_LUMINANCE;
|
||||
case GL_LUMINANCE_ALPHA32F_EXT: return GL_LUMINANCE_ALPHA;
|
||||
case GL_RGBA16F_EXT: return GL_RGBA;
|
||||
case GL_RGB16F_EXT: return GL_RGB;
|
||||
case GL_ALPHA16F_EXT: return GL_ALPHA;
|
||||
case GL_LUMINANCE16F_EXT: return GL_LUMINANCE;
|
||||
case GL_LUMINANCE_ALPHA16F_EXT: return GL_LUMINANCE_ALPHA;
|
||||
case GL_BGRA8_EXT: return GL_BGRA_EXT;
|
||||
default: return GL_NONE; // Unsupported
|
||||
}
|
||||
}
|
||||
|
||||
GLenum ExtractType(GLenum internalformat)
|
||||
{
|
||||
switch (internalformat)
|
||||
{
|
||||
case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
|
||||
case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
case GL_RGB8_OES: return GL_UNSIGNED_BYTE;
|
||||
case GL_RGBA8_OES: return GL_UNSIGNED_BYTE;
|
||||
case GL_LUMINANCE8_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
|
||||
case GL_LUMINANCE8_EXT: return GL_UNSIGNED_BYTE;
|
||||
case GL_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
|
||||
case GL_RGBA32F_EXT: return GL_FLOAT;
|
||||
case GL_RGB32F_EXT: return GL_FLOAT;
|
||||
case GL_ALPHA32F_EXT: return GL_FLOAT;
|
||||
case GL_LUMINANCE32F_EXT: return GL_FLOAT;
|
||||
case GL_LUMINANCE_ALPHA32F_EXT: return GL_FLOAT;
|
||||
case GL_RGBA16F_EXT: return GL_HALF_FLOAT_OES;
|
||||
case GL_RGB16F_EXT: return GL_HALF_FLOAT_OES;
|
||||
case GL_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
|
||||
case GL_LUMINANCE16F_EXT: return GL_HALF_FLOAT_OES;
|
||||
case GL_LUMINANCE_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
|
||||
case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE;
|
||||
default: return GL_NONE; // Unsupported
|
||||
}
|
||||
}
|
||||
|
||||
bool IsColorRenderable(GLenum internalformat)
|
||||
{
|
||||
switch (internalformat)
|
||||
|
@ -853,6 +921,50 @@ unsigned int GetDepthSize(D3DFORMAT depthFormat)
|
|||
}
|
||||
}
|
||||
|
||||
bool IsFloat32Format(D3DFORMAT surfaceFormat)
|
||||
{
|
||||
switch(surfaceFormat)
|
||||
{
|
||||
case D3DFMT_R16F:
|
||||
case D3DFMT_G16R16F:
|
||||
case D3DFMT_A16B16G16R16F:
|
||||
return false;
|
||||
case D3DFMT_R32F:
|
||||
case D3DFMT_G32R32F:
|
||||
case D3DFMT_A32B32G32R32F:
|
||||
return true;
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_X8R8G8B8:
|
||||
case D3DFMT_A1R5G5B5:
|
||||
case D3DFMT_R5G6B5:
|
||||
return false;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsFloat16Format(D3DFORMAT surfaceFormat)
|
||||
{
|
||||
switch(surfaceFormat)
|
||||
{
|
||||
case D3DFMT_R16F:
|
||||
case D3DFMT_G16R16F:
|
||||
case D3DFMT_A16B16G16R16F:
|
||||
return true;
|
||||
case D3DFMT_R32F:
|
||||
case D3DFMT_G32R32F:
|
||||
case D3DFMT_A32B32G32R32F:
|
||||
return false;
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_X8R8G8B8:
|
||||
case D3DFMT_A1R5G5B5:
|
||||
case D3DFMT_R5G6B5:
|
||||
return false;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
|
||||
{
|
||||
if (type == D3DMULTISAMPLE_NONMASKABLE)
|
||||
|
|
|
@ -21,10 +21,11 @@ namespace gl
|
|||
|
||||
struct Color;
|
||||
|
||||
int UniformComponentCount(GLenum type);
|
||||
int UniformExternalComponentCount(GLenum type);
|
||||
int UniformInternalComponentCount(GLenum type);
|
||||
GLenum UniformComponentType(GLenum type);
|
||||
size_t UniformTypeSize(GLenum type);
|
||||
size_t UniformInternalSize(GLenum type);
|
||||
size_t UniformExternalSize(GLenum type);
|
||||
int VariableRowCount(GLenum type);
|
||||
int VariableColumnCount(GLenum type);
|
||||
|
||||
|
@ -38,6 +39,8 @@ bool IsCompressed(GLenum format);
|
|||
bool IsCubemapTextureTarget(GLenum target);
|
||||
bool IsTextureTarget(GLenum target);
|
||||
bool CheckTextureFormatType(GLenum format, GLenum type);
|
||||
GLenum ExtractFormat(GLenum internalformat);
|
||||
GLenum ExtractType(GLenum internalformat);
|
||||
|
||||
bool IsColorRenderable(GLenum internalformat);
|
||||
bool IsDepthRenderable(GLenum internalformat);
|
||||
|
@ -74,6 +77,8 @@ GLuint GetGreenSize(D3DFORMAT colorFormat);
|
|||
GLuint GetBlueSize(D3DFORMAT colorFormat);
|
||||
GLuint GetDepthSize(D3DFORMAT depthFormat);
|
||||
GLuint GetStencilSize(D3DFORMAT stencilFormat);
|
||||
bool IsFloat32Format(D3DFORMAT surfaceFormat);
|
||||
bool IsFloat16Format(D3DFORMAT surfaceFormat);
|
||||
|
||||
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
|
||||
|
||||
|
@ -85,4 +90,18 @@ GLenum ConvertDepthStencilFormat(D3DFORMAT format);
|
|||
std::string getTempPath();
|
||||
void writeFile(const char* path, const void* data, size_t size);
|
||||
|
||||
inline bool isDeviceLostError(HRESULT errorCode)
|
||||
{
|
||||
switch (errorCode)
|
||||
{
|
||||
case D3DERR_DRIVERINTERNALERROR:
|
||||
case D3DERR_DEVICELOST:
|
||||
case D3DERR_DEVICEHUNG:
|
||||
case D3DERR_DEVICEREMOVED:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LIBGLESV2_UTILITIES_H
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче