diff options
Diffstat (limited to 'mesalib')
26 files changed, 2006 insertions, 3080 deletions
diff --git a/mesalib/scons/mslib_sa.py b/mesalib/scons/mslib_sa.py deleted file mode 100644 index d7957f705..000000000 --- a/mesalib/scons/mslib_sa.py +++ /dev/null @@ -1,137 +0,0 @@ -"""mslib_sa
-
-Tool-specific initialization for lib (MicroSoft library archiver).
-
-Based on SCons.Tool.mslib, without the MSVC detection.
-
-"""
-
-#
-# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-import os
-import tempfile
-import string
-
-import SCons.Defaults
-import SCons.Tool
-import SCons.Util
-import SCons.Errors
-
-class TempFileMunge:
- """Same as SCons.Platform.TempFileMunge, but preserves LINK /LIB
- together."""
-
- def __init__(self, cmd):
- self.cmd = cmd
-
- def __call__(self, target, source, env, for_signature):
- if for_signature:
- return self.cmd
- cmd = env.subst_list(self.cmd, 0, target, source)[0]
- try:
- maxline = int(env.subst('$MAXLINELENGTH'))
- except ValueError:
- maxline = 2048
-
- if (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= maxline:
- return self.cmd
-
- # We do a normpath because mktemp() has what appears to be
- # a bug in Windows that will use a forward slash as a path
- # delimiter. Windows's link mistakes that for a command line
- # switch and barfs.
- #
- # We use the .lnk suffix for the benefit of the Phar Lap
- # linkloc linker, which likes to append an .lnk suffix if
- # none is given.
- tmp = os.path.normpath(tempfile.mktemp('.lnk'))
- native_tmp = SCons.Util.get_native_path(tmp)
-
- if env['SHELL'] and env['SHELL'] == 'sh':
- # The sh shell will try to escape the backslashes in the
- # path, so unescape them.
- native_tmp = string.replace(native_tmp, '\\', r'\\\\')
- # In Cygwin, we want to use rm to delete the temporary
- # file, because del does not exist in the sh shell.
- rm = env.Detect('rm') or 'del'
- else:
- # Don't use 'rm' if the shell is not sh, because rm won't
- # work with the Windows shells (cmd.exe or command.com) or
- # Windows path names.
- rm = 'del'
-
- prefix = env.subst('$TEMPFILEPREFIX')
- if not prefix:
- prefix = '@'
-
- if cmd[0:2] == ['link', '/lib']:
- split = 2
- else:
- split = 1
-
- args = map(SCons.Subst.quote_spaces, cmd[split:])
- open(tmp, 'w').write(string.join(args, " ") + "\n")
- # XXX Using the SCons.Action.print_actions value directly
- # like this is bogus, but expedient. This class should
- # really be rewritten as an Action that defines the
- # __call__() and strfunction() methods and lets the
- # normal action-execution logic handle whether or not to
- # print/execute the action. The problem, though, is all
- # of that is decided before we execute this method as
- # part of expanding the $TEMPFILE construction variable.
- # Consequently, refactoring this will have to wait until
- # we get more flexible with allowing Actions to exist
- # independently and get strung together arbitrarily like
- # Ant tasks. In the meantime, it's going to be more
- # user-friendly to not let obsession with architectural
- # purity get in the way of just being helpful, so we'll
- # reach into SCons.Action directly.
- if SCons.Action.print_actions:
- print("Using tempfile "+native_tmp+" for command line:\n"+
- " ".join(map(str,cmd)))
- return cmd[:split] + [ prefix + native_tmp + '\n' + rm, native_tmp ]
-
-def generate(env):
- """Add Builders and construction variables for lib to an Environment."""
- SCons.Tool.createStaticLibBuilder(env)
-
- if env.Detect('lib'):
- env['AR'] = 'lib'
- else:
- # Recent WINDDK versions do not ship with lib.
- env['AR'] = 'link /lib'
- env['TEMPFILE'] = TempFileMunge
- env['ARFLAGS'] = SCons.Util.CLVar('/nologo')
- env['ARCOM'] = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
- env['LIBPREFIX'] = ''
- env['LIBSUFFIX'] = '.lib'
-
-def exists(env):
- return env.Detect('lib') or env.Detect('link')
-
-# Local Variables:
-# tab-width:4
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/mesalib/scons/mslink_sa.py b/mesalib/scons/mslink_sa.py deleted file mode 100644 index a0cfde33e..000000000 --- a/mesalib/scons/mslink_sa.py +++ /dev/null @@ -1,246 +0,0 @@ -"""mslink_sa
-
-Tool-specific initialization for the Microsoft linker.
-
-Based on SCons.Tool.mslink, without the MSVS detection.
-
-"""
-
-#
-# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-import os.path
-
-import SCons.Action
-import SCons.Defaults
-import SCons.Errors
-import SCons.Platform.win32
-import SCons.Tool
-import SCons.Tool.msvc
-import SCons.Util
-
-def pdbGenerator(env, target, source, for_signature):
- try:
- return ['/PDB:%s' % target[0].attributes.pdb, '/DEBUG']
- except (AttributeError, IndexError):
- return None
-
-def _dllTargets(target, source, env, for_signature, paramtp):
- listCmd = []
- dll = env.FindIxes(target, '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp)
- if dll: listCmd.append("/out:%s"%dll.get_string(for_signature))
-
- implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
- if implib: listCmd.append("/implib:%s"%implib.get_string(for_signature))
-
- return listCmd
-
-def _dllSources(target, source, env, for_signature, paramtp):
- listCmd = []
-
- deffile = env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")
- for src in source:
- # Check explicitly for a non-None deffile so that the __cmp__
- # method of the base SCons.Util.Proxy class used for some Node
- # proxies doesn't try to use a non-existent __dict__ attribute.
- if deffile and src == deffile:
- # Treat this source as a .def file.
- listCmd.append("/def:%s" % src.get_string(for_signature))
- else:
- # Just treat it as a generic source file.
- listCmd.append(src)
- return listCmd
-
-def windowsShlinkTargets(target, source, env, for_signature):
- return _dllTargets(target, source, env, for_signature, 'SHLIB')
-
-def windowsShlinkSources(target, source, env, for_signature):
- return _dllSources(target, source, env, for_signature, 'SHLIB')
-
-def _windowsLdmodTargets(target, source, env, for_signature):
- """Get targets for loadable modules."""
- return _dllTargets(target, source, env, for_signature, 'LDMODULE')
-
-def _windowsLdmodSources(target, source, env, for_signature):
- """Get sources for loadable modules."""
- return _dllSources(target, source, env, for_signature, 'LDMODULE')
-
-def _dllEmitter(target, source, env, paramtp):
- """Common implementation of dll emitter."""
- SCons.Tool.msvc.validate_vars(env)
-
- extratargets = []
- extrasources = []
-
- dll = env.FindIxes(target, '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp)
- no_import_lib = env.get('no_import_lib', 0)
-
- if not dll:
- raise SCons.Errors.UserError, 'A shared library should have exactly one target with the suffix: %s' % env.subst('$%sSUFFIX' % paramtp)
-
- insert_def = env.subst("$WINDOWS_INSERT_DEF")
- if not insert_def in ['', '0', 0] and \
- not env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"):
-
- # append a def file to the list of sources
- extrasources.append(
- env.ReplaceIxes(dll,
- '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp,
- "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"))
-
- if env.has_key('PDB') and env['PDB']:
- pdb = env.arg2nodes('$PDB', target=target, source=source)[0]
- extratargets.append(pdb)
- target[0].attributes.pdb = pdb
-
- if not no_import_lib and \
- not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"):
- # Append an import library to the list of targets.
- extratargets.append(
- env.ReplaceIxes(dll,
- '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp,
- "LIBPREFIX", "LIBSUFFIX"))
- # and .exp file is created if there are exports from a DLL
- extratargets.append(
- env.ReplaceIxes(dll,
- '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp,
- "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX"))
-
- return (target+extratargets, source+extrasources)
-
-def windowsLibEmitter(target, source, env):
- return _dllEmitter(target, source, env, 'SHLIB')
-
-def ldmodEmitter(target, source, env):
- """Emitter for loadable modules.
-
- Loadable modules are identical to shared libraries on Windows, but building
- them is subject to different parameters (LDMODULE*).
- """
- return _dllEmitter(target, source, env, 'LDMODULE')
-
-def prog_emitter(target, source, env):
- SCons.Tool.msvc.validate_vars(env)
-
- extratargets = []
-
- exe = env.FindIxes(target, "PROGPREFIX", "PROGSUFFIX")
- if not exe:
- raise SCons.Errors.UserError, "An executable should have exactly one target with the suffix: %s" % env.subst("$PROGSUFFIX")
-
- if env.has_key('PDB') and env['PDB']:
- pdb = env.arg2nodes('$PDB', target=target, source=source)[0]
- extratargets.append(pdb)
- target[0].attributes.pdb = pdb
-
- return (target+extratargets,source)
-
-def RegServerFunc(target, source, env):
- if env.has_key('register') and env['register']:
- ret = regServerAction([target[0]], [source[0]], env)
- if ret:
- raise SCons.Errors.UserError, "Unable to register %s" % target[0]
- else:
- print "Registered %s sucessfully" % target[0]
- return ret
- return 0
-
-regServerAction = SCons.Action.Action("$REGSVRCOM", "$REGSVRCOMSTR")
-regServerCheck = SCons.Action.Action(RegServerFunc, None)
-shlibLinkAction = SCons.Action.Action('${TEMPFILE("$SHLINK $SHLINKFLAGS $_SHLINK_TARGETS $_LIBDIRFLAGS $_LIBFLAGS $_PDB $_SHLINK_SOURCES")}')
-compositeShLinkAction = shlibLinkAction + regServerCheck
-ldmodLinkAction = SCons.Action.Action('${TEMPFILE("$LDMODULE $LDMODULEFLAGS $_LDMODULE_TARGETS $_LIBDIRFLAGS $_LIBFLAGS $_PDB $_LDMODULE_SOURCES")}')
-compositeLdmodAction = ldmodLinkAction + regServerCheck
-
-def generate(env):
- """Add Builders and construction variables for ar to an Environment."""
- SCons.Tool.createSharedLibBuilder(env)
- SCons.Tool.createProgBuilder(env)
-
- env['SHLINK'] = '$LINK'
- env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll')
- env['_SHLINK_TARGETS'] = windowsShlinkTargets
- env['_SHLINK_SOURCES'] = windowsShlinkSources
- env['SHLINKCOM'] = compositeShLinkAction
- env.Append(SHLIBEMITTER = [windowsLibEmitter])
- env['LINK'] = 'link'
- env['LINKFLAGS'] = SCons.Util.CLVar('/nologo')
- env['_PDB'] = pdbGenerator
- env['LINKCOM'] = '${TEMPFILE("$LINK $LINKFLAGS /OUT:$TARGET.windows $_LIBDIRFLAGS $_LIBFLAGS $_PDB $SOURCES.windows")}'
- env.Append(PROGEMITTER = [prog_emitter])
- env['LIBDIRPREFIX']='/LIBPATH:'
- env['LIBDIRSUFFIX']=''
- env['LIBLINKPREFIX']=''
- env['LIBLINKSUFFIX']='$LIBSUFFIX'
-
- env['WIN32DEFPREFIX'] = ''
- env['WIN32DEFSUFFIX'] = '.def'
- env['WIN32_INSERT_DEF'] = 0
- env['WINDOWSDEFPREFIX'] = '${WIN32DEFPREFIX}'
- env['WINDOWSDEFSUFFIX'] = '${WIN32DEFSUFFIX}'
- env['WINDOWS_INSERT_DEF'] = '${WIN32_INSERT_DEF}'
-
- env['WIN32EXPPREFIX'] = ''
- env['WIN32EXPSUFFIX'] = '.exp'
- env['WINDOWSEXPPREFIX'] = '${WIN32EXPPREFIX}'
- env['WINDOWSEXPSUFFIX'] = '${WIN32EXPSUFFIX}'
-
- env['WINDOWSSHLIBMANIFESTPREFIX'] = ''
- env['WINDOWSSHLIBMANIFESTSUFFIX'] = '${SHLIBSUFFIX}.manifest'
- env['WINDOWSPROGMANIFESTPREFIX'] = ''
- env['WINDOWSPROGMANIFESTSUFFIX'] = '${PROGSUFFIX}.manifest'
-
- env['REGSVRACTION'] = regServerCheck
- env['REGSVR'] = os.path.join(SCons.Platform.win32.get_system_root(),'System32','regsvr32')
- env['REGSVRFLAGS'] = '/s '
- env['REGSVRCOM'] = '$REGSVR $REGSVRFLAGS ${TARGET.windows}'
-
- # Loadable modules are on Windows the same as shared libraries, but they
- # are subject to different build parameters (LDMODULE* variables).
- # Therefore LDMODULE* variables correspond as much as possible to
- # SHLINK*/SHLIB* ones.
- SCons.Tool.createLoadableModuleBuilder(env)
- env['LDMODULE'] = '$SHLINK'
- env['LDMODULEPREFIX'] = '$SHLIBPREFIX'
- env['LDMODULESUFFIX'] = '$SHLIBSUFFIX'
- env['LDMODULEFLAGS'] = '$SHLINKFLAGS'
- env['_LDMODULE_TARGETS'] = _windowsLdmodTargets
- env['_LDMODULE_SOURCES'] = _windowsLdmodSources
- env['LDMODULEEMITTER'] = [ldmodEmitter]
- env['LDMODULECOM'] = compositeLdmodAction
-
-def exists(env):
- platform = env.get('PLATFORM', '')
- if platform in ('win32', 'cygwin'):
- # Only explicitly search for a 'link' executable on Windows
- # systems. Some other systems (e.g. Ubuntu Linux) have an
- # executable named 'link' and we don't want that to make SCons
- # think Visual Studio is installed.
- return env.Detect('link')
- return None
-
-# Local Variables:
-# tab-width:4
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/mesalib/scons/msvc_sa.py b/mesalib/scons/msvc_sa.py deleted file mode 100644 index 0bfc8920f..000000000 --- a/mesalib/scons/msvc_sa.py +++ /dev/null @@ -1,246 +0,0 @@ -"""msvc_sa
-
-Tool-specific initialization for Microsoft Visual C/C++.
-
-Based on SCons.Tool.msvc, without the MSVS detection.
-
-"""
-
-#
-# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-import os.path
-import re
-import string
-
-import SCons.Action
-import SCons.Builder
-import SCons.Errors
-import SCons.Platform.win32
-import SCons.Tool
-import SCons.Util
-import SCons.Warnings
-import SCons.Scanner.RC
-
-CSuffixes = ['.c', '.C']
-CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
-
-def validate_vars(env):
- """Validate the PCH and PCHSTOP construction variables."""
- if env.has_key('PCH') and env['PCH']:
- if not env.has_key('PCHSTOP'):
- raise SCons.Errors.UserError, "The PCHSTOP construction must be defined if PCH is defined."
- if not SCons.Util.is_String(env['PCHSTOP']):
- raise SCons.Errors.UserError, "The PCHSTOP construction variable must be a string: %r"%env['PCHSTOP']
-
-def pch_emitter(target, source, env):
- """Adds the object file target."""
-
- validate_vars(env)
-
- pch = None
- obj = None
-
- for t in target:
- if SCons.Util.splitext(str(t))[1] == '.pch':
- pch = t
- if SCons.Util.splitext(str(t))[1] == '.obj':
- obj = t
-
- if not obj:
- obj = SCons.Util.splitext(str(pch))[0]+'.obj'
-
- target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
-
- return (target, source)
-
-def object_emitter(target, source, env, parent_emitter):
- """Sets up the PCH dependencies for an object file."""
-
- validate_vars(env)
-
- parent_emitter(target, source, env)
-
- if env.has_key('PCH') and env['PCH']:
- env.Depends(target, env['PCH'])
-
- return (target, source)
-
-def static_object_emitter(target, source, env):
- return object_emitter(target, source, env,
- SCons.Defaults.StaticObjectEmitter)
-
-def shared_object_emitter(target, source, env):
- return object_emitter(target, source, env,
- SCons.Defaults.SharedObjectEmitter)
-
-pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
-pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
- emitter=pch_emitter,
- source_scanner=SCons.Tool.SourceFileScanner)
-
-
-# Logic to build .rc files into .res files (resource files)
-res_scanner = SCons.Scanner.RC.RCScan()
-res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
-res_builder = SCons.Builder.Builder(action=res_action,
- src_suffix='.rc',
- suffix='.res',
- src_builder=[],
- source_scanner=res_scanner)
-
-def msvc_batch_key(action, env, target, source):
- """
- Returns a key to identify unique batches of sources for compilation.
-
- If batching is enabled (via the $MSVC_BATCH setting), then all
- target+source pairs that use the same action, defined by the same
- environment, and have the same target and source directories, will
- be batched.
-
- Returning None specifies that the specified target+source should not
- be batched with other compilations.
- """
- b = env.subst('$MSVC_BATCH')
- if b in (None, '', '0'):
- # We're not using batching; return no key.
- return None
- t = target[0]
- s = source[0]
- if os.path.splitext(t.name)[0] != os.path.splitext(s.name)[0]:
- # The base names are different, so this *must* be compiled
- # separately; return no key.
- return None
- return (id(action), id(env), t.dir, s.dir)
-
-def msvc_output_flag(target, source, env, for_signature):
- """
- Returns the correct /Fo flag for batching.
-
- If batching is disabled or there's only one source file, then we
- return an /Fo string that specifies the target explicitly. Otherwise,
- we return an /Fo string that just specifies the first target's
- directory (where the Visual C/C++ compiler will put the .obj files).
- """
- b = env.subst('$MSVC_BATCH')
- if b in (None, '', '0') or len(source) == 1:
- return '/Fo$TARGET'
- else:
- # The Visual C/C++ compiler requires a \ at the end of the /Fo
- # option to indicate an output directory. We use os.sep here so
- # that the test(s) for this can be run on non-Windows systems
- # without having a hard-coded backslash mess up command-line
- # argument parsing.
- return '/Fo${TARGET.dir}' + os.sep
-
-CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR",
- batch_key=msvc_batch_key,
- targets='$CHANGED_TARGETS')
-ShCAction = SCons.Action.Action("$SHCCCOM", "$SHCCCOMSTR",
- batch_key=msvc_batch_key,
- targets='$CHANGED_TARGETS')
-CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR",
- batch_key=msvc_batch_key,
- targets='$CHANGED_TARGETS')
-ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR",
- batch_key=msvc_batch_key,
- targets='$CHANGED_TARGETS')
-
-def generate(env):
- """Add Builders and construction variables for MSVC++ to an Environment."""
- static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
-
- # TODO(batch): shouldn't reach in to cmdgen this way; necessary
- # for now to bypass the checks in Builder.DictCmdGenerator.__call__()
- # and allow .cc and .cpp to be compiled in the same command line.
- static_obj.cmdgen.source_ext_match = False
- shared_obj.cmdgen.source_ext_match = False
-
- for suffix in CSuffixes:
- static_obj.add_action(suffix, CAction)
- shared_obj.add_action(suffix, ShCAction)
- static_obj.add_emitter(suffix, static_object_emitter)
- shared_obj.add_emitter(suffix, shared_object_emitter)
-
- for suffix in CXXSuffixes:
- static_obj.add_action(suffix, CXXAction)
- shared_obj.add_action(suffix, ShCXXAction)
- static_obj.add_emitter(suffix, static_object_emitter)
- shared_obj.add_emitter(suffix, shared_object_emitter)
-
- env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Z7") or ""}'])
- env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
- env['_MSVC_OUTPUT_FLAG'] = msvc_output_flag
- env['_CCCOMCOM'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS'
- env['CC'] = 'cl'
- env['CCFLAGS'] = SCons.Util.CLVar('/nologo')
- env['CFLAGS'] = SCons.Util.CLVar('')
- env['CCCOM'] = '$CC $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CFLAGS $CCFLAGS $_CCCOMCOM'
- env['SHCC'] = '$CC'
- env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
- env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
- env['SHCCCOM'] = '$SHCC $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCFLAGS $SHCCFLAGS $_CCCOMCOM'
- env['CXX'] = '$CC'
- env['CXXFLAGS'] = SCons.Util.CLVar('$( /TP $)')
- env['CXXCOM'] = '$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM'
- env['SHCXX'] = '$CXX'
- env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
- env['SHCXXCOM'] = '$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM'
- env['CPPDEFPREFIX'] = '/D'
- env['CPPDEFSUFFIX'] = ''
- env['INCPREFIX'] = '/I'
- env['INCSUFFIX'] = ''
-# env.Append(OBJEMITTER = [static_object_emitter])
-# env.Append(SHOBJEMITTER = [shared_object_emitter])
- env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
-
- env['RC'] = 'rc'
- env['RCFLAGS'] = SCons.Util.CLVar('')
- env['RCSUFFIXES']=['.rc','.rc2']
- env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
- env['BUILDERS']['RES'] = res_builder
- env['OBJPREFIX'] = ''
- env['OBJSUFFIX'] = '.obj'
- env['SHOBJPREFIX'] = '$OBJPREFIX'
- env['SHOBJSUFFIX'] = '$OBJSUFFIX'
-
- env['CFILESUFFIX'] = '.c'
- env['CXXFILESUFFIX'] = '.cc'
-
- env['PCHPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Yd") or ""}'])
- env['PCHCOM'] = '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
- env['BUILDERS']['PCH'] = pch_builder
-
- if not env.has_key('ENV'):
- env['ENV'] = {}
- if not env['ENV'].has_key('SystemRoot'): # required for dlls in the winsxs folders
- env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root()
-
-def exists(env):
- return env.Detect('cl')
-
-# Local Variables:
-# tab-width:4
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/mesalib/scons/wcesdk.py b/mesalib/scons/wcesdk.py deleted file mode 100644 index cd797a789..000000000 --- a/mesalib/scons/wcesdk.py +++ /dev/null @@ -1,176 +0,0 @@ -"""wcesdk
-
-Tool-specific initialization for Microsoft Window CE SDKs.
-
-"""
-
-#
-# Copyright (c) 2001-2007 The SCons Foundation
-# Copyright (c) 2008 Tungsten Graphics, Inc.
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-import os.path
-import re
-import string
-
-import SCons.Action
-import SCons.Builder
-import SCons.Errors
-import SCons.Platform.win32
-import SCons.Tool
-import SCons.Util
-import SCons.Warnings
-
-import msvc_sa
-import mslib_sa
-import mslink_sa
-
-def get_wce500_paths(env):
- """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
- of those three environment variables that should be set
- in order to execute the MSVC tools properly."""
-
- exe_paths = []
- lib_paths = []
- include_paths = []
-
- # mymic the batch files located in Microsoft eMbedded C++ 4.0\EVC\WCExxx\BIN
- os_version = os.environ.get('OSVERSION', 'WCE500')
- platform = os.environ.get('PLATFORM', 'STANDARDSDK_500')
- wce_root = os.environ.get('WCEROOT', 'C:\\Program Files\\Microsoft eMbedded C++ 4.0')
- sdk_root = os.environ.get('SDKROOT', 'C:\\Windows CE Tools')
-
- target_cpu = 'x86'
- cfg = 'none'
-
- exe_paths.append( os.path.join(wce_root, 'COMMON', 'EVC', 'bin') )
- exe_paths.append( os.path.join(wce_root, 'EVC', os_version, 'bin') )
- include_paths.append( os.path.join(sdk_root, os_version, platform, 'include', target_cpu) )
- include_paths.append( os.path.join(sdk_root, os_version, platform, 'MFC', 'include') )
- include_paths.append( os.path.join(sdk_root, os_version, platform, 'ATL', 'include') )
- lib_paths.append( os.path.join(sdk_root, os_version, platform, 'lib', target_cpu) )
- lib_paths.append( os.path.join(sdk_root, os_version, platform, 'MFC', 'lib', target_cpu) )
- lib_paths.append( os.path.join(sdk_root, os_version, platform, 'ATL', 'lib', target_cpu) )
-
- include_path = string.join( include_paths, os.pathsep )
- lib_path = string.join(lib_paths, os.pathsep )
- exe_path = string.join(exe_paths, os.pathsep )
- return (include_path, lib_path, exe_path)
-
-def get_wce600_root(env):
- try:
- return os.environ['_WINCEROOT']
- except KeyError:
- pass
-
- if SCons.Util.can_read_reg:
- key = r'SOFTWARE\Microsoft\Platform Builder\6.00\Directories\OS Install Dir'
- try:
- path, t = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, key)
- except SCons.Util.RegError:
- pass
- else:
- return path
-
- default_path = os.path.join(r'C:\WINCE600', version)
- if os.path.exists(default_path):
- return default_path
-
- return None
-
-def get_wce600_paths(env):
- """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
- of those three environment variables that should be set
- in order to execute the MSVC tools properly."""
-
- exe_paths = []
- lib_paths = []
- include_paths = []
-
- # See also C:\WINCE600\public\common\oak\misc\wince.bat
-
- wince_root = get_wce600_root(env)
- if wince_root is None:
- raise SCons.Errors.InternalError, "Windows CE 6.0 SDK not found"
-
- os_version = os.environ.get('_WINCEOSVER', '600')
- platform_root = os.environ.get('_PLATFORMROOT', os.path.join(wince_root, 'platform'))
- sdk_root = os.environ.get('_SDKROOT' ,os.path.join(wince_root, 'sdk'))
-
- platform_root = os.environ.get('_PLATFORMROOT', os.path.join(wince_root, 'platform'))
- sdk_root = os.environ.get('_SDKROOT' ,os.path.join(wince_root, 'sdk'))
-
- host_cpu = os.environ.get('_HOSTCPUTYPE', 'i386')
- target_cpu = os.environ.get('_TGTCPU', 'x86')
-
- if env['build'] == 'debug':
- build = 'debug'
- else:
- build = 'retail'
-
- try:
- project_root = os.environ['_PROJECTROOT']
- except KeyError:
- # No project root defined -- use the common stuff instead
- project_root = os.path.join(wince_root, 'public', 'common')
-
- exe_paths.append( os.path.join(sdk_root, 'bin', host_cpu) )
- exe_paths.append( os.path.join(sdk_root, 'bin', host_cpu, target_cpu) )
- exe_paths.append( os.path.join(wince_root, 'common', 'oak', 'bin', host_cpu) )
- exe_paths.append( os.path.join(wince_root, 'common', 'oak', 'misc') )
-
- include_paths.append( os.path.join(project_root, 'sdk', 'inc') )
- include_paths.append( os.path.join(project_root, 'oak', 'inc') )
- include_paths.append( os.path.join(project_root, 'ddk', 'inc') )
- include_paths.append( os.path.join(sdk_root, 'CE', 'inc') )
-
- lib_paths.append( os.path.join(project_root, 'sdk', 'lib', target_cpu, build) )
- lib_paths.append( os.path.join(project_root, 'oak', 'lib', target_cpu, build) )
- lib_paths.append( os.path.join(project_root, 'ddk', 'lib', target_cpu, build) )
-
- include_path = string.join( include_paths, os.pathsep )
- lib_path = string.join(lib_paths, os.pathsep )
- exe_path = string.join(exe_paths, os.pathsep )
- return (include_path, lib_path, exe_path)
-
-def generate(env):
-
- msvc_sa.generate(env)
- mslib_sa.generate(env)
- mslink_sa.generate(env)
-
- if not env.has_key('ENV'):
- env['ENV'] = {}
-
- try:
- include_path, lib_path, exe_path = get_wce600_paths(env)
-
- env.PrependENVPath('INCLUDE', include_path)
- env.PrependENVPath('LIB', lib_path)
- env.PrependENVPath('PATH', exe_path)
- except (SCons.Util.RegError, SCons.Errors.InternalError):
- pass
-
-def exists(env):
- return get_wce600_root(env) is not None
-
-# vim:set ts=4 sw=4 et:
diff --git a/mesalib/scons/winddk.py b/mesalib/scons/winddk.py deleted file mode 100644 index 9e47b9428..000000000 --- a/mesalib/scons/winddk.py +++ /dev/null @@ -1,148 +0,0 @@ -"""winddk
-
-Tool-specific initialization for Microsoft Windows DDK.
-
-"""
-
-#
-# Copyright (c) 2001-2007 The SCons Foundation
-# Copyright (c) 2008 Tungsten Graphics, Inc.
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-import os.path
-import re
-import string
-
-import SCons.Action
-import SCons.Builder
-import SCons.Errors
-import SCons.Platform.win32
-import SCons.Tool
-import SCons.Util
-import SCons.Warnings
-
-import msvc_sa
-import mslib_sa
-import mslink_sa
-
-versions = [
- '6001.18002',
- '3790.1830',
-]
-
-def cpu_bin(target_cpu):
- if target_cpu == 'i386':
- return 'x86'
- else:
- return target_cpu
-
-def get_winddk_root(env, version):
- default_path = os.path.join(r'C:\WINDDK', version)
- if os.path.exists(default_path):
- return default_path
- return None
-
-def get_winddk_paths(env, version, root):
- version_major, version_minor = map(int, version.split('.'))
-
- if version_major >= 6000:
- target_os = 'wlh'
- else:
- target_os = 'wxp'
-
- if env['machine'] in ('generic', 'x86'):
- target_cpu = 'i386'
- elif env['machine'] == 'x86_64':
- target_cpu = 'amd64'
- else:
- raise SCons.Errors.InternalError, "Unsupported target machine"
-
- if version_major >= 6000:
- # TODO: take in consideration the host cpu
- bin_dir = os.path.join(root, 'bin', 'x86', cpu_bin(target_cpu))
- else:
- if target_cpu == 'i386':
- bin_dir = os.path.join(root, 'bin', 'x86')
- else:
- # TODO: take in consideration the host cpu
- bin_dir = os.path.join(root, 'bin', 'win64', 'x86', cpu_bin(target_cpu))
-
- crt_inc_dir = os.path.join(root, 'inc', 'crt')
- if version_major >= 6000:
- sdk_inc_dir = os.path.join(root, 'inc', 'api')
- ddk_inc_dir = os.path.join(root, 'inc', 'ddk')
- wdm_inc_dir = os.path.join(root, 'inc', 'ddk')
- else:
- ddk_inc_dir = os.path.join(root, 'inc', 'ddk', target_os)
- sdk_inc_dir = os.path.join(root, 'inc', target_os)
- wdm_inc_dir = os.path.join(root, 'inc', 'ddk', 'wdm', target_os)
-
- if env['toolchain'] == 'winddk':
- env.PrependENVPath('PATH', [bin_dir])
- env.PrependENVPath('INCLUDE', [
- wdm_inc_dir,
- ddk_inc_dir,
- crt_inc_dir,
- sdk_inc_dir,
- ])
- env.PrependENVPath('LIB', [
- os.path.join(root, 'lib', 'crt', target_cpu),
- os.path.join(root, 'lib', target_os, target_cpu),
- ])
- elif env['toolchain'] == 'crossmingw':
- env.Prepend(CPPFLAGS = [
- '-isystem', ddk_inc_dir,
- '-isystem', sdk_inc_dir,
- ])
- else:
- env.Prepend(CPPPATH = [
- wdm_inc_dir,
- ddk_inc_dir,
- sdk_inc_dir,
- ])
- env.Prepend(LIBPATH = [
- os.path.join(root, 'lib', target_os, target_cpu),
- ])
-
-
-def generate(env):
- if not env.has_key('ENV'):
- env['ENV'] = {}
-
- for version in versions:
- root = get_winddk_root(env, version)
- if root is not None:
- get_winddk_paths(env, version, root)
- break
-
- if env['toolchain'] == 'winddk':
- msvc_sa.generate(env)
- mslib_sa.generate(env)
- mslink_sa.generate(env)
-
-def exists(env):
- for version in versions:
- if get_winddk_root(env, version) is not None:
- return True
- return False
-
-# vim:set ts=4 sw=4 et:
diff --git a/mesalib/scons/winsdk.py b/mesalib/scons/winsdk.py deleted file mode 100644 index ab4369046..000000000 --- a/mesalib/scons/winsdk.py +++ /dev/null @@ -1,131 +0,0 @@ -"""winsdk
-
-Tool-specific initialization for Microsoft Windows SDK.
-
-"""
-
-#
-# Copyright (c) 2001-2007 The SCons Foundation
-# Copyright (c) 2008 Tungsten Graphics, Inc.
-# Copyright (c) 2009 VMware, Inc.
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-import os.path
-import platform
-
-import SCons.Errors
-import SCons.Util
-
-import msvc_sa
-import mslib_sa
-import mslink_sa
-
-
-def get_vs_root(env):
- # TODO: Check HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7
- path = os.path.join(os.getenv('ProgramFiles', r'C:\Program Files'), 'Microsoft Visual Studio 9.0')
- return path
-
-def get_vs_paths(env):
- vs_root = get_vs_root(env)
- if vs_root is None:
- raise SCons.Errors.InternalError, "WINSDK compiler not found"
-
- tool_path = os.path.join(vs_root, 'Common7', 'IDE')
-
- env.PrependENVPath('PATH', tool_path)
-
-def get_vc_root(env):
- # TODO: Check HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VC7
- path = os.path.join(os.getenv('ProgramFiles', r'C:\Program Files'), 'Microsoft Visual Studio 9.0', 'VC')
- return path
-
-def get_vc_paths(env):
- vc_root = get_vc_root(env)
- if vc_root is None:
- raise SCons.Errors.InternalError, "WINSDK compiler not found"
-
- target_cpu = env['machine']
-
- if target_cpu in ('generic', 'x86'):
- bin_dir = 'bin'
- lib_dir = 'lib'
- elif target_cpu == 'x86_64':
- # TODO: take in consideration the host cpu
- bin_dir = r'bin\x86_amd64'
- lib_dir = r'lib\amd64'
- else:
- raise SCons.Errors.InternalError, "Unsupported target machine"
- include_dir = 'include'
-
- env.PrependENVPath('PATH', os.path.join(vc_root, bin_dir))
- env.PrependENVPath('INCLUDE', os.path.join(vc_root, include_dir))
- env.PrependENVPath('LIB', os.path.join(vc_root, lib_dir))
-
-def get_sdk_root(env):
- if SCons.Util.can_read_reg:
- key = r'SOFTWARE\Microsoft\Microsoft SDKs\Windows\CurrentInstallFolder'
- try:
- path, t = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, key)
- except SCons.Util.RegError:
- pass
- else:
- return path
-
- return None
-
-def get_sdk_paths(env):
- sdk_root = get_sdk_root(env)
- if sdk_root is None:
- raise SCons.Errors.InternalError, "WINSDK not found"
-
- target_cpu = env['machine']
-
- bin_dir = 'Bin'
- if target_cpu in ('generic', 'x86'):
- lib_dir = 'Lib'
- elif target_cpu == 'x86_64':
- lib_dir = r'Lib\x64'
- else:
- raise SCons.Errors.InternalError, "Unsupported target machine"
- include_dir = 'Include'
-
- env.PrependENVPath('PATH', os.path.join(sdk_root, bin_dir))
- env.PrependENVPath('INCLUDE', os.path.join(sdk_root, include_dir))
- env.PrependENVPath('LIB', os.path.join(sdk_root, lib_dir))
-
-def generate(env):
- if not env.has_key('ENV'):
- env['ENV'] = {}
-
- get_vs_paths(env)
- get_vc_paths(env)
- get_sdk_paths(env)
-
- msvc_sa.generate(env)
- mslib_sa.generate(env)
- mslink_sa.generate(env)
-
-def exists(env):
- return get_vc_root(env) is not None and get_sdk_root(env) is not None
-
-# vim:set ts=4 sw=4 et:
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 484786c5f..ce29d5a87 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -2120,25 +2120,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, var->depth_layout = ir_depth_layout_unchanged; else var->depth_layout = ir_depth_layout_none; - - /* From page 46 (page 52 of the PDF) of the GLSL ES specification: - * - * "Array variables are l-values and may be passed to parameters - * declared as out or inout. However, they may not be used as - * the target of an assignment." - * - * From page 32 (page 38 of the PDF) of the GLSL 1.10 spec: - * - * "Other binary or unary expressions, non-dereferenced arrays, - * function names, swizzles with repeated fields, and constants - * cannot be l-values." - * - * So we only mark 1.10 as non-lvalues, and check for array - * assignment in 100 specifically in do_assignment. - */ - if (var->type->is_array() && state->language_version != 110) { - var->array_lvalue = true; - } } /** @@ -2953,6 +2934,26 @@ ast_parameter_declarator::hir(exec_list *instructions, type = glsl_type::error_type; } + /* From page 39 (page 45 of the PDF) of the GLSL 1.10 spec: + * + * "When calling a function, expressions that do not evaluate to + * l-values cannot be passed to parameters declared as out or inout." + * + * From page 32 (page 38 of the PDF) of the GLSL 1.10 spec: + * + * "Other binary or unary expressions, non-dereferenced arrays, + * function names, swizzles with repeated fields, and constants + * cannot be l-values." + * + * So for GLSL 1.10, passing an array as an out or inout parameter is not + * allowed. This restriction is removed in GLSL 1.20, and in GLSL ES. + */ + if ((var->mode == ir_var_inout || var->mode == ir_var_out) + && type->is_array() && state->language_version == 110) { + _mesa_glsl_error(&loc, state, "Arrays cannot be out or inout parameters in GLSL 1.10"); + type = glsl_type::error_type; + } + instructions->push_tail(var); /* Parameter declarations do not have r-values. diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 41ed4f114..d6594cd9a 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1105,9 +1105,6 @@ ir_dereference::is_lvalue() const if ((var == NULL) || var->read_only) return false; - if (this->type->is_array() && !var->array_lvalue) - return false; - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: * * "Samplers cannot be treated as l-values; hence cannot be used @@ -1323,7 +1320,7 @@ ir_swizzle::variable_referenced() const ir_variable::ir_variable(const struct glsl_type *type, const char *name, ir_variable_mode mode) : max_array_access(0), read_only(false), centroid(false), invariant(false), - mode(mode), interpolation(ir_var_smooth), array_lvalue(false) + mode(mode), interpolation(ir_var_smooth) { this->ir_type = ir_type_variable; this->type = type; diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 2e899f3ed..cc4e68002 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -346,14 +346,6 @@ public: unsigned interpolation:2; /** - * Flag that the whole array is assignable - * - * In GLSL 1.20 and later whole arrays are assignable (and comparable for - * equality). This flag enables this behavior. - */ - unsigned array_lvalue:1; - - /** * \name ARB_fragment_coord_conventions * @{ */ diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index f0757365d..c1befa95c 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -47,7 +47,6 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const var->centroid = this->centroid; var->invariant = this->invariant; var->interpolation = this->interpolation; - var->array_lvalue = this->array_lvalue; var->location = this->location; var->warn_extension = this->warn_extension; var->origin_upper_left = this->origin_upper_left; diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 2ebcd35bd..482bd98a2 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -1569,10 +1569,10 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) /* vertex colors */ for (i = 0; i < 4; i++) { - verts[i].r = ctx->Color.ClearColorUnclamped[0]; - verts[i].g = ctx->Color.ClearColorUnclamped[1]; - verts[i].b = ctx->Color.ClearColorUnclamped[2]; - verts[i].a = ctx->Color.ClearColorUnclamped[3]; + verts[i].r = ctx->Color.ClearColor.f[0]; + verts[i].g = ctx->Color.ClearColor.f[1]; + verts[i].b = ctx->Color.ClearColor.f[2]; + verts[i].a = ctx->Color.ClearColor.f[3]; } /* upload new vertex data */ @@ -1679,7 +1679,7 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) _mesa_UseProgramObjectARB(clear->ShaderProg); _mesa_Uniform4fvARB(clear->ColorLocation, 1, - ctx->Color.ClearColorUnclamped); + ctx->Color.ClearColor.f); _mesa_BindVertexArray(clear->ArrayObj); _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 6d6401934..cdd413737 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -816,8 +816,10 @@ driCreateNewScreen(int scrn, (void) loaderPrivate; - if (driDriverAPI.InitScreen == NULL) + if (driDriverAPI.InitScreen == NULL) { + __driUtilMessage("driver does not support DRI1"); return NULL; + } psp = calloc(1, sizeof *psp); if (!psp) diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c index 35a150d06..14d15ed6c 100644 --- a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c +++ b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c @@ -249,14 +249,15 @@ static void wmesa_flush(struct gl_context *ctx) /* * Set the color used to clear the color buffer. */ -static void clear_color(struct gl_context *ctx, const GLfloat color[4]) +static void clear_color(struct gl_context *ctx, + const union gl_color_union color) { WMesaContext pwc = wmesa_context(ctx); GLubyte col[3]; - CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]); - CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]); - CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]); + UNCLAMPED_FLOAT_TO_UBYTE(col[0], color.f[0]); + UNCLAMPED_FLOAT_TO_UBYTE(col[1], color.f[1]); + UNCLAMPED_FLOAT_TO_UBYTE(col[2], color.f[2]); pwc->clearColorRef = RGB(col[0], col[1], col[2]); DeleteObject(pwc->clearPen); DeleteObject(pwc->clearBrush); diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index 573100402..9767740a3 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -884,10 +884,10 @@ _mesa_PopAttrib(void) color = (const struct gl_colorbuffer_attrib *) attr->data; _mesa_ClearIndex((GLfloat) color->ClearIndex); - _mesa_ClearColor(color->ClearColorUnclamped[0], - color->ClearColorUnclamped[1], - color->ClearColorUnclamped[2], - color->ClearColorUnclamped[3]); + _mesa_ClearColor(color->ClearColor.f[0], + color->ClearColor.f[1], + color->ClearColor.f[2], + color->ClearColor.f[3]); _mesa_IndexMask(color->IndexMask); if (!ctx->Extensions.EXT_draw_buffers2) { _mesa_ColorMask((GLboolean) (color->ColorMask[0][0] != 0), diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c index 94a457f58..4214a661b 100644 --- a/mesalib/src/mesa/main/blend.c +++ b/mesalib/src/mesa/main/blend.c @@ -1,833 +1,832 @@ -/**
- * \file blend.c
- * Blending operations.
- */
-
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.1
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-
-#include "glheader.h"
-#include "blend.h"
-#include "context.h"
-#include "enums.h"
-#include "macros.h"
-#include "mtypes.h"
-
-
-
-/**
- * Check if given blend source factor is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_src_factor(const struct gl_context *ctx, GLenum factor)
-{
- switch (factor) {
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- return ctx->Extensions.NV_blend_square;
- case GL_ZERO:
- case GL_ONE:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_SRC_ALPHA_SATURATE:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Check if given blend destination factor is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_dst_factor(const struct gl_context *ctx, GLenum factor)
-{
- switch (factor) {
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- return ctx->Extensions.NV_blend_square;
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Check if src/dest RGB/A blend factors are legal. If not generate
- * a GL error.
- * \return GL_TRUE if factors are legal, GL_FALSE otherwise.
- */
-static GLboolean
-validate_blend_factors(struct gl_context *ctx, const char *func,
- GLenum sfactorRGB, GLenum dfactorRGB,
- GLenum sfactorA, GLenum dfactorA)
-{
- if (!legal_src_factor(ctx, sfactorRGB)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(sfactorRGB = %s)", func,
- _mesa_lookup_enum_by_nr(sfactorRGB));
- return GL_FALSE;
- }
-
- if (!legal_dst_factor(ctx, dfactorRGB)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(dfactorRGB = %s)", func,
- _mesa_lookup_enum_by_nr(dfactorRGB));
- return GL_FALSE;
- }
-
- if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(sfactorA = %s)", func,
- _mesa_lookup_enum_by_nr(sfactorA));
- return GL_FALSE;
- }
-
- if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(dfactorA = %s)", func,
- _mesa_lookup_enum_by_nr(dfactorA));
- return GL_FALSE;
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Specify the blending operation.
- *
- * \param sfactor source factor operator.
- * \param dfactor destination factor operator.
- *
- * \sa glBlendFunc, glBlendFuncSeparateEXT
- */
-void GLAPIENTRY
-_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
-{
- _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
-}
-
-
-/**
- * Set the separate blend source/dest factors for all draw buffers.
- *
- * \param sfactorRGB RGB source factor operator.
- * \param dfactorRGB RGB destination factor operator.
- * \param sfactorA alpha source factor operator.
- * \param dfactorA alpha destination factor operator.
- */
-void GLAPIENTRY
-_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
- GLenum sfactorA, GLenum dfactorA )
-{
- GLuint buf, numBuffers;
- GLboolean changed;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
- _mesa_lookup_enum_by_nr(sfactorRGB),
- _mesa_lookup_enum_by_nr(dfactorRGB),
- _mesa_lookup_enum_by_nr(sfactorA),
- _mesa_lookup_enum_by_nr(dfactorA));
-
- if (!validate_blend_factors(ctx, "glBlendFuncSeparate",
- sfactorRGB, dfactorRGB,
- sfactorA, dfactorA)) {
- return;
- }
-
- numBuffers = ctx->Extensions.ARB_draw_buffers_blend
- ? ctx->Const.MaxDrawBuffers : 1;
-
- changed = GL_FALSE;
- for (buf = 0; buf < numBuffers; buf++) {
- if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB ||
- ctx->Color.Blend[buf].DstRGB != dfactorRGB ||
- ctx->Color.Blend[buf].SrcA != sfactorA ||
- ctx->Color.Blend[buf].DstA != dfactorA) {
- changed = GL_TRUE;
- break;
- }
- }
- if (!changed)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
-
- for (buf = 0; buf < numBuffers; buf++) {
- ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
- ctx->Color.Blend[buf].DstRGB = dfactorRGB;
- ctx->Color.Blend[buf].SrcA = sfactorA;
- ctx->Color.Blend[buf].DstA = dfactorA;
- }
- ctx->Color._BlendFuncPerBuffer = GL_FALSE;
-
- if (ctx->Driver.BlendFuncSeparate) {
- ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB,
- sfactorA, dfactorA);
- }
-}
-
-
-#if _HAVE_FULL_GL
-
-
-/**
- * Set blend source/dest factors for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
-{
- _mesa_BlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor);
-}
-
-
-/**
- * Set separate blend source/dest factors for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
- GLenum sfactorA, GLenum dfactorA)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (!ctx->Extensions.ARB_draw_buffers_blend) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()");
- return;
- }
-
- if (buf >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
- buf);
- return;
- }
-
- if (!validate_blend_factors(ctx, "glBlendFuncSeparatei",
- sfactorRGB, dfactorRGB,
- sfactorA, dfactorA)) {
- return;
- }
-
- if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB &&
- ctx->Color.Blend[buf].DstRGB == dfactorRGB &&
- ctx->Color.Blend[buf].SrcA == sfactorA &&
- ctx->Color.Blend[buf].DstA == dfactorA)
- return; /* no change */
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
-
- ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
- ctx->Color.Blend[buf].DstRGB = dfactorRGB;
- ctx->Color.Blend[buf].SrcA = sfactorA;
- ctx->Color.Blend[buf].DstA = dfactorA;
- ctx->Color._BlendFuncPerBuffer = GL_TRUE;
-
- if (ctx->Driver.BlendFuncSeparatei) {
- ctx->Driver.BlendFuncSeparatei(ctx, buf, sfactorRGB, dfactorRGB,
- sfactorA, dfactorA);
- }
-}
-
-
-/**
- * Check if given blend equation is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_blend_equation(const struct gl_context *ctx,
- GLenum mode, GLboolean is_separate)
-{
- switch (mode) {
- case GL_FUNC_ADD:
- return GL_TRUE;
- case GL_MIN:
- case GL_MAX:
- return ctx->Extensions.EXT_blend_minmax;
- case GL_LOGIC_OP:
- /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
- */
- return ctx->Extensions.EXT_blend_logic_op && !is_separate;
- case GL_FUNC_SUBTRACT:
- case GL_FUNC_REVERSE_SUBTRACT:
- return ctx->Extensions.EXT_blend_subtract;
- default:
- return GL_FALSE;
- }
-}
-
-
-/* This is really an extension function! */
-void GLAPIENTRY
-_mesa_BlendEquation( GLenum mode )
-{
- GLuint buf, numBuffers;
- GLboolean changed;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendEquation(%s)\n",
- _mesa_lookup_enum_by_nr(mode));
-
- if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
- return;
- }
-
- numBuffers = ctx->Extensions.ARB_draw_buffers_blend
- ? ctx->Const.MaxDrawBuffers : 1;
-
- changed = GL_FALSE;
- for (buf = 0; buf < numBuffers; buf++) {
- if (ctx->Color.Blend[buf].EquationRGB != mode ||
- ctx->Color.Blend[buf].EquationA != mode) {
- changed = GL_TRUE;
- break;
- }
- }
- if (!changed)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- for (buf = 0; buf < numBuffers; buf++) {
- ctx->Color.Blend[buf].EquationRGB = mode;
- ctx->Color.Blend[buf].EquationA = mode;
- }
- ctx->Color._BlendEquationPerBuffer = GL_FALSE;
-
- if (ctx->Driver.BlendEquationSeparate)
- (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
-}
-
-
-/**
- * Set blend equation for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendEquationi(GLuint buf, GLenum mode)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
- buf, _mesa_lookup_enum_by_nr(mode));
-
- if (buf >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
- buf);
- return;
- }
-
- if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi");
- return;
- }
-
- if (ctx->Color.Blend[buf].EquationRGB == mode &&
- ctx->Color.Blend[buf].EquationA == mode)
- return; /* no change */
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.Blend[buf].EquationRGB = mode;
- ctx->Color.Blend[buf].EquationA = mode;
- ctx->Color._BlendEquationPerBuffer = GL_TRUE;
-
- if (ctx->Driver.BlendEquationSeparatei)
- ctx->Driver.BlendEquationSeparatei(ctx, buf, mode, mode);
-}
-
-
-void GLAPIENTRY
-_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
-{
- GLuint buf, numBuffers;
- GLboolean changed;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n",
- _mesa_lookup_enum_by_nr(modeRGB),
- _mesa_lookup_enum_by_nr(modeA));
-
- if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlendEquationSeparateEXT not supported by driver");
- return;
- }
-
- if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
- return;
- }
-
- if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
- return;
- }
-
- numBuffers = ctx->Extensions.ARB_draw_buffers_blend
- ? ctx->Const.MaxDrawBuffers : 1;
-
- changed = GL_FALSE;
- for (buf = 0; buf < numBuffers; buf++) {
- if (ctx->Color.Blend[buf].EquationRGB != modeRGB ||
- ctx->Color.Blend[buf].EquationA != modeA) {
- changed = GL_TRUE;
- break;
- }
- }
- if (!changed)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- for (buf = 0; buf < numBuffers; buf++) {
- ctx->Color.Blend[buf].EquationRGB = modeRGB;
- ctx->Color.Blend[buf].EquationA = modeA;
- }
- ctx->Color._BlendEquationPerBuffer = GL_FALSE;
-
- if (ctx->Driver.BlendEquationSeparate)
- ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA);
-}
-
-
-/**
- * Set separate blend equations for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf,
- _mesa_lookup_enum_by_nr(modeRGB),
- _mesa_lookup_enum_by_nr(modeA));
-
- if (buf >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)",
- buf);
- return;
- }
-
- if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)");
- return;
- }
-
- if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)");
- return;
- }
-
- if (ctx->Color.Blend[buf].EquationRGB == modeRGB &&
- ctx->Color.Blend[buf].EquationA == modeA)
- return; /* no change */
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.Blend[buf].EquationRGB = modeRGB;
- ctx->Color.Blend[buf].EquationA = modeA;
- ctx->Color._BlendEquationPerBuffer = GL_TRUE;
-
- if (ctx->Driver.BlendEquationSeparatei)
- ctx->Driver.BlendEquationSeparatei(ctx, buf, modeRGB, modeA);
-}
-
-
-
-#endif /* _HAVE_FULL_GL */
-
-
-/**
- * Set the blending color.
- *
- * \param red red color component.
- * \param green green color component.
- * \param blue blue color component.
- * \param alpha alpha color component.
- *
- * \sa glBlendColor().
- *
- * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
- * change, flushes the vertices and notifies the driver via
- * dd_function_table::BlendColor callback.
- */
-void GLAPIENTRY
-_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
-{
- GLfloat tmp[4];
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- tmp[0] = red;
- tmp[1] = green;
- tmp[2] = blue;
- tmp[3] = alpha;
-
- if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped))
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- COPY_4FV( ctx->Color.BlendColorUnclamped, tmp );
-
- ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F);
- ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F);
- ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F);
- ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F);
-
- if (ctx->Driver.BlendColor)
- (*ctx->Driver.BlendColor)(ctx, ctx->Color.BlendColor);
-}
-
-
-/**
- * Specify the alpha test function.
- *
- * \param func alpha comparison function.
- * \param ref reference value.
- *
- * Verifies the parameters and updates gl_colorbuffer_attrib.
- * On a change, flushes the vertices and notifies the driver via
- * dd_function_table::AlphaFunc callback.
- */
-void GLAPIENTRY
-_mesa_AlphaFunc( GLenum func, GLclampf ref )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n",
- _mesa_lookup_enum_by_nr(func), ref);
-
- switch (func) {
- case GL_NEVER:
- case GL_LESS:
- case GL_EQUAL:
- case GL_LEQUAL:
- case GL_GREATER:
- case GL_NOTEQUAL:
- case GL_GEQUAL:
- case GL_ALWAYS:
- if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref)
- return; /* no change */
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.AlphaFunc = func;
- ctx->Color.AlphaRefUnclamped = ref;
- ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F);
-
- if (ctx->Driver.AlphaFunc)
- ctx->Driver.AlphaFunc(ctx, func, ctx->Color.AlphaRef);
- return;
-
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
- return;
- }
-}
-
-
-/**
- * Specify a logic pixel operation for color index rendering.
- *
- * \param opcode operation.
- *
- * Verifies that \p opcode is a valid enum and updates
-gl_colorbuffer_attrib::LogicOp.
- * On a change, flushes the vertices and notifies the driver via the
- * dd_function_table::LogicOpcode callback.
- */
-void GLAPIENTRY
-_mesa_LogicOp( GLenum opcode )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode));
-
- switch (opcode) {
- case GL_CLEAR:
- case GL_SET:
- case GL_COPY:
- case GL_COPY_INVERTED:
- case GL_NOOP:
- case GL_INVERT:
- case GL_AND:
- case GL_NAND:
- case GL_OR:
- case GL_NOR:
- case GL_XOR:
- case GL_EQUIV:
- case GL_AND_REVERSE:
- case GL_AND_INVERTED:
- case GL_OR_REVERSE:
- case GL_OR_INVERTED:
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
- return;
- }
-
- if (ctx->Color.LogicOp == opcode)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.LogicOp = opcode;
-
- if (ctx->Driver.LogicOpcode)
- ctx->Driver.LogicOpcode( ctx, opcode );
-}
-
-#if _HAVE_FULL_GL
-void GLAPIENTRY
-_mesa_IndexMask( GLuint mask )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (ctx->Color.IndexMask == mask)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.IndexMask = mask;
-}
-#endif
-
-
-/**
- * Enable or disable writing of frame buffer color components.
- *
- * \param red whether to mask writing of the red color component.
- * \param green whether to mask writing of the green color component.
- * \param blue whether to mask writing of the blue color component.
- * \param alpha whether to mask writing of the alpha color component.
- *
- * \sa glColorMask().
- *
- * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
- * change, flushes the vertices and notifies the driver via the
- * dd_function_table::ColorMask callback.
- */
-void GLAPIENTRY
-_mesa_ColorMask( GLboolean red, GLboolean green,
- GLboolean blue, GLboolean alpha )
-{
- GET_CURRENT_CONTEXT(ctx);
- GLubyte tmp[4];
- GLuint i;
- GLboolean flushed;
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
- red, green, blue, alpha);
-
- /* Shouldn't have any information about channel depth in core mesa
- * -- should probably store these as the native booleans:
- */
- tmp[RCOMP] = red ? 0xff : 0x0;
- tmp[GCOMP] = green ? 0xff : 0x0;
- tmp[BCOMP] = blue ? 0xff : 0x0;
- tmp[ACOMP] = alpha ? 0xff : 0x0;
-
- flushed = GL_FALSE;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
- if (!flushed) {
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- }
- flushed = GL_TRUE;
- COPY_4UBV(ctx->Color.ColorMask[i], tmp);
- }
- }
-
- if (ctx->Driver.ColorMask)
- ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
-}
-
-
-/**
- * For GL_EXT_draw_buffers2 and GL3
- */
-void GLAPIENTRY
-_mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
- GLboolean blue, GLboolean alpha )
-{
- GLubyte tmp[4];
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
- buf, red, green, blue, alpha);
-
- if (buf >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
- return;
- }
-
- /* Shouldn't have any information about channel depth in core mesa
- * -- should probably store these as the native booleans:
- */
- tmp[RCOMP] = red ? 0xff : 0x0;
- tmp[GCOMP] = green ? 0xff : 0x0;
- tmp[BCOMP] = blue ? 0xff : 0x0;
- tmp[ACOMP] = alpha ? 0xff : 0x0;
-
- if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
-
- if (ctx->Driver.ColorMaskIndexed)
- ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
-}
-
-
-void GLAPIENTRY
-_mesa_ClampColorARB(GLenum target, GLenum clamp)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
- return;
- }
-
- switch (target) {
- case GL_CLAMP_VERTEX_COLOR_ARB:
- FLUSH_VERTICES(ctx, _NEW_LIGHT);
- ctx->Light.ClampVertexColor = clamp;
- break;
- case GL_CLAMP_FRAGMENT_COLOR_ARB:
- FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
- ctx->Color.ClampFragmentColor = clamp;
- break;
- case GL_CLAMP_READ_COLOR_ARB:
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.ClampReadColor = clamp;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
- return;
- }
-}
-
-
-
-
-/**********************************************************************/
-/** \name Initialization */
-/*@{*/
-
-/**
- * Initialization of the context's Color attribute group.
- *
- * \param ctx GL context.
- *
- * Initializes the related fields in the context color attribute group,
- * __struct gl_contextRec::Color.
- */
-void _mesa_init_color( struct gl_context * ctx )
-{
- GLuint i;
-
- /* Color buffer group */
- ctx->Color.IndexMask = ~0u;
- memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
- ctx->Color.ClearIndex = 0;
- ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
- ASSIGN_4V( ctx->Color.ClearColorUnclamped, 0, 0, 0, 0 );
- ctx->Color.AlphaEnabled = GL_FALSE;
- ctx->Color.AlphaFunc = GL_ALWAYS;
- ctx->Color.AlphaRef = 0;
- ctx->Color.BlendEnabled = 0x0;
- for (i = 0; i < Elements(ctx->Color.Blend); i++) {
- ctx->Color.Blend[i].SrcRGB = GL_ONE;
- ctx->Color.Blend[i].DstRGB = GL_ZERO;
- ctx->Color.Blend[i].SrcA = GL_ONE;
- ctx->Color.Blend[i].DstA = GL_ZERO;
- ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD;
- ctx->Color.Blend[i].EquationA = GL_FUNC_ADD;
- }
- ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 );
- ctx->Color.IndexLogicOpEnabled = GL_FALSE;
- ctx->Color.ColorLogicOpEnabled = GL_FALSE;
- ctx->Color._LogicOpEnabled = GL_FALSE;
- ctx->Color.LogicOp = GL_COPY;
- ctx->Color.DitherFlag = GL_TRUE;
-
- if (ctx->Visual.doubleBufferMode) {
- ctx->Color.DrawBuffer[0] = GL_BACK;
- }
- else {
- ctx->Color.DrawBuffer[0] = GL_FRONT;
- }
-
- ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
- ctx->Color._ClampFragmentColor = GL_TRUE;
- ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
- ctx->Color._ClampReadColor = GL_TRUE;
-}
-
-/*@}*/
+/** + * \file blend.c + * Blending operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.5.1 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#include "glheader.h" +#include "blend.h" +#include "context.h" +#include "enums.h" +#include "macros.h" +#include "mtypes.h" + + + +/** + * Check if given blend source factor is legal. + * \return GL_TRUE if legal, GL_FALSE otherwise. + */ +static GLboolean +legal_src_factor(const struct gl_context *ctx, GLenum factor) +{ + switch (factor) { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + return ctx->Extensions.NV_blend_square; + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Check if given blend destination factor is legal. + * \return GL_TRUE if legal, GL_FALSE otherwise. + */ +static GLboolean +legal_dst_factor(const struct gl_context *ctx, GLenum factor) +{ + switch (factor) { + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + return ctx->Extensions.NV_blend_square; + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Check if src/dest RGB/A blend factors are legal. If not generate + * a GL error. + * \return GL_TRUE if factors are legal, GL_FALSE otherwise. + */ +static GLboolean +validate_blend_factors(struct gl_context *ctx, const char *func, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + if (!legal_src_factor(ctx, sfactorRGB)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(sfactorRGB = %s)", func, + _mesa_lookup_enum_by_nr(sfactorRGB)); + return GL_FALSE; + } + + if (!legal_dst_factor(ctx, dfactorRGB)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(dfactorRGB = %s)", func, + _mesa_lookup_enum_by_nr(dfactorRGB)); + return GL_FALSE; + } + + if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(sfactorA = %s)", func, + _mesa_lookup_enum_by_nr(sfactorA)); + return GL_FALSE; + } + + if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(dfactorA = %s)", func, + _mesa_lookup_enum_by_nr(dfactorA)); + return GL_FALSE; + } + + return GL_TRUE; +} + + +/** + * Specify the blending operation. + * + * \param sfactor source factor operator. + * \param dfactor destination factor operator. + * + * \sa glBlendFunc, glBlendFuncSeparateEXT + */ +void GLAPIENTRY +_mesa_BlendFunc( GLenum sfactor, GLenum dfactor ) +{ + _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor); +} + + +/** + * Set the separate blend source/dest factors for all draw buffers. + * + * \param sfactorRGB RGB source factor operator. + * \param dfactorRGB RGB destination factor operator. + * \param sfactorA alpha source factor operator. + * \param dfactorA alpha destination factor operator. + */ +void GLAPIENTRY +_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ) +{ + GLuint buf, numBuffers; + GLboolean changed; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n", + _mesa_lookup_enum_by_nr(sfactorRGB), + _mesa_lookup_enum_by_nr(dfactorRGB), + _mesa_lookup_enum_by_nr(sfactorA), + _mesa_lookup_enum_by_nr(dfactorA)); + + if (!validate_blend_factors(ctx, "glBlendFuncSeparate", + sfactorRGB, dfactorRGB, + sfactorA, dfactorA)) { + return; + } + + numBuffers = ctx->Extensions.ARB_draw_buffers_blend + ? ctx->Const.MaxDrawBuffers : 1; + + changed = GL_FALSE; + for (buf = 0; buf < numBuffers; buf++) { + if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB || + ctx->Color.Blend[buf].DstRGB != dfactorRGB || + ctx->Color.Blend[buf].SrcA != sfactorA || + ctx->Color.Blend[buf].DstA != dfactorA) { + changed = GL_TRUE; + break; + } + } + if (!changed) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + + for (buf = 0; buf < numBuffers; buf++) { + ctx->Color.Blend[buf].SrcRGB = sfactorRGB; + ctx->Color.Blend[buf].DstRGB = dfactorRGB; + ctx->Color.Blend[buf].SrcA = sfactorA; + ctx->Color.Blend[buf].DstA = dfactorA; + } + ctx->Color._BlendFuncPerBuffer = GL_FALSE; + + if (ctx->Driver.BlendFuncSeparate) { + ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB, + sfactorA, dfactorA); + } +} + + +#if _HAVE_FULL_GL + + +/** + * Set blend source/dest factors for one color buffer/target. + */ +void GLAPIENTRY +_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor) +{ + _mesa_BlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor); +} + + +/** + * Set separate blend source/dest factors for one color buffer/target. + */ +void GLAPIENTRY +_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.ARB_draw_buffers_blend) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()"); + return; + } + + if (buf >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)", + buf); + return; + } + + if (!validate_blend_factors(ctx, "glBlendFuncSeparatei", + sfactorRGB, dfactorRGB, + sfactorA, dfactorA)) { + return; + } + + if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB && + ctx->Color.Blend[buf].DstRGB == dfactorRGB && + ctx->Color.Blend[buf].SrcA == sfactorA && + ctx->Color.Blend[buf].DstA == dfactorA) + return; /* no change */ + + FLUSH_VERTICES(ctx, _NEW_COLOR); + + ctx->Color.Blend[buf].SrcRGB = sfactorRGB; + ctx->Color.Blend[buf].DstRGB = dfactorRGB; + ctx->Color.Blend[buf].SrcA = sfactorA; + ctx->Color.Blend[buf].DstA = dfactorA; + ctx->Color._BlendFuncPerBuffer = GL_TRUE; + + if (ctx->Driver.BlendFuncSeparatei) { + ctx->Driver.BlendFuncSeparatei(ctx, buf, sfactorRGB, dfactorRGB, + sfactorA, dfactorA); + } +} + + +/** + * Check if given blend equation is legal. + * \return GL_TRUE if legal, GL_FALSE otherwise. + */ +static GLboolean +legal_blend_equation(const struct gl_context *ctx, + GLenum mode, GLboolean is_separate) +{ + switch (mode) { + case GL_FUNC_ADD: + return GL_TRUE; + case GL_MIN: + case GL_MAX: + return ctx->Extensions.EXT_blend_minmax; + case GL_LOGIC_OP: + /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter. + */ + return ctx->Extensions.EXT_blend_logic_op && !is_separate; + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + return ctx->Extensions.EXT_blend_subtract; + default: + return GL_FALSE; + } +} + + +/* This is really an extension function! */ +void GLAPIENTRY +_mesa_BlendEquation( GLenum mode ) +{ + GLuint buf, numBuffers; + GLboolean changed; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBlendEquation(%s)\n", + _mesa_lookup_enum_by_nr(mode)); + + if (!legal_blend_equation(ctx, mode, GL_FALSE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); + return; + } + + numBuffers = ctx->Extensions.ARB_draw_buffers_blend + ? ctx->Const.MaxDrawBuffers : 1; + + changed = GL_FALSE; + for (buf = 0; buf < numBuffers; buf++) { + if (ctx->Color.Blend[buf].EquationRGB != mode || + ctx->Color.Blend[buf].EquationA != mode) { + changed = GL_TRUE; + break; + } + } + if (!changed) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + for (buf = 0; buf < numBuffers; buf++) { + ctx->Color.Blend[buf].EquationRGB = mode; + ctx->Color.Blend[buf].EquationA = mode; + } + ctx->Color._BlendEquationPerBuffer = GL_FALSE; + + if (ctx->Driver.BlendEquationSeparate) + (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode ); +} + + +/** + * Set blend equation for one color buffer/target. + */ +void GLAPIENTRY +_mesa_BlendEquationi(GLuint buf, GLenum mode) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n", + buf, _mesa_lookup_enum_by_nr(mode)); + + if (buf >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)", + buf); + return; + } + + if (!legal_blend_equation(ctx, mode, GL_FALSE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi"); + return; + } + + if (ctx->Color.Blend[buf].EquationRGB == mode && + ctx->Color.Blend[buf].EquationA == mode) + return; /* no change */ + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.Blend[buf].EquationRGB = mode; + ctx->Color.Blend[buf].EquationA = mode; + ctx->Color._BlendEquationPerBuffer = GL_TRUE; + + if (ctx->Driver.BlendEquationSeparatei) + ctx->Driver.BlendEquationSeparatei(ctx, buf, mode, mode); +} + + +void GLAPIENTRY +_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA ) +{ + GLuint buf, numBuffers; + GLboolean changed; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n", + _mesa_lookup_enum_by_nr(modeRGB), + _mesa_lookup_enum_by_nr(modeA)); + + if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlendEquationSeparateEXT not supported by driver"); + return; + } + + if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)"); + return; + } + + if (!legal_blend_equation(ctx, modeA, GL_TRUE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)"); + return; + } + + numBuffers = ctx->Extensions.ARB_draw_buffers_blend + ? ctx->Const.MaxDrawBuffers : 1; + + changed = GL_FALSE; + for (buf = 0; buf < numBuffers; buf++) { + if (ctx->Color.Blend[buf].EquationRGB != modeRGB || + ctx->Color.Blend[buf].EquationA != modeA) { + changed = GL_TRUE; + break; + } + } + if (!changed) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + for (buf = 0; buf < numBuffers; buf++) { + ctx->Color.Blend[buf].EquationRGB = modeRGB; + ctx->Color.Blend[buf].EquationA = modeA; + } + ctx->Color._BlendEquationPerBuffer = GL_FALSE; + + if (ctx->Driver.BlendEquationSeparate) + ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA); +} + + +/** + * Set separate blend equations for one color buffer/target. + */ +void GLAPIENTRY +_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf, + _mesa_lookup_enum_by_nr(modeRGB), + _mesa_lookup_enum_by_nr(modeA)); + + if (buf >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)", + buf); + return; + } + + if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)"); + return; + } + + if (!legal_blend_equation(ctx, modeA, GL_TRUE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)"); + return; + } + + if (ctx->Color.Blend[buf].EquationRGB == modeRGB && + ctx->Color.Blend[buf].EquationA == modeA) + return; /* no change */ + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.Blend[buf].EquationRGB = modeRGB; + ctx->Color.Blend[buf].EquationA = modeA; + ctx->Color._BlendEquationPerBuffer = GL_TRUE; + + if (ctx->Driver.BlendEquationSeparatei) + ctx->Driver.BlendEquationSeparatei(ctx, buf, modeRGB, modeA); +} + + + +#endif /* _HAVE_FULL_GL */ + + +/** + * Set the blending color. + * + * \param red red color component. + * \param green green color component. + * \param blue blue color component. + * \param alpha alpha color component. + * + * \sa glBlendColor(). + * + * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a + * change, flushes the vertices and notifies the driver via + * dd_function_table::BlendColor callback. + */ +void GLAPIENTRY +_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) +{ + GLfloat tmp[4]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + tmp[0] = red; + tmp[1] = green; + tmp[2] = blue; + tmp[3] = alpha; + + if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped)) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + COPY_4FV( ctx->Color.BlendColorUnclamped, tmp ); + + ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F); + ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F); + ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F); + ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F); + + if (ctx->Driver.BlendColor) + (*ctx->Driver.BlendColor)(ctx, ctx->Color.BlendColor); +} + + +/** + * Specify the alpha test function. + * + * \param func alpha comparison function. + * \param ref reference value. + * + * Verifies the parameters and updates gl_colorbuffer_attrib. + * On a change, flushes the vertices and notifies the driver via + * dd_function_table::AlphaFunc callback. + */ +void GLAPIENTRY +_mesa_AlphaFunc( GLenum func, GLclampf ref ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n", + _mesa_lookup_enum_by_nr(func), ref); + + switch (func) { + case GL_NEVER: + case GL_LESS: + case GL_EQUAL: + case GL_LEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + case GL_GEQUAL: + case GL_ALWAYS: + if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref) + return; /* no change */ + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.AlphaFunc = func; + ctx->Color.AlphaRefUnclamped = ref; + ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F); + + if (ctx->Driver.AlphaFunc) + ctx->Driver.AlphaFunc(ctx, func, ctx->Color.AlphaRef); + return; + + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" ); + return; + } +} + + +/** + * Specify a logic pixel operation for color index rendering. + * + * \param opcode operation. + * + * Verifies that \p opcode is a valid enum and updates +gl_colorbuffer_attrib::LogicOp. + * On a change, flushes the vertices and notifies the driver via the + * dd_function_table::LogicOpcode callback. + */ +void GLAPIENTRY +_mesa_LogicOp( GLenum opcode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode)); + + switch (opcode) { + case GL_CLEAR: + case GL_SET: + case GL_COPY: + case GL_COPY_INVERTED: + case GL_NOOP: + case GL_INVERT: + case GL_AND: + case GL_NAND: + case GL_OR: + case GL_NOR: + case GL_XOR: + case GL_EQUIV: + case GL_AND_REVERSE: + case GL_AND_INVERTED: + case GL_OR_REVERSE: + case GL_OR_INVERTED: + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" ); + return; + } + + if (ctx->Color.LogicOp == opcode) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.LogicOp = opcode; + + if (ctx->Driver.LogicOpcode) + ctx->Driver.LogicOpcode( ctx, opcode ); +} + +#if _HAVE_FULL_GL +void GLAPIENTRY +_mesa_IndexMask( GLuint mask ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->Color.IndexMask == mask) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.IndexMask = mask; +} +#endif + + +/** + * Enable or disable writing of frame buffer color components. + * + * \param red whether to mask writing of the red color component. + * \param green whether to mask writing of the green color component. + * \param blue whether to mask writing of the blue color component. + * \param alpha whether to mask writing of the alpha color component. + * + * \sa glColorMask(). + * + * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a + * change, flushes the vertices and notifies the driver via the + * dd_function_table::ColorMask callback. + */ +void GLAPIENTRY +_mesa_ColorMask( GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha ) +{ + GET_CURRENT_CONTEXT(ctx); + GLubyte tmp[4]; + GLuint i; + GLboolean flushed; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n", + red, green, blue, alpha); + + /* Shouldn't have any information about channel depth in core mesa + * -- should probably store these as the native booleans: + */ + tmp[RCOMP] = red ? 0xff : 0x0; + tmp[GCOMP] = green ? 0xff : 0x0; + tmp[BCOMP] = blue ? 0xff : 0x0; + tmp[ACOMP] = alpha ? 0xff : 0x0; + + flushed = GL_FALSE; + for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { + if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) { + if (!flushed) { + FLUSH_VERTICES(ctx, _NEW_COLOR); + } + flushed = GL_TRUE; + COPY_4UBV(ctx->Color.ColorMask[i], tmp); + } + } + + if (ctx->Driver.ColorMask) + ctx->Driver.ColorMask( ctx, red, green, blue, alpha ); +} + + +/** + * For GL_EXT_draw_buffers2 and GL3 + */ +void GLAPIENTRY +_mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha ) +{ + GLubyte tmp[4]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n", + buf, red, green, blue, alpha); + + if (buf >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf); + return; + } + + /* Shouldn't have any information about channel depth in core mesa + * -- should probably store these as the native booleans: + */ + tmp[RCOMP] = red ? 0xff : 0x0; + tmp[GCOMP] = green ? 0xff : 0x0; + tmp[BCOMP] = blue ? 0xff : 0x0; + tmp[ACOMP] = alpha ? 0xff : 0x0; + + if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf])) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + COPY_4UBV(ctx->Color.ColorMask[buf], tmp); + + if (ctx->Driver.ColorMaskIndexed) + ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha); +} + + +void GLAPIENTRY +_mesa_ClampColorARB(GLenum target, GLenum clamp) +{ + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)"); + return; + } + + switch (target) { + case GL_CLAMP_VERTEX_COLOR_ARB: + FLUSH_VERTICES(ctx, _NEW_LIGHT); + ctx->Light.ClampVertexColor = clamp; + break; + case GL_CLAMP_FRAGMENT_COLOR_ARB: + FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP); + ctx->Color.ClampFragmentColor = clamp; + break; + case GL_CLAMP_READ_COLOR_ARB: + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.ClampReadColor = clamp; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)"); + return; + } +} + + + + +/**********************************************************************/ +/** \name Initialization */ +/*@{*/ + +/** + * Initialization of the context's Color attribute group. + * + * \param ctx GL context. + * + * Initializes the related fields in the context color attribute group, + * __struct gl_contextRec::Color. + */ +void _mesa_init_color( struct gl_context * ctx ) +{ + GLuint i; + + /* Color buffer group */ + ctx->Color.IndexMask = ~0u; + memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask)); + ctx->Color.ClearIndex = 0; + ASSIGN_4V( ctx->Color.ClearColor.f, 0, 0, 0, 0 ); + ctx->Color.AlphaEnabled = GL_FALSE; + ctx->Color.AlphaFunc = GL_ALWAYS; + ctx->Color.AlphaRef = 0; + ctx->Color.BlendEnabled = 0x0; + for (i = 0; i < Elements(ctx->Color.Blend); i++) { + ctx->Color.Blend[i].SrcRGB = GL_ONE; + ctx->Color.Blend[i].DstRGB = GL_ZERO; + ctx->Color.Blend[i].SrcA = GL_ONE; + ctx->Color.Blend[i].DstA = GL_ZERO; + ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD; + ctx->Color.Blend[i].EquationA = GL_FUNC_ADD; + } + ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 ); + ctx->Color.IndexLogicOpEnabled = GL_FALSE; + ctx->Color.ColorLogicOpEnabled = GL_FALSE; + ctx->Color._LogicOpEnabled = GL_FALSE; + ctx->Color.LogicOp = GL_COPY; + ctx->Color.DitherFlag = GL_TRUE; + + if (ctx->Visual.doubleBufferMode) { + ctx->Color.DrawBuffer[0] = GL_BACK; + } + else { + ctx->Color.DrawBuffer[0] = GL_FRONT; + } + + ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB; + ctx->Color._ClampFragmentColor = GL_TRUE; + ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB; + ctx->Color._ClampReadColor = GL_TRUE; +} + +/*@}*/ diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c index fa95e4522..301fe694c 100644 --- a/mesalib/src/mesa/main/clear.c +++ b/mesalib/src/mesa/main/clear.c @@ -83,16 +83,11 @@ _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) tmp[2] = blue; tmp[3] = alpha; - if (TEST_EQ_4V(tmp, ctx->Color.ClearColorUnclamped)) + if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.f)) return; /* no change */ FLUSH_VERTICES(ctx, _NEW_COLOR); - COPY_4V(ctx->Color.ClearColorUnclamped, tmp); - - ctx->Color.ClearColor[0] = CLAMP(tmp[0], 0.0F, 1.0F); - ctx->Color.ClearColor[1] = CLAMP(tmp[1], 0.0F, 1.0F); - ctx->Color.ClearColor[2] = CLAMP(tmp[2], 0.0F, 1.0F); - ctx->Color.ClearColor[3] = CLAMP(tmp[3], 0.0F, 1.0F); + COPY_4V(ctx->Color.ClearColor.f, tmp); if (ctx->Driver.ClearColor) { /* it's OK to call glClearColor in CI mode but it should be a NOP */ @@ -110,25 +105,22 @@ _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) void GLAPIENTRY _mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a) { - GLfloat tmp[4]; + GLint tmp[4]; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - tmp[0] = (GLfloat) r; - tmp[1] = (GLfloat) g; - tmp[2] = (GLfloat) b; - tmp[3] = (GLfloat) a; + tmp[0] = r; + tmp[1] = g; + tmp[2] = b; + tmp[3] = a; - if (TEST_EQ_4V(tmp, ctx->Color.ClearColor)) + if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.i)) return; /* no change */ FLUSH_VERTICES(ctx, _NEW_COLOR); + COPY_4V(ctx->Color.ClearColor.i, tmp); - /* XXX we should eventually have a float/int/uint union for - * the ctx->Color.ClearColor state. - */ - COPY_4V(ctx->Color.ClearColor, tmp); - + /* these should be NOP calls for drivers supporting EXT_texture_integer */ if (ctx->Driver.ClearColor) { ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor); } @@ -141,25 +133,22 @@ _mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a) void GLAPIENTRY _mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a) { - GLfloat tmp[4]; + GLuint tmp[4]; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - tmp[0] = (GLfloat) r; - tmp[1] = (GLfloat) g; - tmp[2] = (GLfloat) b; - tmp[3] = (GLfloat) a; + tmp[0] = r; + tmp[1] = g; + tmp[2] = b; + tmp[3] = a; - if (TEST_EQ_4V(tmp, ctx->Color.ClearColor)) + if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.ui)) return; /* no change */ FLUSH_VERTICES(ctx, _NEW_COLOR); + COPY_4V(ctx->Color.ClearColor.ui, tmp); - /* XXX we should eventually have a float/int/uint union for - * the ctx->Color.ClearColor state. - */ - COPY_4V(ctx->Color.ClearColor, tmp); - + /* these should be NOP calls for drivers supporting EXT_texture_integer */ if (ctx->Driver.ClearColor) { ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor); } @@ -364,21 +353,18 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) return; } else if (mask) { - /* XXX note: we're putting the integer clear values into the - * floating point state var. This will not always work. We'll - * need a new ctx->Driver.ClearBuffer() hook.... - */ - GLclampf clearSave[4]; + union gl_color_union clearSave; + /* save color */ - COPY_4V(clearSave, ctx->Color.ClearColor); + clearSave = ctx->Color.ClearColor; /* set color */ - COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf); + COPY_4V(ctx->Color.ClearColor.i, value); if (ctx->Driver.ClearColor) ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor); /* clear buffer(s) */ ctx->Driver.Clear(ctx, mask); /* restore color */ - COPY_4V(ctx->Color.ClearColor, clearSave); + ctx->Color.ClearColor = clearSave; if (ctx->Driver.ClearColor) ctx->Driver.ClearColor(ctx, clearSave); } @@ -418,21 +404,18 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) return; } else if (mask) { - /* XXX note: we're putting the uint clear values into the - * floating point state var. This will not always work. We'll - * need a new ctx->Driver.ClearBuffer() hook.... - */ - GLclampf clearSave[4]; + union gl_color_union clearSave; + /* save color */ - COPY_4V(clearSave, ctx->Color.ClearColor); + clearSave = ctx->Color.ClearColor; /* set color */ - COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf); + COPY_4V(ctx->Color.ClearColor.ui, value); if (ctx->Driver.ClearColor) ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor); /* clear buffer(s) */ ctx->Driver.Clear(ctx, mask); /* restore color */ - COPY_4V(ctx->Color.ClearColor, clearSave); + ctx->Color.ClearColor = clearSave; if (ctx->Driver.ClearColor) ctx->Driver.ClearColor(ctx, clearSave); } @@ -495,17 +478,18 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) return; } else if (mask) { - GLclampf clearSave[4]; + union gl_color_union clearSave; + /* save color */ - COPY_4V(clearSave, ctx->Color.ClearColor); + clearSave = ctx->Color.ClearColor; /* set color */ - COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf); + COPY_4V_CAST(ctx->Color.ClearColor.f, value, GLclampf); if (ctx->Driver.ClearColor) ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor); /* clear buffer(s) */ ctx->Driver.Clear(ctx, mask); /* restore color */ - COPY_4V(ctx->Color.ClearColor, clearSave); + ctx->Color.ClearColor = clearSave; if (ctx->Driver.ClearColor) ctx->Driver.ClearColor(ctx, clearSave); } diff --git a/mesalib/src/mesa/main/colormac.h b/mesalib/src/mesa/main/colormac.h index d308c48b6..4b7c3b4a0 100644 --- a/mesalib/src/mesa/main/colormac.h +++ b/mesalib/src/mesa/main/colormac.h @@ -169,6 +169,17 @@ do { \ } while (0) +/** + * Convert four float values in [0,1] to ubytes in [0,255] with clamping. + */ +static inline void +_mesa_unclamped_float_rgba_to_ubyte(GLubyte dst[4], const GLfloat src[4]) +{ + int i; + for (i = 0; i < 4; i++) + UNCLAMPED_FLOAT_TO_UBYTE(dst[i], src[i]); +} + /** * \name Generic color packing macros. All inputs should be GLubytes. diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index b77e4f092..d6cc0196d 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -589,7 +589,8 @@ struct dd_function_table { GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA); /** Specify clear values for the color buffers */ - void (*ClearColor)(struct gl_context *ctx, const GLfloat color[4]); + void (*ClearColor)(struct gl_context *ctx, + const union gl_color_union color); /** Specify the clear value for the depth buffer */ void (*ClearDepth)(struct gl_context *ctx, GLclampd d); /** Specify the clear value for the stencil buffer */ diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 069254b18..a777bd8c4 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -1673,10 +1673,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped); break; case GL_COLOR_CLEAR_VALUE: - if(ctx->Color._ClampFragmentColor) - COPY_4FV(v->value_float_4, ctx->Color.ClearColor); - else - COPY_4FV(v->value_float_4, ctx->Color.ClearColorUnclamped); + if(ctx->Color._ClampFragmentColor) { + v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F); + v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F); + v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F); + v->value_float_4[3] = CLAMP(ctx->Color.ClearColor.f[3], 0.0F, 1.0F); + } else + COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f); break; case GL_BLEND_COLOR_EXT: if(ctx->Color._ClampFragmentColor) diff --git a/mesalib/src/mesa/main/image.c b/mesalib/src/mesa/main/image.c index 3e75e7c6b..66d7eec65 100644 --- a/mesalib/src/mesa/main/image.c +++ b/mesalib/src/mesa/main/image.c @@ -1513,12 +1513,8 @@ _mesa_convert_colors(GLenum srcType, const GLvoid *src, GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); GLuint i; for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]); - } + if (!mask || mask[i]) + _mesa_unclamped_float_rgba_to_ubyte(dst1[i], src4[i]); } if (useTemp) memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index ae500b4c2..8671ecda9 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -721,16 +721,26 @@ struct gl_accum_attrib /** + * Used for storing clear color, texture border color, etc. + * The float values are typically unclamped. + */ +union gl_color_union +{ + GLfloat f[4]; + GLint i[4]; + GLuint ui[4]; +}; + + +/** * Color buffer attribute group (GL_COLOR_BUFFER_BIT). */ struct gl_colorbuffer_attrib { - GLuint ClearIndex; /**< Index to use for glClear */ - GLfloat ClearColorUnclamped[4]; /**< Color to use for glClear*/ - GLclampf ClearColor[4]; /**< Color to use for glClear */ - - GLuint IndexMask; /**< Color index write mask */ - GLubyte ColorMask[MAX_DRAW_BUFFERS][4];/**< Each flag is 0xff or 0x0 */ + GLuint ClearIndex; /**< Index for glClear */ + union gl_color_union ClearColor; /**< Color for glClear, unclamped */ + GLuint IndexMask; /**< Color index write mask */ + GLubyte ColorMask[MAX_DRAW_BUFFERS][4]; /**< Each flag is 0xff or 0x0 */ GLenum DrawBuffer[MAX_DRAW_BUFFERS]; /**< Which buffer to draw into */ @@ -750,8 +760,8 @@ struct gl_colorbuffer_attrib /*@{*/ GLbitfield BlendEnabled; /**< Per-buffer blend enable flags */ - /* NOTE: this does _not_ depend on fragment clamping or any other clamping control, - * only on the fixed-pointness of the render target. + /* NOTE: this does _not_ depend on fragment clamping or any other clamping + * control, only on the fixed-pointness of the render target. * The query does however depend on fragment color clamping. */ GLfloat BlendColorUnclamped[4]; /**< Blending color */ @@ -1356,11 +1366,7 @@ struct gl_sampler_object GLenum WrapR; /**< R-axis texture image wrap mode */ GLenum MinFilter; /**< minification filter */ GLenum MagFilter; /**< magnification filter */ - union { - GLfloat f[4]; - GLuint ui[4]; - GLint i[4]; - } BorderColor; /**< Interpreted according to texture format */ + union gl_color_union BorderColor; /**< Interpreted according to texture format */ GLfloat MinLod; /**< min lambda, OpenGL 1.2 */ GLfloat MaxLod; /**< max lambda, OpenGL 1.2 */ GLfloat LodBias; /**< OpenGL 1.4 */ diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index b0f9c33b8..2323819aa 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -111,21 +111,43 @@ is_sampler_type(GLenum type) { switch (type) { case GL_SAMPLER_1D: + case GL_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_1D: case GL_SAMPLER_2D: + case GL_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_2D: case GL_SAMPLER_3D: + case GL_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_3D: case GL_SAMPLER_CUBE: + case GL_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: case GL_SAMPLER_CUBE_SHADOW: case GL_SAMPLER_2D_RECT_ARB: + case GL_INT_SAMPLER_2D_RECT: + case GL_UNSIGNED_INT_SAMPLER_2D_RECT: case GL_SAMPLER_2D_RECT_SHADOW_ARB: case GL_SAMPLER_1D_ARRAY_EXT: + case GL_INT_SAMPLER_1D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: case GL_SAMPLER_2D_ARRAY_EXT: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: case GL_SAMPLER_1D_ARRAY_SHADOW_EXT: case GL_SAMPLER_2D_ARRAY_SHADOW_EXT: case GL_SAMPLER_CUBE_MAP_ARRAY: case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: case GL_SAMPLER_BUFFER: + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return GL_TRUE; default: return GL_FALSE; diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index 117000ba7..a4799e3cc 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -323,9 +323,9 @@ clear_with_quad(struct gl_context *ctx, set_vertex_shader(st); if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { - st_translate_color(ctx->Color.ClearColorUnclamped, - ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, - clearColor); + st_translate_color(ctx->Color.ClearColor.f, + ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, + clearColor); } /* draw quad matching scissor rect */ @@ -582,12 +582,12 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { - st_translate_color(ctx->Color.ClearColor, - ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, - clearColor); + st_translate_color(ctx->Color.ClearColor.f, + ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, + clearColor); } - st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColorUnclamped, + st->pipe->clear(st->pipe, clear_buffers, clearColor, ctx->Depth.Clear, ctx->Stencil.Clear); } if (mask & BUFFER_BIT_ACCUM) diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index bd4f0860c..6eb8a506b 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -1441,8 +1441,9 @@ st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2) * This is used for translating texture border color and the clear * color. For example, the clear color is interpreted according to * the renderbuffer's base format. For example, if clearing a - * GL_LUMINANCE buffer, ClearColor[0] = luminance and ClearColor[1] = - * alpha. Similarly for texture border colors. + * GL_LUMINANCE buffer, we'll return colorOut[0] = colorOut[1] = + * colorOut[2] = colorIn[0]. + * Similarly for texture border colors. */ void st_translate_color(const GLfloat colorIn[4], GLenum baseFormat, diff --git a/mesalib/src/mesa/swrast/s_blend.c b/mesalib/src/mesa/swrast/s_blend.c index 125364913..3760f91d6 100644 --- a/mesalib/src/mesa/swrast/s_blend.c +++ b/mesalib/src/mesa/swrast/s_blend.c @@ -1,1014 +1,1010 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file swrast/s_blend.c
- * \brief software blending.
- * \author Brian Paul
- *
- * Only a few blend modes have been optimized (min, max, transparency, add)
- * more optimized cases can easily be added if needed.
- * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example.
- */
-
-
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/colormac.h"
-#include "main/macros.h"
-
-#include "s_blend.h"
-#include "s_context.h"
-#include "s_span.h"
-
-
-#if defined(USE_MMX_ASM)
-#include "x86/mmx.h"
-#include "x86/common_x86_asm.h"
-#define _BLENDAPI _ASMAPI
-#else
-#define _BLENDAPI
-#endif
-
-
-/**
- * Integer divide by 255
- * Declare "int divtemp" before using.
- * This satisfies Glean and should be reasonably fast.
- * Contributed by Nathan Hand.
- */
-#define DIV255(X) (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16)
-
-
-
-/**
- * Special case for glBlendFunc(GL_ZERO, GL_ONE).
- * No-op means the framebuffer values remain unchanged.
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLint bytes;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ZERO);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
- (void) ctx;
-
- /* just memcpy */
- if (chanType == GL_UNSIGNED_BYTE)
- bytes = 4 * n * sizeof(GLubyte);
- else if (chanType == GL_UNSIGNED_SHORT)
- bytes = 4 * n * sizeof(GLushort);
- else
- bytes = 4 * n * sizeof(GLfloat);
-
- memcpy(src, dst, bytes);
-}
-
-
-/**
- * Special case for glBlendFunc(GL_ONE, GL_ZERO)
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ZERO);
- (void) ctx;
- (void) n;
- (void) mask;
- (void) src;
- (void) dst;
-}
-
-
-/**
- * Common transparency blending mode:
- * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
- */
-static void _BLENDAPI
-blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- GLuint i;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(chanType == GL_UNSIGNED_BYTE);
-
- (void) ctx;
-
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- const GLint t = rgba[i][ACOMP]; /* t is in [0, 255] */
- if (t == 0) {
- /* 0% alpha */
- COPY_4UBV(rgba[i], dest[i]);
- }
- else if (t != 255) {
- GLint divtemp;
- const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
- const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
- const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
- const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP];
- ASSERT(r <= 255);
- ASSERT(g <= 255);
- ASSERT(b <= 255);
- ASSERT(a <= 255);
- rgba[i][RCOMP] = (GLubyte) r;
- rgba[i][GCOMP] = (GLubyte) g;
- rgba[i][BCOMP] = (GLubyte) b;
- rgba[i][ACOMP] = (GLubyte) a;
- }
- }
- }
-}
-
-
-static void _BLENDAPI
-blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- GLuint i;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(chanType == GL_UNSIGNED_SHORT);
-
- (void) ctx;
-
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- const GLint t = rgba[i][ACOMP];
- if (t == 0) {
- /* 0% alpha */
- COPY_4V(rgba[i], dest[i]);
- }
- else if (t != 65535) {
- const GLfloat tt = (GLfloat) t / 65535.0F;
- GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
- GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
- GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
- GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
- ASSIGN_4V(rgba[i], r, g, b, a);
- }
- }
- }
-}
-
-
-static void _BLENDAPI
-blend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- GLuint i;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(chanType == GL_FLOAT);
-
- (void) ctx;
-
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- const GLfloat t = rgba[i][ACOMP]; /* t in [0, 1] */
- if (t == 0.0F) {
- /* 0% alpha */
- COPY_4V(rgba[i], dest[i]);
- }
- else if (t != 1.0F) {
- GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP];
- GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP];
- GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP];
- GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP];
- ASSIGN_4V(rgba[i], r, g, b, a);
- }
- }
- }
-}
-
-
-
-/**
- * Add src and dest: glBlendFunc(GL_ONE, GL_ONE).
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLuint i;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
- (void) ctx;
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
- GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
- GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
- GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
- rgba[i][RCOMP] = (GLubyte) MIN2( r, 255 );
- rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 );
- rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 );
- rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 );
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
- GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
- GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
- GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
- rgba[i][RCOMP] = (GLshort) MIN2( r, 255 );
- rgba[i][GCOMP] = (GLshort) MIN2( g, 255 );
- rgba[i][BCOMP] = (GLshort) MIN2( b, 255 );
- rgba[i][ACOMP] = (GLshort) MIN2( a, 255 );
- }
- }
- }
- else {
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- ASSERT(chanType == GL_FLOAT);
- for (i=0;i<n;i++) {
- if (mask[i]) {
- /* don't RGB clamp to max */
- rgba[i][RCOMP] += dest[i][RCOMP];
- rgba[i][GCOMP] += dest[i][GCOMP];
- rgba[i][BCOMP] += dest[i][BCOMP];
- rgba[i][ACOMP] += dest[i][ACOMP];
- }
- }
- }
-}
-
-
-
-/**
- * Blend min function.
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLuint i;
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MIN);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_MIN);
- (void) ctx;
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
- rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
- rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
- rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
- rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
- rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
- rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
- }
- }
- }
- else {
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- ASSERT(chanType == GL_FLOAT);
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
- rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
- rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
- rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
- }
- }
- }
-}
-
-
-/**
- * Blend max function.
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLuint i;
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MAX);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_MAX);
- (void) ctx;
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
- rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
- rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
- rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
- rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
- rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
- rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
- }
- }
- }
- else {
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- ASSERT(chanType == GL_FLOAT);
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
- rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
- rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
- rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
- }
- }
- }
-}
-
-
-
-/**
- * Modulate: result = src * dest
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLuint i;
- (void) ctx;
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- GLint divtemp;
- rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]);
- rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]);
- rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]);
- rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]);
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
- rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
- rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
- rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
- }
- }
- }
- else {
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- ASSERT(chanType == GL_FLOAT);
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
- rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
- rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
- rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
- }
- }
- }
-}
-
-
-/**
- * Do any blending operation, using floating point.
- * \param n number of pixels
- * \param mask fragment writemask array
- * \param rgba array of incoming (and modified) pixels
- * \param dest array of pixels from the dest color buffer
- */
-static void
-blend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLfloat rgba[][4], GLfloat dest[][4],
- GLenum chanType)
-{
- GLuint i;
-
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- /* Incoming/source Color */
- const GLfloat Rs = rgba[i][RCOMP];
- const GLfloat Gs = rgba[i][GCOMP];
- const GLfloat Bs = rgba[i][BCOMP];
- const GLfloat As = rgba[i][ACOMP];
-
- /* Frame buffer/dest color */
- const GLfloat Rd = dest[i][RCOMP];
- const GLfloat Gd = dest[i][GCOMP];
- const GLfloat Bd = dest[i][BCOMP];
- const GLfloat Ad = dest[i][ACOMP];
-
- GLfloat sR, sG, sB, sA; /* Source factor */
- GLfloat dR, dG, dB, dA; /* Dest factor */
- GLfloat r, g, b, a; /* result color */
-
- /* XXX for the case of constant blend terms we could init
- * the sX and dX variables just once before the loop.
- */
-
- /* Source RGB factor */
- switch (ctx->Color.Blend[0].SrcRGB) {
- case GL_ZERO:
- sR = sG = sB = 0.0F;
- break;
- case GL_ONE:
- sR = sG = sB = 1.0F;
- break;
- case GL_DST_COLOR:
- sR = Rd;
- sG = Gd;
- sB = Bd;
- break;
- case GL_ONE_MINUS_DST_COLOR:
- sR = 1.0F - Rd;
- sG = 1.0F - Gd;
- sB = 1.0F - Bd;
- break;
- case GL_SRC_ALPHA:
- sR = sG = sB = As;
- break;
- case GL_ONE_MINUS_SRC_ALPHA:
- sR = sG = sB = 1.0F - As;
- break;
- case GL_DST_ALPHA:
- sR = sG = sB = Ad;
- break;
- case GL_ONE_MINUS_DST_ALPHA:
- sR = sG = sB = 1.0F - Ad;
- break;
- case GL_SRC_ALPHA_SATURATE:
- if (As < 1.0F - Ad) {
- sR = sG = sB = As;
- }
- else {
- sR = sG = sB = 1.0F - Ad;
- }
- break;
- case GL_CONSTANT_COLOR:
- sR = ctx->Color.BlendColor[0];
- sG = ctx->Color.BlendColor[1];
- sB = ctx->Color.BlendColor[2];
- break;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- sR = 1.0F - ctx->Color.BlendColor[0];
- sG = 1.0F - ctx->Color.BlendColor[1];
- sB = 1.0F - ctx->Color.BlendColor[2];
- break;
- case GL_CONSTANT_ALPHA:
- sR = sG = sB = ctx->Color.BlendColor[3];
- break;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
- break;
- case GL_SRC_COLOR:
- sR = Rs;
- sG = Gs;
- sB = Bs;
- break;
- case GL_ONE_MINUS_SRC_COLOR:
- sR = 1.0F - Rs;
- sG = 1.0F - Gs;
- sB = 1.0F - Bs;
- break;
- default:
- /* this should never happen */
- _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float");
- return;
- }
-
- /* Source Alpha factor */
- switch (ctx->Color.Blend[0].SrcA) {
- case GL_ZERO:
- sA = 0.0F;
- break;
- case GL_ONE:
- sA = 1.0F;
- break;
- case GL_DST_COLOR:
- sA = Ad;
- break;
- case GL_ONE_MINUS_DST_COLOR:
- sA = 1.0F - Ad;
- break;
- case GL_SRC_ALPHA:
- sA = As;
- break;
- case GL_ONE_MINUS_SRC_ALPHA:
- sA = 1.0F - As;
- break;
- case GL_DST_ALPHA:
- sA = Ad;
- break;
- case GL_ONE_MINUS_DST_ALPHA:
- sA = 1.0F - Ad;
- break;
- case GL_SRC_ALPHA_SATURATE:
- sA = 1.0;
- break;
- case GL_CONSTANT_COLOR:
- sA = ctx->Color.BlendColor[3];
- break;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- sA = 1.0F - ctx->Color.BlendColor[3];
- break;
- case GL_CONSTANT_ALPHA:
- sA = ctx->Color.BlendColor[3];
- break;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- sA = 1.0F - ctx->Color.BlendColor[3];
- break;
- case GL_SRC_COLOR:
- sA = As;
- break;
- case GL_ONE_MINUS_SRC_COLOR:
- sA = 1.0F - As;
- break;
- default:
- /* this should never happen */
- sA = 0.0F;
- _mesa_problem(ctx, "Bad blend source A factor in blend_general_float");
- return;
- }
-
- /* Dest RGB factor */
- switch (ctx->Color.Blend[0].DstRGB) {
- case GL_ZERO:
- dR = dG = dB = 0.0F;
- break;
- case GL_ONE:
- dR = dG = dB = 1.0F;
- break;
- case GL_SRC_COLOR:
- dR = Rs;
- dG = Gs;
- dB = Bs;
- break;
- case GL_ONE_MINUS_SRC_COLOR:
- dR = 1.0F - Rs;
- dG = 1.0F - Gs;
- dB = 1.0F - Bs;
- break;
- case GL_SRC_ALPHA:
- dR = dG = dB = As;
- break;
- case GL_ONE_MINUS_SRC_ALPHA:
- dR = dG = dB = 1.0F - As;
- break;
- case GL_DST_ALPHA:
- dR = dG = dB = Ad;
- break;
- case GL_ONE_MINUS_DST_ALPHA:
- dR = dG = dB = 1.0F - Ad;
- break;
- case GL_CONSTANT_COLOR:
- dR = ctx->Color.BlendColor[0];
- dG = ctx->Color.BlendColor[1];
- dB = ctx->Color.BlendColor[2];
- break;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- dR = 1.0F - ctx->Color.BlendColor[0];
- dG = 1.0F - ctx->Color.BlendColor[1];
- dB = 1.0F - ctx->Color.BlendColor[2];
- break;
- case GL_CONSTANT_ALPHA:
- dR = dG = dB = ctx->Color.BlendColor[3];
- break;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
- break;
- case GL_DST_COLOR:
- dR = Rd;
- dG = Gd;
- dB = Bd;
- break;
- case GL_ONE_MINUS_DST_COLOR:
- dR = 1.0F - Rd;
- dG = 1.0F - Gd;
- dB = 1.0F - Bd;
- break;
- default:
- /* this should never happen */
- dR = dG = dB = 0.0F;
- _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float");
- return;
- }
-
- /* Dest Alpha factor */
- switch (ctx->Color.Blend[0].DstA) {
- case GL_ZERO:
- dA = 0.0F;
- break;
- case GL_ONE:
- dA = 1.0F;
- break;
- case GL_SRC_COLOR:
- dA = As;
- break;
- case GL_ONE_MINUS_SRC_COLOR:
- dA = 1.0F - As;
- break;
- case GL_SRC_ALPHA:
- dA = As;
- break;
- case GL_ONE_MINUS_SRC_ALPHA:
- dA = 1.0F - As;
- break;
- case GL_DST_ALPHA:
- dA = Ad;
- break;
- case GL_ONE_MINUS_DST_ALPHA:
- dA = 1.0F - Ad;
- break;
- case GL_CONSTANT_COLOR:
- dA = ctx->Color.BlendColor[3];
- break;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- dA = 1.0F - ctx->Color.BlendColor[3];
- break;
- case GL_CONSTANT_ALPHA:
- dA = ctx->Color.BlendColor[3];
- break;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- dA = 1.0F - ctx->Color.BlendColor[3];
- break;
- case GL_DST_COLOR:
- dA = Ad;
- break;
- case GL_ONE_MINUS_DST_COLOR:
- dA = 1.0F - Ad;
- break;
- default:
- /* this should never happen */
- dA = 0.0F;
- _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float");
- return;
- }
-
- /* compute the blended RGB */
- switch (ctx->Color.Blend[0].EquationRGB) {
- case GL_FUNC_ADD:
- r = Rs * sR + Rd * dR;
- g = Gs * sG + Gd * dG;
- b = Bs * sB + Bd * dB;
- a = As * sA + Ad * dA;
- break;
- case GL_FUNC_SUBTRACT:
- r = Rs * sR - Rd * dR;
- g = Gs * sG - Gd * dG;
- b = Bs * sB - Bd * dB;
- a = As * sA - Ad * dA;
- break;
- case GL_FUNC_REVERSE_SUBTRACT:
- r = Rd * dR - Rs * sR;
- g = Gd * dG - Gs * sG;
- b = Bd * dB - Bs * sB;
- a = Ad * dA - As * sA;
- break;
- case GL_MIN:
- r = MIN2( Rd, Rs );
- g = MIN2( Gd, Gs );
- b = MIN2( Bd, Bs );
- break;
- case GL_MAX:
- r = MAX2( Rd, Rs );
- g = MAX2( Gd, Gs );
- b = MAX2( Bd, Bs );
- break;
- default:
- /* should never get here */
- r = g = b = 0.0F; /* silence uninitialized var warning */
- _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
- return;
- }
-
- /* compute the blended alpha */
- switch (ctx->Color.Blend[0].EquationA) {
- case GL_FUNC_ADD:
- a = As * sA + Ad * dA;
- break;
- case GL_FUNC_SUBTRACT:
- a = As * sA - Ad * dA;
- break;
- case GL_FUNC_REVERSE_SUBTRACT:
- a = Ad * dA - As * sA;
- break;
- case GL_MIN:
- a = MIN2( Ad, As );
- break;
- case GL_MAX:
- a = MAX2( Ad, As );
- break;
- default:
- /* should never get here */
- a = 0.0F; /* silence uninitialized var warning */
- _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
- return;
- }
-
- /* final clamping */
-#if 0
- rgba[i][RCOMP] = MAX2( r, 0.0F );
- rgba[i][GCOMP] = MAX2( g, 0.0F );
- rgba[i][BCOMP] = MAX2( b, 0.0F );
- rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F );
-#else
- ASSIGN_4V(rgba[i], r, g, b, a);
-#endif
- }
- }
-}
-
-
-/**
- * Do any blending operation, any chanType.
- */
-static void
-blend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- void *src, const void *dst, GLenum chanType)
-{
- GLfloat (*rgbaF)[4], (*destF)[4];
-
- rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
- destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
- if (!rgbaF || !destF) {
- free(rgbaF);
- free(destF);
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending");
- return;
- }
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- GLuint i;
- /* convert ubytes to floats */
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]);
- rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]);
- rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]);
- rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]);
- destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]);
- destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]);
- destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]);
- destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]);
- }
- }
- /* do blend */
- blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
- /* convert back to ubytes */
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][RCOMP], rgbaF[i][RCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][GCOMP], rgbaF[i][GCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][BCOMP], rgbaF[i][BCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][ACOMP], rgbaF[i][ACOMP]);
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- GLuint i;
- /* convert ushorts to floats */
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]);
- rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]);
- rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]);
- rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]);
- destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]);
- destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]);
- destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]);
- destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]);
- }
- }
- /* do blend */
- blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
- /* convert back to ushorts */
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]);
- UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]);
- UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]);
- UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]);
- }
- }
- }
- else {
- blend_general_float(ctx, n, mask, (GLfloat (*)[4]) src,
- (GLfloat (*)[4]) dst, chanType);
- }
-
- free(rgbaF);
- free(destF);
-}
-
-
-
-/**
- * Analyze current blending parameters to pick fastest blending function.
- * Result: the ctx->Color.BlendFunc pointer is updated.
- */
-void
-_swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType)
-{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
- const GLenum eq = ctx->Color.Blend[0].EquationRGB;
- const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
- const GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
- const GLenum srcA = ctx->Color.Blend[0].SrcA;
- const GLenum dstA = ctx->Color.Blend[0].DstA;
-
- if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) {
- swrast->BlendFunc = blend_general;
- }
- else if (eq == GL_MIN) {
- /* Note: GL_MIN ignores the blending weight factors */
-#if defined(USE_MMX_ASM)
- if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_min;
- }
- else
-#endif
- swrast->BlendFunc = blend_min;
- }
- else if (eq == GL_MAX) {
- /* Note: GL_MAX ignores the blending weight factors */
-#if defined(USE_MMX_ASM)
- if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_max;
- }
- else
-#endif
- swrast->BlendFunc = blend_max;
- }
- else if (srcRGB != srcA || dstRGB != dstA) {
- swrast->BlendFunc = blend_general;
- }
- else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA
- && dstRGB == GL_ONE_MINUS_SRC_ALPHA) {
-#if defined(USE_MMX_ASM)
- if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_transparency;
- }
- else
-#endif
- {
- if (chanType == GL_UNSIGNED_BYTE)
- swrast->BlendFunc = blend_transparency_ubyte;
- else if (chanType == GL_UNSIGNED_SHORT)
- swrast->BlendFunc = blend_transparency_ushort;
- else
- swrast->BlendFunc = blend_transparency_float;
- }
- }
- else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) {
-#if defined(USE_MMX_ASM)
- if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_add;
- }
- else
-#endif
- swrast->BlendFunc = blend_add;
- }
- else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT)
- && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR))
- ||
- ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT)
- && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) {
-#if defined(USE_MMX_ASM)
- if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_modulate;
- }
- else
-#endif
- swrast->BlendFunc = blend_modulate;
- }
- else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
- swrast->BlendFunc = blend_noop;
- }
- else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
- swrast->BlendFunc = blend_replace;
- }
- else {
- swrast->BlendFunc = blend_general;
- }
-}
-
-
-
-/**
- * Apply the blending operator to a span of pixels.
- * We can handle horizontal runs of pixels (spans) or arrays of x/y
- * pixel coordinates.
- */
-void
-_swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span)
-{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
- void *rbPixels;
-
- ASSERT(span->end <= MAX_WIDTH);
- ASSERT(span->arrayMask & SPAN_RGBA);
- ASSERT(rb->DataType == span->array->ChanType);
- ASSERT(!ctx->Color._LogicOpEnabled);
-
- rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
-
- swrast->BlendFunc(ctx, span->end, span->array->mask,
- span->array->rgba, rbPixels, span->array->ChanType);
-}
+/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file swrast/s_blend.c + * \brief software blending. + * \author Brian Paul + * + * Only a few blend modes have been optimized (min, max, transparency, add) + * more optimized cases can easily be added if needed. + * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example. + */ + + + +#include "main/glheader.h" +#include "main/context.h" +#include "main/colormac.h" +#include "main/macros.h" + +#include "s_blend.h" +#include "s_context.h" +#include "s_span.h" + + +#if defined(USE_MMX_ASM) +#include "x86/mmx.h" +#include "x86/common_x86_asm.h" +#define _BLENDAPI _ASMAPI +#else +#define _BLENDAPI +#endif + + +/** + * Integer divide by 255 + * Declare "int divtemp" before using. + * This satisfies Glean and should be reasonably fast. + * Contributed by Nathan Hand. + */ +#define DIV255(X) (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16) + + + +/** + * Special case for glBlendFunc(GL_ZERO, GL_ONE). + * No-op means the framebuffer values remain unchanged. + * Any chanType ok. + */ +static void _BLENDAPI +blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + GLint bytes; + + ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ZERO); + ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE); + (void) ctx; + + /* just memcpy */ + if (chanType == GL_UNSIGNED_BYTE) + bytes = 4 * n * sizeof(GLubyte); + else if (chanType == GL_UNSIGNED_SHORT) + bytes = 4 * n * sizeof(GLushort); + else + bytes = 4 * n * sizeof(GLfloat); + + memcpy(src, dst, bytes); +} + + +/** + * Special case for glBlendFunc(GL_ONE, GL_ZERO) + * Any chanType ok. + */ +static void _BLENDAPI +blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE); + ASSERT(ctx->Color.Blend[0].DstRGB == GL_ZERO); + (void) ctx; + (void) n; + (void) mask; + (void) src; + (void) dst; +} + + +/** + * Common transparency blending mode: + * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). + */ +static void _BLENDAPI +blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; + const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; + GLuint i; + + ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); + ASSERT(chanType == GL_UNSIGNED_BYTE); + + (void) ctx; + + for (i = 0; i < n; i++) { + if (mask[i]) { + const GLint t = rgba[i][ACOMP]; /* t is in [0, 255] */ + if (t == 0) { + /* 0% alpha */ + COPY_4UBV(rgba[i], dest[i]); + } + else if (t != 255) { + GLint divtemp; + const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP]; + const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP]; + const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP]; + const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP]; + ASSERT(r <= 255); + ASSERT(g <= 255); + ASSERT(b <= 255); + ASSERT(a <= 255); + rgba[i][RCOMP] = (GLubyte) r; + rgba[i][GCOMP] = (GLubyte) g; + rgba[i][BCOMP] = (GLubyte) b; + rgba[i][ACOMP] = (GLubyte) a; + } + } + } +} + + +static void _BLENDAPI +blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + GLushort (*rgba)[4] = (GLushort (*)[4]) src; + const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; + GLuint i; + + ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); + ASSERT(chanType == GL_UNSIGNED_SHORT); + + (void) ctx; + + for (i = 0; i < n; i++) { + if (mask[i]) { + const GLint t = rgba[i][ACOMP]; + if (t == 0) { + /* 0% alpha */ + COPY_4V(rgba[i], dest[i]); + } + else if (t != 65535) { + const GLfloat tt = (GLfloat) t / 65535.0F; + GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]); + GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]); + GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]); + GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]); + ASSIGN_4V(rgba[i], r, g, b, a); + } + } + } +} + + +static void _BLENDAPI +blend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; + const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; + GLuint i; + + ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); + ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); + ASSERT(chanType == GL_FLOAT); + + (void) ctx; + + for (i = 0; i < n; i++) { + if (mask[i]) { + const GLfloat t = rgba[i][ACOMP]; /* t in [0, 1] */ + if (t == 0.0F) { + /* 0% alpha */ + COPY_4V(rgba[i], dest[i]); + } + else if (t != 1.0F) { + GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP]; + GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP]; + GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP]; + GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP]; + ASSIGN_4V(rgba[i], r, g, b, a); + } + } + } +} + + + +/** + * Add src and dest: glBlendFunc(GL_ONE, GL_ONE). + * Any chanType ok. + */ +static void _BLENDAPI +blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + GLuint i; + + ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); + ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE); + ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE); + (void) ctx; + + if (chanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; + const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; + for (i=0;i<n;i++) { + if (mask[i]) { + GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; + GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; + GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; + GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; + rgba[i][RCOMP] = (GLubyte) MIN2( r, 255 ); + rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 ); + rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 ); + rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 ); + } + } + } + else if (chanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = (GLushort (*)[4]) src; + const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; + for (i=0;i<n;i++) { + if (mask[i]) { + GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; + GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; + GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; + GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; + rgba[i][RCOMP] = (GLshort) MIN2( r, 255 ); + rgba[i][GCOMP] = (GLshort) MIN2( g, 255 ); + rgba[i][BCOMP] = (GLshort) MIN2( b, 255 ); + rgba[i][ACOMP] = (GLshort) MIN2( a, 255 ); + } + } + } + else { + GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; + const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; + ASSERT(chanType == GL_FLOAT); + for (i=0;i<n;i++) { + if (mask[i]) { + /* don't RGB clamp to max */ + rgba[i][RCOMP] += dest[i][RCOMP]; + rgba[i][GCOMP] += dest[i][GCOMP]; + rgba[i][BCOMP] += dest[i][BCOMP]; + rgba[i][ACOMP] += dest[i][ACOMP]; + } + } + } +} + + + +/** + * Blend min function. + * Any chanType ok. + */ +static void _BLENDAPI +blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + GLuint i; + ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MIN); + ASSERT(ctx->Color.Blend[0].EquationA == GL_MIN); + (void) ctx; + + if (chanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; + const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } + } + else if (chanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = (GLushort (*)[4]) src; + const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } + } + else { + GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; + const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; + ASSERT(chanType == GL_FLOAT); + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } + } +} + + +/** + * Blend max function. + * Any chanType ok. + */ +static void _BLENDAPI +blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + GLuint i; + ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MAX); + ASSERT(ctx->Color.Blend[0].EquationA == GL_MAX); + (void) ctx; + + if (chanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; + const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } + } + else if (chanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = (GLushort (*)[4]) src; + const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } + } + else { + GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; + const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; + ASSERT(chanType == GL_FLOAT); + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } + } +} + + + +/** + * Modulate: result = src * dest + * Any chanType ok. + */ +static void _BLENDAPI +blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLvoid *src, const GLvoid *dst, GLenum chanType) +{ + GLuint i; + (void) ctx; + + if (chanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; + const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; + for (i=0;i<n;i++) { + if (mask[i]) { + GLint divtemp; + rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]); + rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]); + rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]); + rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]); + } + } + } + else if (chanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = (GLushort (*)[4]) src; + const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16; + rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16; + rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16; + rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16; + } + } + } + else { + GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; + const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; + ASSERT(chanType == GL_FLOAT); + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP]; + rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP]; + rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP]; + rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP]; + } + } + } +} + + +/** + * Do any blending operation, using floating point. + * \param n number of pixels + * \param mask fragment writemask array + * \param rgba array of incoming (and modified) pixels + * \param dest array of pixels from the dest color buffer + */ +static void +blend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[], + GLfloat rgba[][4], GLfloat dest[][4], + GLenum chanType) +{ + GLuint i; + + for (i = 0; i < n; i++) { + if (mask[i]) { + /* Incoming/source Color */ + const GLfloat Rs = rgba[i][RCOMP]; + const GLfloat Gs = rgba[i][GCOMP]; + const GLfloat Bs = rgba[i][BCOMP]; + const GLfloat As = rgba[i][ACOMP]; + + /* Frame buffer/dest color */ + const GLfloat Rd = dest[i][RCOMP]; + const GLfloat Gd = dest[i][GCOMP]; + const GLfloat Bd = dest[i][BCOMP]; + const GLfloat Ad = dest[i][ACOMP]; + + GLfloat sR, sG, sB, sA; /* Source factor */ + GLfloat dR, dG, dB, dA; /* Dest factor */ + GLfloat r, g, b, a; /* result color */ + + /* XXX for the case of constant blend terms we could init + * the sX and dX variables just once before the loop. + */ + + /* Source RGB factor */ + switch (ctx->Color.Blend[0].SrcRGB) { + case GL_ZERO: + sR = sG = sB = 0.0F; + break; + case GL_ONE: + sR = sG = sB = 1.0F; + break; + case GL_DST_COLOR: + sR = Rd; + sG = Gd; + sB = Bd; + break; + case GL_ONE_MINUS_DST_COLOR: + sR = 1.0F - Rd; + sG = 1.0F - Gd; + sB = 1.0F - Bd; + break; + case GL_SRC_ALPHA: + sR = sG = sB = As; + break; + case GL_ONE_MINUS_SRC_ALPHA: + sR = sG = sB = 1.0F - As; + break; + case GL_DST_ALPHA: + sR = sG = sB = Ad; + break; + case GL_ONE_MINUS_DST_ALPHA: + sR = sG = sB = 1.0F - Ad; + break; + case GL_SRC_ALPHA_SATURATE: + if (As < 1.0F - Ad) { + sR = sG = sB = As; + } + else { + sR = sG = sB = 1.0F - Ad; + } + break; + case GL_CONSTANT_COLOR: + sR = ctx->Color.BlendColor[0]; + sG = ctx->Color.BlendColor[1]; + sB = ctx->Color.BlendColor[2]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + sR = 1.0F - ctx->Color.BlendColor[0]; + sG = 1.0F - ctx->Color.BlendColor[1]; + sB = 1.0F - ctx->Color.BlendColor[2]; + break; + case GL_CONSTANT_ALPHA: + sR = sG = sB = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + sR = sG = sB = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_SRC_COLOR: + sR = Rs; + sG = Gs; + sB = Bs; + break; + case GL_ONE_MINUS_SRC_COLOR: + sR = 1.0F - Rs; + sG = 1.0F - Gs; + sB = 1.0F - Bs; + break; + default: + /* this should never happen */ + _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float"); + return; + } + + /* Source Alpha factor */ + switch (ctx->Color.Blend[0].SrcA) { + case GL_ZERO: + sA = 0.0F; + break; + case GL_ONE: + sA = 1.0F; + break; + case GL_DST_COLOR: + sA = Ad; + break; + case GL_ONE_MINUS_DST_COLOR: + sA = 1.0F - Ad; + break; + case GL_SRC_ALPHA: + sA = As; + break; + case GL_ONE_MINUS_SRC_ALPHA: + sA = 1.0F - As; + break; + case GL_DST_ALPHA: + sA = Ad; + break; + case GL_ONE_MINUS_DST_ALPHA: + sA = 1.0F - Ad; + break; + case GL_SRC_ALPHA_SATURATE: + sA = 1.0; + break; + case GL_CONSTANT_COLOR: + sA = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + sA = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_CONSTANT_ALPHA: + sA = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + sA = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_SRC_COLOR: + sA = As; + break; + case GL_ONE_MINUS_SRC_COLOR: + sA = 1.0F - As; + break; + default: + /* this should never happen */ + sA = 0.0F; + _mesa_problem(ctx, "Bad blend source A factor in blend_general_float"); + return; + } + + /* Dest RGB factor */ + switch (ctx->Color.Blend[0].DstRGB) { + case GL_ZERO: + dR = dG = dB = 0.0F; + break; + case GL_ONE: + dR = dG = dB = 1.0F; + break; + case GL_SRC_COLOR: + dR = Rs; + dG = Gs; + dB = Bs; + break; + case GL_ONE_MINUS_SRC_COLOR: + dR = 1.0F - Rs; + dG = 1.0F - Gs; + dB = 1.0F - Bs; + break; + case GL_SRC_ALPHA: + dR = dG = dB = As; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dR = dG = dB = 1.0F - As; + break; + case GL_DST_ALPHA: + dR = dG = dB = Ad; + break; + case GL_ONE_MINUS_DST_ALPHA: + dR = dG = dB = 1.0F - Ad; + break; + case GL_CONSTANT_COLOR: + dR = ctx->Color.BlendColor[0]; + dG = ctx->Color.BlendColor[1]; + dB = ctx->Color.BlendColor[2]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + dR = 1.0F - ctx->Color.BlendColor[0]; + dG = 1.0F - ctx->Color.BlendColor[1]; + dB = 1.0F - ctx->Color.BlendColor[2]; + break; + case GL_CONSTANT_ALPHA: + dR = dG = dB = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + dR = dG = dB = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_DST_COLOR: + dR = Rd; + dG = Gd; + dB = Bd; + break; + case GL_ONE_MINUS_DST_COLOR: + dR = 1.0F - Rd; + dG = 1.0F - Gd; + dB = 1.0F - Bd; + break; + default: + /* this should never happen */ + dR = dG = dB = 0.0F; + _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float"); + return; + } + + /* Dest Alpha factor */ + switch (ctx->Color.Blend[0].DstA) { + case GL_ZERO: + dA = 0.0F; + break; + case GL_ONE: + dA = 1.0F; + break; + case GL_SRC_COLOR: + dA = As; + break; + case GL_ONE_MINUS_SRC_COLOR: + dA = 1.0F - As; + break; + case GL_SRC_ALPHA: + dA = As; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dA = 1.0F - As; + break; + case GL_DST_ALPHA: + dA = Ad; + break; + case GL_ONE_MINUS_DST_ALPHA: + dA = 1.0F - Ad; + break; + case GL_CONSTANT_COLOR: + dA = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + dA = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_CONSTANT_ALPHA: + dA = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + dA = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_DST_COLOR: + dA = Ad; + break; + case GL_ONE_MINUS_DST_COLOR: + dA = 1.0F - Ad; + break; + default: + /* this should never happen */ + dA = 0.0F; + _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float"); + return; + } + + /* compute the blended RGB */ + switch (ctx->Color.Blend[0].EquationRGB) { + case GL_FUNC_ADD: + r = Rs * sR + Rd * dR; + g = Gs * sG + Gd * dG; + b = Bs * sB + Bd * dB; + a = As * sA + Ad * dA; + break; + case GL_FUNC_SUBTRACT: + r = Rs * sR - Rd * dR; + g = Gs * sG - Gd * dG; + b = Bs * sB - Bd * dB; + a = As * sA - Ad * dA; + break; + case GL_FUNC_REVERSE_SUBTRACT: + r = Rd * dR - Rs * sR; + g = Gd * dG - Gs * sG; + b = Bd * dB - Bs * sB; + a = Ad * dA - As * sA; + break; + case GL_MIN: + r = MIN2( Rd, Rs ); + g = MIN2( Gd, Gs ); + b = MIN2( Bd, Bs ); + break; + case GL_MAX: + r = MAX2( Rd, Rs ); + g = MAX2( Gd, Gs ); + b = MAX2( Bd, Bs ); + break; + default: + /* should never get here */ + r = g = b = 0.0F; /* silence uninitialized var warning */ + _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); + return; + } + + /* compute the blended alpha */ + switch (ctx->Color.Blend[0].EquationA) { + case GL_FUNC_ADD: + a = As * sA + Ad * dA; + break; + case GL_FUNC_SUBTRACT: + a = As * sA - Ad * dA; + break; + case GL_FUNC_REVERSE_SUBTRACT: + a = Ad * dA - As * sA; + break; + case GL_MIN: + a = MIN2( Ad, As ); + break; + case GL_MAX: + a = MAX2( Ad, As ); + break; + default: + /* should never get here */ + a = 0.0F; /* silence uninitialized var warning */ + _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); + return; + } + + /* final clamping */ +#if 0 + rgba[i][RCOMP] = MAX2( r, 0.0F ); + rgba[i][GCOMP] = MAX2( g, 0.0F ); + rgba[i][BCOMP] = MAX2( b, 0.0F ); + rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F ); +#else + ASSIGN_4V(rgba[i], r, g, b, a); +#endif + } + } +} + + +/** + * Do any blending operation, any chanType. + */ +static void +blend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[], + void *src, const void *dst, GLenum chanType) +{ + GLfloat (*rgbaF)[4], (*destF)[4]; + + rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat)); + destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat)); + if (!rgbaF || !destF) { + free(rgbaF); + free(destF); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending"); + return; + } + + if (chanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; + const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; + GLuint i; + /* convert ubytes to floats */ + for (i = 0; i < n; i++) { + if (mask[i]) { + rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]); + rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]); + rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]); + rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]); + destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]); + destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]); + destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]); + destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]); + } + } + /* do blend */ + blend_general_float(ctx, n, mask, rgbaF, destF, chanType); + /* convert back to ubytes */ + for (i = 0; i < n; i++) { + if (mask[i]) + _mesa_unclamped_float_rgba_to_ubyte(rgba[i], rgbaF[i]); + } + } + else if (chanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = (GLushort (*)[4]) src; + const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; + GLuint i; + /* convert ushorts to floats */ + for (i = 0; i < n; i++) { + if (mask[i]) { + rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]); + rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]); + rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]); + rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]); + destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]); + destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]); + destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]); + destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]); + } + } + /* do blend */ + blend_general_float(ctx, n, mask, rgbaF, destF, chanType); + /* convert back to ushorts */ + for (i = 0; i < n; i++) { + if (mask[i]) { + UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]); + } + } + } + else { + blend_general_float(ctx, n, mask, (GLfloat (*)[4]) src, + (GLfloat (*)[4]) dst, chanType); + } + + free(rgbaF); + free(destF); +} + + + +/** + * Analyze current blending parameters to pick fastest blending function. + * Result: the ctx->Color.BlendFunc pointer is updated. + */ +void +_swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLenum eq = ctx->Color.Blend[0].EquationRGB; + const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB; + const GLenum dstRGB = ctx->Color.Blend[0].DstRGB; + const GLenum srcA = ctx->Color.Blend[0].SrcA; + const GLenum dstA = ctx->Color.Blend[0].DstA; + + if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) { + swrast->BlendFunc = blend_general; + } + else if (eq == GL_MIN) { + /* Note: GL_MIN ignores the blending weight factors */ +#if defined(USE_MMX_ASM) + if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { + swrast->BlendFunc = _mesa_mmx_blend_min; + } + else +#endif + swrast->BlendFunc = blend_min; + } + else if (eq == GL_MAX) { + /* Note: GL_MAX ignores the blending weight factors */ +#if defined(USE_MMX_ASM) + if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { + swrast->BlendFunc = _mesa_mmx_blend_max; + } + else +#endif + swrast->BlendFunc = blend_max; + } + else if (srcRGB != srcA || dstRGB != dstA) { + swrast->BlendFunc = blend_general; + } + else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA + && dstRGB == GL_ONE_MINUS_SRC_ALPHA) { +#if defined(USE_MMX_ASM) + if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { + swrast->BlendFunc = _mesa_mmx_blend_transparency; + } + else +#endif + { + if (chanType == GL_UNSIGNED_BYTE) + swrast->BlendFunc = blend_transparency_ubyte; + else if (chanType == GL_UNSIGNED_SHORT) + swrast->BlendFunc = blend_transparency_ushort; + else + swrast->BlendFunc = blend_transparency_float; + } + } + else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) { +#if defined(USE_MMX_ASM) + if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { + swrast->BlendFunc = _mesa_mmx_blend_add; + } + else +#endif + swrast->BlendFunc = blend_add; + } + else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT) + && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR)) + || + ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT) + && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) { +#if defined(USE_MMX_ASM) + if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { + swrast->BlendFunc = _mesa_mmx_blend_modulate; + } + else +#endif + swrast->BlendFunc = blend_modulate; + } + else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) { + swrast->BlendFunc = blend_noop; + } + else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) { + swrast->BlendFunc = blend_replace; + } + else { + swrast->BlendFunc = blend_general; + } +} + + + +/** + * Apply the blending operator to a span of pixels. + * We can handle horizontal runs of pixels (spans) or arrays of x/y + * pixel coordinates. + */ +void +_swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + void *rbPixels; + + ASSERT(span->end <= MAX_WIDTH); + ASSERT(span->arrayMask & SPAN_RGBA); + ASSERT(rb->DataType == span->array->ChanType); + ASSERT(!ctx->Color._LogicOpEnabled); + + rbPixels = _swrast_get_dest_rgba(ctx, rb, span); + + swrast->BlendFunc(ctx, span->end, span->array->mask, + span->array->rgba, rbPixels, span->array->ChanType); +} diff --git a/mesalib/src/mesa/swrast/s_clear.c b/mesalib/src/mesa/swrast/s_clear.c index 9e9b53116..980d29bba 100644 --- a/mesalib/src/mesa/swrast/s_clear.c +++ b/mesalib/src/mesa/swrast/s_clear.c @@ -60,20 +60,17 @@ clear_rgba_buffer_with_masking(struct gl_context *ctx, struct gl_renderbuffer *r span.array->ChanType = rb->DataType; if (span.array->ChanType == GL_UNSIGNED_BYTE) { GLubyte clearColor[4]; - UNCLAMPED_FLOAT_TO_UBYTE(clearColor[RCOMP], ctx->Color.ClearColor[0]); - UNCLAMPED_FLOAT_TO_UBYTE(clearColor[GCOMP], ctx->Color.ClearColor[1]); - UNCLAMPED_FLOAT_TO_UBYTE(clearColor[BCOMP], ctx->Color.ClearColor[2]); - UNCLAMPED_FLOAT_TO_UBYTE(clearColor[ACOMP], ctx->Color.ClearColor[3]); + _mesa_unclamped_float_rgba_to_ubyte(clearColor, ctx->Color.ClearColor.f); for (i = 0; i < width; i++) { COPY_4UBV(span.array->rgba[i], clearColor); } } else if (span.array->ChanType == GL_UNSIGNED_SHORT) { GLushort clearColor[4]; - UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor[0]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor[1]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor[2]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor[3]); + UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor.f[0]); + UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor.f[1]); + UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor.f[2]); + UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor.f[3]); for (i = 0; i < width; i++) { COPY_4V_CAST(span.array->rgba[i], clearColor, GLchan); } @@ -81,10 +78,10 @@ clear_rgba_buffer_with_masking(struct gl_context *ctx, struct gl_renderbuffer *r else { ASSERT(span.array->ChanType == GL_FLOAT); for (i = 0; i < width; i++) { - CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor[0]); - CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor[1]); - CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor[2]); - CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor[3]); + UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor.f[0]); + UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor.f[1]); + UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor.f[2]); + UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor.f[3]); } } @@ -115,6 +112,7 @@ clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint buf GLubyte clear8[4]; GLushort clear16[4]; GLvoid *clearVal; + GLfloat clearFloat[4]; GLint i; ASSERT(ctx->Color.ColorMask[buf][0] && @@ -126,21 +124,22 @@ clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint buf switch (rb->DataType) { case GL_UNSIGNED_BYTE: - UNCLAMPED_FLOAT_TO_UBYTE(clear8[0], ctx->Color.ClearColor[0]); - UNCLAMPED_FLOAT_TO_UBYTE(clear8[1], ctx->Color.ClearColor[1]); - UNCLAMPED_FLOAT_TO_UBYTE(clear8[2], ctx->Color.ClearColor[2]); - UNCLAMPED_FLOAT_TO_UBYTE(clear8[3], ctx->Color.ClearColor[3]); + _mesa_unclamped_float_rgba_to_ubyte(clear8, ctx->Color.ClearColor.f); clearVal = clear8; break; case GL_UNSIGNED_SHORT: - UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor[0]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor[1]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor[2]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor[3]); + UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor.f[0]); + UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor.f[1]); + UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor.f[2]); + UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor.f[3]); clearVal = clear16; break; case GL_FLOAT: - clearVal = ctx->Color.ClearColor; + clearFloat[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F); + clearFloat[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F); + clearFloat[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F); + clearFloat[3] = CLAMP(ctx->Color.ClearColor.f[3], 0.0F, 1.0F); + clearVal = clearFloat; break; default: _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer"); |