Bug 696889 - Upgrade ANGLE to r802 - no review
authorBenoit Jacob <bjacob@mozilla.com>
Tue, 25 Oct 2011 08:58:43 -0400
changeset 79195 dd18ab29d0e834dd771ed085581b2213a48cea1b
parent 79194 df2b31a1e4c43040d153d945573ca56df6342d12
child 79196 3131f4933dd48026d607276cfb72e9148481d149
push id21377
push userbmo@edmorley.co.uk
push dateWed, 26 Oct 2011 00:52:20 +0000
treeherdermozilla-central@cc66accc8181 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs696889
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 696889 - Upgrade ANGLE to r802 - no review This is syncing us with the ANGLE project at http://code.google.com/p/angleproject/ Also, with this new ANGLE revision, two WebGL conformance tests are now passing on windows so this patch removes them from failing_tests_windows.txt.
content/canvas/test/webgl/failing_tests_windows.txt
gfx/angle/CONTRIBUTORS
gfx/angle/DEPS
gfx/angle/README.mozilla
gfx/angle/angle-instrinsic-msvc2005.patch
gfx/angle/angle-intrinsic-msvc2005.patch
gfx/angle/angle-nspr-misc.patch
gfx/angle/angle-use-xmalloc.patch
gfx/angle/build/common.gypi
gfx/angle/extensions/ANGLE_translated_shader_source.txt
gfx/angle/extensions/EGL_ANGLE_software_display.txt
gfx/angle/include/GLES2/gl2ext.h
gfx/angle/include/GLSLANG/ShaderLang.h
gfx/angle/samples/build_samples.gyp
gfx/angle/samples/translator/translator.cpp
gfx/angle/src/common/debug.cpp
gfx/angle/src/common/version.h
gfx/angle/src/compiler/OutputHLSL.cpp
gfx/angle/src/compiler/UnfoldSelect.cpp
gfx/angle/src/compiler/UnfoldSelect.h
gfx/angle/src/compiler/intermOut.cpp
gfx/angle/src/libGLESv2/Context.cpp
gfx/angle/src/libGLESv2/Context.h
gfx/angle/src/libGLESv2/Framebuffer.cpp
gfx/angle/src/libGLESv2/Program.cpp
gfx/angle/src/libGLESv2/Program.h
gfx/angle/src/libGLESv2/Shader.cpp
gfx/angle/src/libGLESv2/Shader.h
gfx/angle/src/libGLESv2/libGLESv2.cpp
gfx/angle/src/libGLESv2/libGLESv2.def
gfx/angle/src/libGLESv2/utilities.cpp
gfx/angle/src/libGLESv2/utilities.h
--- a/content/canvas/test/webgl/failing_tests_windows.txt
+++ b/content/canvas/test/webgl/failing_tests_windows.txt
@@ -1,16 +1,14 @@
 conformance/canvas/buffer-preserve-test.html
 conformance/context/premultiplyalpha-test.html
 conformance/glsl/functions/glsl-function-atan.html
 conformance/glsl/functions/glsl-function-atan-xy.html
 conformance/glsl/functions/glsl-function-mod-gentype.html
-conformance/glsl/misc/glsl-function-nodes.html
 conformance/glsl/misc/glsl-long-variable-names.html
 conformance/glsl/misc/shader-with-256-character-identifier.frag.html
 conformance/glsl/misc/shader-with-long-line.html
-conformance/glsl/variables/gl-frontfacing.html
 conformance/reading/read-pixels-test.html
 conformance/renderbuffers/framebuffer-object-attachment.html
 conformance/more/conformance/quickCheckAPI-S_V.html
 conformance/more/functions/copyTexImage2D.html
 conformance/more/functions/copyTexSubImage2D.html
 conformance/more/functions/uniformfArrayLen1.html
--- a/gfx/angle/CONTRIBUTORS
+++ b/gfx/angle/CONTRIBUTORS
@@ -23,20 +23,23 @@ Google Inc.
  Daniel Nicoara
  Alastair Patrick
  Alok Priyadarshi
  Kenneth Russell
  Ben Vanik
  Adrienne Walker
 
 Mozilla Corp.
+ Ehsan Akhgari
  Benoit Jacob
  Makoto Kato
  Vladimir Vukicevic
 
 Apple Inc.
  David Kilzer
 
 Aitor Moreno <aitormoreno at gmail.com>
 Jim Hauxwell <james at dattrax.co.uk>
 ddefrostt
 timeless
 Yore Apex
+Mark Callow
+
--- a/gfx/angle/DEPS
+++ b/gfx/angle/DEPS
@@ -1,11 +1,11 @@
 deps = {
   "trunk/third_party/gyp":
-      "http://gyp.googlecode.com/svn/trunk@800",
+      "http://gyp.googlecode.com/svn/trunk@1080",
 }
 
 hooks = [
   {
     # A change to a .gyp, .gypi, or to GYP itself should run the generator.
     "pattern": ".",
     "action": ["python", "trunk/build/gyp_angle"],
   },
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -1,22 +1,19 @@
 This is the ANGLE project, from http://code.google.com/p/angleproject/
 
-Current revision: r774
+Current revision: r802
 
 == Applied local patches ==
 
 In this order:
-  angle-nspr-misc.patch - don't bother with ANGLE_OS detection with NSPR
-  angle-renaming.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
-  angle-instrinsic-msvc2005.patch - work around a MSVC 2005 compile error
+  angle-renaming-debug.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
+  angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
   angle-limit-identifiers-to-250-chars.patch - see bug 675625
   angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands.
-  angle-mCurrentValueOffsets-size_t.patch - ANGLE bug 220 - compile fix on win64
-  angle-pool_allocator-assignable.patch - ANGLE r798
 
 In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE.
 
 == How to update this ANGLE copy ==
 
 1. Unapply patches
 2. Apply diff with new ANGLE version
 3. Reapply patches.
rename from gfx/angle/angle-instrinsic-msvc2005.patch
rename to gfx/angle/angle-intrinsic-msvc2005.patch
deleted file mode 100644
--- a/gfx/angle/angle-nspr-misc.patch
+++ /dev/null
@@ -1,2 +0,0 @@
-# HG changeset patch
-# Parent 6a9ec71ad85de76c551a5398b1427d9f76430b1f
--- a/gfx/angle/angle-use-xmalloc.patch
+++ b/gfx/angle/angle-use-xmalloc.patch
@@ -1,43 +1,44 @@
 # HG changeset patch
-# Parent 74f1894d664435118be4fdefd53cabfdaa9985bc
+# Parent fecc64a6df53a9056b21958affad38c80ca38496
+
 diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
 --- a/gfx/angle/Makefile.in
 +++ b/gfx/angle/Makefile.in
-@@ -123,16 +123,18 @@ CSRCS   = \
-         memory.c \
-         scanner.c \
-         symbols.c \
-         tokens.c \
+@@ -127,16 +127,18 @@ CSRCS   = \
  	$(NULL)
  
  DEFINES += -DANGLE_USE_NSPR -DANGLE_BUILD
  
+ #these defines are from ANGLE's build_angle.gyp
+ DEFINES += -DANGLE_DISABLE_TRACE
+ DEFINES += -DANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0
+ 
 +EXTRA_DSO_LDOPTS = $(MOZALLOC_LIB)
 +
  ifdef MOZ_ANGLE
  
  # libEGL depends on (links against!) libGLESv2!
  DIRS = src/libGLESv2 src/libEGL
  
  libs::
  	expand "$(MOZ_D3DX9_CAB)" -F:$(MOZ_D3DX9_DLL) "$(DIST)/bin"
  	expand "$(MOZ_D3DCOMPILER_CAB)" -F:$(MOZ_D3DCOMPILER_DLL) "$(DIST)/bin"
 diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla
 --- a/gfx/angle/README.mozilla
 +++ b/gfx/angle/README.mozilla
-@@ -4,16 +4,17 @@ Current revision: r740
+@@ -3,16 +3,17 @@ This is the ANGLE project, from http://c
+ Current revision: r774
  
  == Applied local patches ==
  
  In this order:
-   angle-nspr-misc.patch - don't bother with ANGLE_OS detection with NSPR
    angle-renaming.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
-   angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
+   angle-instrinsic-msvc2005.patch - work around a MSVC 2005 compile error
    angle-limit-identifiers-to-250-chars.patch - see bug 675625
 +  angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands.
  
  In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE.
  
  == How to update this ANGLE copy ==
  
  1. Unapply patches
@@ -113,31 +114,31 @@ diff --git a/gfx/angle/src/compiler/prep
          atable->arev = newrev;
          atable->size = size;
      }
      return 0;
  } // GrowAtomTable
 diff --git a/gfx/angle/src/libEGL/Makefile.in b/gfx/angle/src/libEGL/Makefile.in
 --- a/gfx/angle/src/libEGL/Makefile.in
 +++ b/gfx/angle/src/libEGL/Makefile.in
-@@ -150,8 +150,10 @@ RCFILE = $(srcdir)/libEGL.rc
+@@ -153,8 +153,10 @@ RCFILE = $(srcdir)/libEGL.rc
  include $(topsrcdir)/config/rules.mk
  
  EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3d9.lib" \
                     "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/dxguid.lib" \
  		   "$(DIST)/lib/libGLESv2.lib" \
  		   dwmapi.lib \
  		   delayimp.lib \
  		   /delayload:dwmapi.dll
 +
 +EXTRA_DSO_LDOPTS += $(MOZALLOC_LIB)
 diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in
 --- a/gfx/angle/src/libGLESv2/Makefile.in
 +++ b/gfx/angle/src/libGLESv2/Makefile.in
-@@ -159,8 +159,10 @@ CPPSRCS	+= \
+@@ -162,8 +162,10 @@ CPPSRCS	+= \
  DEFFILE = $(srcdir)/libGLESv2.def
  RCFILE = $(srcdir)/libGLESv2.rc
  
  include $(topsrcdir)/config/rules.mk
  
  EXTRA_DSO_LDOPTS = "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3d9.lib" \
                     "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3dx9.lib" \
  		   "$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/D3DCompiler.lib"
--- a/gfx/angle/build/common.gypi
+++ b/gfx/angle/build/common.gypi
@@ -1,15 +1,15 @@
 # Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 {
   'variables': {
-    'library%': 'shared_library',
+    'component%': 'static_library',
   },
   'target_defaults': {
     'default_configuration': 'Debug',
     'configurations': {
       'Common': {
         'abstract': 1,
         'msvs_configuration_attributes': {
           'OutputDirectory': '$(SolutionDir)$(ConfigurationName)',
@@ -76,16 +76,21 @@
             'RuntimeLibrary': '0',  # /MT (static)
           },
           'VCLinkerTool': {
             'LinkIncremental': '1',
           },
         },
       },  # Release
     },  # configurations
+    'conditions': [
+      ['component=="shared_library"', {
+        'defines': ['COMPONENT_BUILD'],
+      }],
+    ],
   },  # target_defaults
   'conditions': [
     ['OS=="win"', {
       'target_defaults': {
         'msvs_cygwin_dirs': ['../third_party/cygwin'],
       },
     }],
     ['OS!="win" and OS!="mac"', {
new file mode 100644
--- /dev/null
+++ b/gfx/angle/extensions/ANGLE_translated_shader_source.txt
@@ -0,0 +1,118 @@
+Name
+
+    ANGLE_translated_shader_source
+
+Name Strings
+
+    GL_ANGLE_translated_shader_source
+
+Contributors
+
+    Daniel Koch, TransGaming Inc.
+    Gregg Tavares, Google Inc.
+    Kenneth Russell, Google Inc.
+    Zhenyao Mo, Google Inc.
+
+Contact
+
+    Zhenyao Mo, Google Inc. (zmo 'at' google 'dot' com)
+
+Status
+
+    Implemented in ANGLE ES2
+
+Version
+
+    Last Modified Date: October 5, 2011
+    Author Revision: 2
+
+Number
+
+    OpenGL ES Extension #??
+
+Dependencies
+
+    OpenGL ES 2.0 is required.
+
+    The extension is written against the OpenGL ES 2.0 specification.
+
+Overview
+
+    WebGL uses the GLSL ES 2.0 spec on all platforms, and translates these
+    shaders to the host platform's native language (HLSL, GLSL, and even GLSL
+    ES). For debugging purposes, it is useful to be able to examine the shader
+    after translation.
+
+    This extension addes a new function to query the translated shader source,
+    and adds a new enum for GetShaderiv's <pname> parameter to query the
+    translated shader source length. 
+
+IP Status
+
+    No known IP claims.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    void GetTranslatedShaderSourceANGLE(uint shader, sizei bufsize,
+                                        sizei* length, char* source);
+
+New Tokens
+
+    Accepted by the <pname> parameter of GetShaderiv:
+
+    TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE              0x93A0
+
+Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
+Requests)
+
+    Append in the end of the fourth paragraph of section 6.1.8 (Shader and
+    Program Queries):
+
+    " If <pname> is TRANSLATED_SHADER_LENGTH_ANGLE, the length of the translated
+    source string, including a null terminator, is returned. If no source has
+    been defined, CompileShader has not been called, or the translation has
+    failed for <shader>, zero is returned."
+
+    Append after the last paragraph of section 6.1.8 (Shader and Program
+    Queries):
+
+    "The command
+
+      void GetTranslatedShaderSourceANGLE( uint shader, sizei bufSize,
+         sizei *length, char *source );
+
+    returns in <source> the string making up the translated source code for
+    the shader object <shader>. The string <source> will be null terminated.
+    The actual number of characters written into <source>, excluding the null
+    terminator, is returned in <length>. If <length> is NULL, no length is
+    returned. The maximum number of characters that may be written into 
+    <source>, including the null terminator, is speciļ¬ed by <bufSize>. The
+    string <source> is the translated string of a concatenation of the strings
+    passed to the GL using ShaderSource. The length of this translated string
+    is given by TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, which can be queried
+    with GetShaderiv.
+
+    If no source has been defined, CompileShader has not been called, or the
+    translation has failed for <shader>, zero is returned for <length>, and
+    an empty string is returned for <source>.
+
+    If the value of SHADER_COMPILER is not TRUE, then the error INVALID_-
+    OPERATION is generated."
+
+Issues
+
+    1) What enum value should be used for TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE?
+
+      RESOLVED: The first draft used a temporary enum value. This been replaced
+      with a enum allocated from the ANGLE range of GL enums. 
+
+Revision History
+
+    Revision 1, 2011/09/29, zmo
+      - first draft
+    Revision 2, 2011/10/05, dgkoch
+      - assigned enum
--- a/gfx/angle/extensions/EGL_ANGLE_software_display.txt
+++ b/gfx/angle/extensions/EGL_ANGLE_software_display.txt
@@ -16,17 +16,17 @@ Contacts
     John Bauman, Google Inc. (jbauman 'at' chromium.org)
 
 Status
 
     In progress
 
 Version
 
-    Version 1, July 12, 2011
+    Version 2, October 19, 2011
 
 Number
 
     EGL Extension #??
 
 Dependencies
 
     This extension is written against the wording of the EGL 1.4
@@ -41,23 +41,25 @@ New Types
     None
 
 New Procedures and Functions
 
     None
 
 New Tokens
 
-    None
+    EGL_SOFTWARE_DISPLAY_ANGLE         (EGLNativeDisplayType)-1
 
 Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
 
     Add before the last sentence of the first paragraph of section 3.2,
     "Initialization":
 
     "If <display_id> is EGL_SOFTWARE_DISPLAY_ANGLE, a display that will render
     everything in software will be returned."
 
 Issues
 
 Revision History
 
     Version 1, 2011/07/12 - first draft.
+    Version 2, 2011/10/18 - add token definition
+
--- a/gfx/angle/include/GLES2/gl2ext.h
+++ b/gfx/angle/include/GLES2/gl2ext.h
@@ -212,16 +212,21 @@ typedef void* GLeglImageOES;
 #define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE                      0x83F2
 #endif
 
 /* GL_ANGLE_texture_compression_dxt5 */
 #ifndef GL_ANGLE_texture_compression_dxt5
 #define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE                      0x83F3
 #endif
 
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE                0x93A0
+#endif
+
 /*------------------------------------------------------------------------*
  * APPLE extension tokens
  *------------------------------------------------------------------------*/
 
 /* GL_APPLE_rgb_422 */
 #ifndef GL_APPLE_rgb_422
 #define GL_RGB_422_APPLE                                        0x8A1F
 #define GL_UNSIGNED_SHORT_8_8_APPLE                             0x85BA
@@ -805,16 +810,25 @@ typedef void (GL_APIENTRYP PFNGLRENDERBU
 #define GL_ANGLE_texture_compression_dxt3 1
 #endif
 
 /* GL_ANGLE_texture_compression_dxt5 */
 #ifndef GL_ANGLE_texture_compression_dxt5
 #define GL_ANGLE_texture_compression_dxt5 1
 #endif
 
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+#endif
+
 /*------------------------------------------------------------------------*
  * APPLE extension functions
  *------------------------------------------------------------------------*/
 
 /* GL_APPLE_rgb_422 */
 #ifndef GL_APPLE_rgb_422
 #define GL_APPLE_rgb_422 1
 #endif
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
@@ -1,16 +1,33 @@
 //
 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 #ifndef _COMPILER_INTERFACE_INCLUDED_
 #define _COMPILER_INTERFACE_INCLUDED_
 
+#if defined(COMPONENT_BUILD)
+#if defined(_WIN32) || defined(_WIN64)
+
+#if defined(COMPILER_IMPLEMENTATION)
+#define COMPILER_EXPORT __declspec(dllexport)
+#else
+#define COMPILER_EXPORT __declspec(dllimport)
+#endif  // defined(COMPILER_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#define COMPILER_EXPORT __attribute__((visibility("default")))
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define COMPILER_EXPORT
+#endif
+
 //
 // This is the platform independent interface between an OGL driver
 // and the shading language compiler.
 //
 
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -88,22 +105,22 @@ typedef enum {
   SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100
 } ShCompileOptions;
 
 //
 // Driver must call this first, once, before doing any other
 // compiler operations.
 // If the function succeeds, the return value is nonzero, else zero.
 //
-int ShInitialize();
+COMPILER_EXPORT int ShInitialize();
 //
 // Driver should call this at shutdown.
 // If the function succeeds, the return value is nonzero, else zero.
 //
-int ShFinalize();
+COMPILER_EXPORT int ShFinalize();
 
 //
 // Implementation dependent built-in resources (constants and extensions).
 // The names for these resources has been obtained by stripping gl_/GL_.
 //
 typedef struct
 {
     // Constants.
@@ -120,17 +137,17 @@ typedef struct
     // Set to 1 to enable the extension, else 0.
     int OES_standard_derivatives;
     int OES_EGL_image_external;
 } ShBuiltInResources;
 
 //
 // Initialize built-in resources with minimum expected values.
 //
-void ShInitBuiltInResources(ShBuiltInResources* resources);
+COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
 
 //
 // ShHandle held by but opaque to the driver.  It is allocated,
 // managed, and de-allocated by the compiler. It's contents 
 // are defined by and used by the compiler.
 //
 // If handle creation fails, 0 will be returned.
 //
@@ -143,20 +160,22 @@ typedef void* ShHandle;
 // not supported.
 // Parameters:
 // type: Specifies the type of shader - SH_FRAGMENT_SHADER or SH_VERTEX_SHADER.
 // spec: Specifies the language spec the compiler must conform to -
 //       SH_GLES2_SPEC or SH_WEBGL_SPEC.
 // output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
 //         or SH_HLSL_OUTPUT.
 // resources: Specifies the built-in resources.
-ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
-                             ShShaderOutput output,
-                             const ShBuiltInResources* resources);
-void ShDestruct(ShHandle handle);
+COMPILER_EXPORT ShHandle ShConstructCompiler(
+    ShShaderType type,
+    ShShaderSpec spec,
+    ShShaderOutput output,
+    const ShBuiltInResources* resources);
+COMPILER_EXPORT void ShDestruct(ShHandle handle);
 
 //
 // Compiles the given shader source.
 // If the function succeeds, the return value is nonzero, else zero.
 // Parameters:
 // handle: Specifies the handle of compiler to be used.
 // shaderStrings: Specifies an array of pointers to null-terminated strings
 //                containing the shader source code.
@@ -173,17 +192,17 @@ void ShDestruct(ShHandle handle);
 // SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
 //                       Can be queried by calling ShGetInfoLog().
 // SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
 //                 Can be queried by calling ShGetObjectCode().
 // SH_ATTRIBUTES_UNIFORMS: Extracts attributes and uniforms.
 //                         Can be queried by calling ShGetActiveAttrib() and
 //                         ShGetActiveUniform().
 //
-int ShCompile(
+COMPILER_EXPORT int ShCompile(
     const ShHandle handle,
     const char* const shaderStrings[],
     const int numStrings,
     int compileOptions
     );
 
 // Returns a parameter from a compiled shader.
 // Parameters:
@@ -201,37 +220,39 @@ int ShCompile(
 // SH_ACTIVE_UNIFORMS: the number of active uniform variables.
 // SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
 //                               variable name including the null
 //                               termination character.
 // SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
 //                            the null termination character.
 // 
 // params: Requested parameter
-void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params);
+COMPILER_EXPORT void ShGetInfo(const ShHandle handle,
+                               ShShaderInfo pname,
+                               int* params);
 
 // Returns nul-terminated information log for a compiled shader.
 // Parameters:
 // handle: Specifies the compiler
 // infoLog: Specifies an array of characters that is used to return
 //          the information log. It is assumed that infoLog has enough memory
 //          to accomodate the information log. The size of the buffer required
 //          to store the returned information log can be obtained by calling
 //          ShGetInfo with SH_INFO_LOG_LENGTH.
-void ShGetInfoLog(const ShHandle handle, char* infoLog);
+COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
 
 // Returns null-terminated object code for a compiled shader.
 // Parameters:
 // handle: Specifies the compiler
 // infoLog: Specifies an array of characters that is used to return
 //          the object code. It is assumed that infoLog has enough memory to
 //          accomodate the object code. The size of the buffer required to
 //          store the returned object code can be obtained by calling
 //          ShGetInfo with SH_OBJECT_CODE_LENGTH.
-void ShGetObjectCode(const ShHandle handle, char* objCode);
+COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
 
 // Returns information about an active attribute variable.
 // Parameters:
 // handle: Specifies the compiler
 // index: Specifies the index of the attribute variable to be queried.
 // length: Returns the number of characters actually written in the string
 //         indicated by name (excluding the null terminator) if a value other
 //         than NULL is passed.
@@ -242,23 +263,23 @@ void ShGetObjectCode(const ShHandle hand
 //       accomodate the attribute variable name. The size of the buffer
 //       required to store the attribute variable name can be obtained by
 //       calling ShGetInfo with SH_ACTIVE_ATTRIBUTE_MAX_LENGTH.
 // mappedName: Returns a null terminated string containing the mapped name of
 //             the attribute variable, It is assumed that mappedName has enough
 //             memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
 //             about the mapped name. If the name is not mapped, then name and
 //             mappedName are the same.
-void ShGetActiveAttrib(const ShHandle handle,
-                       int index,
-                       int* length,
-                       int* size,
-                       ShDataType* type,
-                       char* name,
-                       char* mappedName);
+COMPILER_EXPORT void ShGetActiveAttrib(const ShHandle handle,
+                                       int index,
+                                       int* length,
+                                       int* size,
+                                       ShDataType* type,
+                                       char* name,
+                                       char* mappedName);
 
 // Returns information about an active uniform variable.
 // Parameters:
 // handle: Specifies the compiler
 // index: Specifies the index of the uniform variable to be queried.
 // length: Returns the number of characters actually written in the string
 //         indicated by name (excluding the null terminator) if a value
 //         other than NULL is passed.
@@ -269,21 +290,21 @@ void ShGetActiveAttrib(const ShHandle ha
 //       accomodate the uniform variable name. The size of the buffer required
 //       to store the uniform variable name can be obtained by calling
 //       ShGetInfo with SH_ACTIVE_UNIFORMS_MAX_LENGTH.
 // mappedName: Returns a null terminated string containing the mapped name of
 //             the uniform variable, It is assumed that mappedName has enough
 //             memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
 //             about the mapped name. If the name is not mapped, then name and
 //             mappedName are the same.
-void ShGetActiveUniform(const ShHandle handle,
-                        int index,
-                        int* length,
-                        int* size,
-                        ShDataType* type,
-                        char* name,
-                        char* mappedName);
+COMPILER_EXPORT void ShGetActiveUniform(const ShHandle handle,
+                                        int index,
+                                        int* length,
+                                        int* size,
+                                        ShDataType* type,
+                                        char* name,
+                                        char* mappedName);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // _COMPILER_INTERFACE_INCLUDED_
--- a/gfx/angle/samples/build_samples.gyp
+++ b/gfx/angle/samples/build_samples.gyp
@@ -20,20 +20,28 @@
     {
       'target_name': 'essl_to_hlsl',
       'type': 'executable',
       'dependencies': [
         '../src/build_angle.gyp:translator_hlsl',
       ],
       'include_dirs': [
         '../include',
+        '../src',
       ],
       'sources': [
         'translator/translator.cpp',
+        '../src/common/debug.cpp',
       ],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'AdditionalLibraryDirectories': ['$(DXSDK_DIR)/lib/x86'],
+          'AdditionalDependencies': ['d3d9.lib'],
+        }
+      }
     },
   ],
   'conditions': [
     ['OS=="win"', {
       'targets': [
         {
           'target_name': 'es_util',
           'type': 'static_library',
--- a/gfx/angle/samples/translator/translator.cpp
+++ b/gfx/angle/samples/translator/translator.cpp
@@ -144,22 +144,22 @@ int main(int argc, char* argv[])
                   buffer = (char*) realloc(buffer, bufferLen * sizeof(char));
                   ShGetObjectCode(compiler, buffer);
                   puts(buffer);
                   LogMsg("END", "COMPILER", numCompiles, "OBJ CODE");
                   printf("\n\n");
               }
               if (compiled && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
                   LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE ATTRIBS");
-                  PrintActiveVariables(compiler, SH_ACTIVE_ATTRIBUTES, compileOptions & SH_MAP_LONG_VARIABLE_NAMES);
+                  PrintActiveVariables(compiler, SH_ACTIVE_ATTRIBUTES, (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) != 0);
                   LogMsg("END", "COMPILER", numCompiles, "ACTIVE ATTRIBS");
                   printf("\n\n");
 
                   LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE UNIFORMS");
-                  PrintActiveVariables(compiler, SH_ACTIVE_UNIFORMS, compileOptions & SH_MAP_LONG_VARIABLE_NAMES);
+                  PrintActiveVariables(compiler, SH_ACTIVE_UNIFORMS, (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) != 0);
                   LogMsg("END", "COMPILER", numCompiles, "ACTIVE UNIFORMS");
                   printf("\n\n");
               }
               if (!compiled)
                   failCode = EFailCompile;
               ++numCompiles;
             } else {
                 failCode = EFailCompilerCreate;
--- a/gfx/angle/src/common/debug.cpp
+++ b/gfx/angle/src/common/debug.cpp
@@ -58,36 +58,42 @@ static void output(bool traceFileDebugOn
     }
 #endif
 }
 
 void trace(bool traceFileDebugOnly, const char *format, ...)
 {
     va_list vararg;
     va_start(vararg, format);
+#if defined(ANGLE_DISABLE_PERF)
+    output(traceFileDebugOnly, NULL, format, vararg);
+#else
     output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg);
+#endif
     va_end(vararg);
 }
 
 bool perfActive()
 {
 #if defined(ANGLE_DISABLE_PERF)
     return false;
 #else
     static bool active = D3DPERF_GetStatus() != 0;
     return active;
 #endif
 }
 
 ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
 {
+#if !defined(ANGLE_DISABLE_PERF)
     va_list vararg;
     va_start(vararg, format);
     output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg);
     va_end(vararg);
+#endif
 }
 
 ScopedPerfEventHelper::~ScopedPerfEventHelper()
 {
 #if !defined(ANGLE_DISABLE_PERF)
     if (perfActive())
     {
         D3DPERF_EndEvent();
--- a/gfx/angle/src/common/version.h
+++ b/gfx/angle/src/common/version.h
@@ -1,10 +1,10 @@
 #define MAJOR_VERSION 0
 #define MINOR_VERSION 0
 #define BUILD_VERSION 0
-#define BUILD_REVISION 774
+#define BUILD_REVISION 802
 
 #define STRINGIFY(x) #x
 #define MACRO_STRINGIFY(x) STRINGIFY(x)
 
 #define REVISION_STRING MACRO_STRINGIFY(BUILD_REVISION)
 #define VERSION_STRING MACRO_STRINGIFY(MAJOR_VERSION) "." MACRO_STRINGIFY(MINOR_VERSION) "." MACRO_STRINGIFY(BUILD_VERSION) "." MACRO_STRINGIFY(BUILD_REVISION)
--- a/gfx/angle/src/compiler/OutputHLSL.cpp
+++ b/gfx/angle/src/compiler/OutputHLSL.cpp
@@ -1498,17 +1498,17 @@ bool OutputHLSL::visitAggregate(Visit vi
 }
 
 bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
 {
     TInfoSinkBase &out = mBody;
 
     if (node->usesTernaryOperator())
     {
-        out << "t" << mUnfoldSelect->getTemporaryIndex();
+        out << "s" << mUnfoldSelect->getNextTemporaryIndex();
     }
     else  // if/else statement
     {
         mUnfoldSelect->traverse(node->getCondition());
 
         out << "if(";
 
         node->getCondition()->traverse(this);
@@ -1562,31 +1562,16 @@ bool OutputHLSL::visitLoop(Visit visit, 
     {
         out << "do\n";
 
         outputLineDirective(node->getLine());
         out << "{\n";
     }
     else
     {
-        if (node->getInit())
-        {
-            mUnfoldSelect->traverse(node->getInit());
-        }
-        
-        if (node->getCondition())
-        {
-            mUnfoldSelect->traverse(node->getCondition());
-        }
-        
-        if (node->getExpression())
-        {
-            mUnfoldSelect->traverse(node->getExpression());
-        }
-
         out << "for(";
         
         if (node->getInit())
         {
             node->getInit()->traverse(this);
         }
 
         out << "; ";
--- a/gfx/angle/src/compiler/UnfoldSelect.cpp
+++ b/gfx/angle/src/compiler/UnfoldSelect.cpp
@@ -15,51 +15,82 @@ namespace sh
 {
 UnfoldSelect::UnfoldSelect(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
 {
     mTemporaryIndex = 0;
 }
 
 void UnfoldSelect::traverse(TIntermNode *node)
 {
-    mTemporaryIndex++;
+    int rewindIndex = mTemporaryIndex;
     node->traverse(this);
+    mTemporaryIndex = rewindIndex;
 }
 
 bool UnfoldSelect::visitSelection(Visit visit, TIntermSelection *node)
 {
     TInfoSinkBase &out = mOutputHLSL->getBodyStream();
 
     if (node->usesTernaryOperator())
     {
-        int i = mTemporaryIndex++;
+        int i = mTemporaryIndex;
 
-        out << mOutputHLSL->typeString(node->getType()) << " t" << i << ";\n";
+        out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n";
 
+        mTemporaryIndex = i + 1;
         node->getCondition()->traverse(this);
         out << "if(";
+        mTemporaryIndex = i + 1;
         node->getCondition()->traverse(mOutputHLSL);
         out << ")\n"
                "{\n";
+        mTemporaryIndex = i + 1;
         node->getTrueBlock()->traverse(this);
-        out << "    t" << i << " = ";
+        out << "    s" << i << " = ";
+        mTemporaryIndex = i + 1;
         node->getTrueBlock()->traverse(mOutputHLSL);
         out << ";\n"
                "}\n"
                "else\n"
                "{\n";
+        mTemporaryIndex = i + 1;
         node->getFalseBlock()->traverse(this);
-        out << "    t" << i << " = ";
+        out << "    s" << i << " = ";
+        mTemporaryIndex = i + 1;
         node->getFalseBlock()->traverse(mOutputHLSL);
         out << ";\n"
                "}\n";
 
-        mTemporaryIndex--;
+        mTemporaryIndex = i + 1;
     }
 
     return false;
 }
 
-int UnfoldSelect::getTemporaryIndex()
+bool UnfoldSelect::visitLoop(Visit visit, TIntermLoop *node)
 {
-    return mTemporaryIndex;
+    int rewindIndex = mTemporaryIndex;
+
+    if (node->getInit())
+    {
+        node->getInit()->traverse(this);
+    }
+    
+    if (node->getCondition())
+    {
+        node->getCondition()->traverse(this);
+    }
+
+    if (node->getExpression())
+    {
+        node->getExpression()->traverse(this);
+    }
+
+    mTemporaryIndex = rewindIndex;
+
+    return false;
+}
+
+int UnfoldSelect::getNextTemporaryIndex()
+{
+    return mTemporaryIndex++;
 }
 }
--- a/gfx/angle/src/compiler/UnfoldSelect.h
+++ b/gfx/angle/src/compiler/UnfoldSelect.h
@@ -18,18 +18,19 @@ class OutputHLSL;
 
 class UnfoldSelect : public TIntermTraverser
 {
   public:
     UnfoldSelect(TParseContext &context, OutputHLSL *outputHLSL);
 
     void traverse(TIntermNode *node);
     bool visitSelection(Visit visit, TIntermSelection *node);
+    bool visitLoop(Visit visit, TIntermLoop *node);
 
-    int getTemporaryIndex();
+    int getNextTemporaryIndex();
 
   protected:
     TParseContext &mContext;
     OutputHLSL *const mOutputHLSL;
 
     int mTemporaryIndex;
 };
 }
--- a/gfx/angle/src/compiler/intermOut.cpp
+++ b/gfx/angle/src/compiler/intermOut.cpp
@@ -256,16 +256,18 @@ bool TOutputTraverser::visitAggregate(Vi
         case EOpDistance:      out << "distance";                break;
         case EOpDot:           out << "dot-product";             break;
         case EOpCross:         out << "cross-product";           break;
         case EOpFaceForward:   out << "face-forward";            break;
         case EOpReflect:       out << "reflect";                 break;
         case EOpRefract:       out << "refract";                 break;
         case EOpMul:           out << "component-wise multiply"; break;
 
+        case EOpDeclaration:   out << "Declaration: ";   break;
+
         default: out.message(EPrefixError, "Bad aggregation op");
     }
 
     if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
         out << " (" << node->getCompleteString() << ")";
 
     out << "\n";
 
--- a/gfx/angle/src/libGLESv2/Context.cpp
+++ b/gfx/angle/src/libGLESv2/Context.cpp
@@ -376,16 +376,18 @@ void Context::markAllStateDirty()
     mMaskStateDirty = true;
     mBlendStateDirty = true;
     mStencilStateDirty = true;
     mPolygonOffsetStateDirty = true;
     mScissorStateDirty = true;
     mSampleStateDirty = true;
     mDitherStateDirty = true;
     mFrontFaceDirty = true;
+    mDxUniformsDirty = true;
+    mCachedCurrentProgram = NULL;
 }
 
 void Context::setClearColor(float red, float green, float blue, float alpha)
 {
     mState.colorClearValue.red = red;
     mState.colorClearValue.green = green;
     mState.colorClearValue.blue = blue;
     mState.colorClearValue.alpha = alpha;
@@ -888,16 +890,17 @@ void Context::deleteBuffer(GLuint buffer
 void Context::deleteShader(GLuint shader)
 {
     mResourceManager->deleteShader(shader);
 }
 
 void Context::deleteProgram(GLuint program)
 {
     mResourceManager->deleteProgram(program);
+    mCachedCurrentProgram = NULL;
 }
 
 void Context::deleteTexture(GLuint texture)
 {
     if (mResourceManager->getTexture(texture))
     {
         detachTexture(texture);
     }
@@ -968,17 +971,17 @@ Renderbuffer *Context::getRenderbuffer(G
 
 Framebuffer *Context::getReadFramebuffer()
 {
     return getFramebuffer(mState.readFramebuffer);
 }
 
 Framebuffer *Context::getDrawFramebuffer()
 {
-    return getFramebuffer(mState.drawFramebuffer);
+    return mBoundDrawFramebuffer;
 }
 
 void Context::bindArrayBuffer(unsigned int buffer)
 {
     mResourceManager->checkBufferAllocation(buffer);
 
     mState.arrayBuffer.set(getBuffer(buffer));
 }
@@ -1017,16 +1020,18 @@ void Context::bindReadFramebuffer(GLuint
 void Context::bindDrawFramebuffer(GLuint framebuffer)
 {
     if (!getFramebuffer(framebuffer))
     {
         mFramebufferMap[framebuffer] = new Framebuffer();
     }
 
     mState.drawFramebuffer = framebuffer;
+
+    mBoundDrawFramebuffer = getFramebuffer(framebuffer);
 }
 
 void Context::bindRenderbuffer(GLuint renderbuffer)
 {
     mResourceManager->checkRenderbufferAllocation(renderbuffer);
 
     mState.renderbuffer.set(getRenderbuffer(renderbuffer));
 }
@@ -1035,16 +1040,18 @@ void Context::useProgram(GLuint program)
 {
     GLuint priorProgram = mState.currentProgram;
     mState.currentProgram = program;               // Must switch before trying to delete, otherwise it only gets flagged.
 
     if (priorProgram != program)
     {
         Program *newProgram = mResourceManager->getProgram(program);
         Program *oldProgram = mResourceManager->getProgram(priorProgram);
+        mCachedCurrentProgram = NULL;
+        mDxUniformsDirty = true;
 
         if (newProgram)
         {
             newProgram->addRef();
         }
         
         if (oldProgram)
         {
@@ -1052,16 +1059,20 @@ void Context::useProgram(GLuint program)
         }
     }
 }
 
 void Context::setFramebufferZero(Framebuffer *buffer)
 {
     delete mFramebufferMap[0];
     mFramebufferMap[0] = buffer;
+    if (mState.drawFramebuffer == 0)
+    {
+        mBoundDrawFramebuffer = buffer;
+    }
 }
 
 void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
 {
     Renderbuffer *renderbufferObject = mState.renderbuffer.get();
     renderbufferObject->setStorage(renderbuffer);
 }
 
@@ -1100,17 +1111,21 @@ Buffer *Context::getArrayBuffer()
 
 Buffer *Context::getElementArrayBuffer()
 {
     return mState.elementArrayBuffer.get();
 }
 
 Program *Context::getCurrentProgram()
 {
-    return mResourceManager->getProgram(mState.currentProgram);
+    if (!mCachedCurrentProgram)
+    {
+        mCachedCurrentProgram = mResourceManager->getProgram(mState.currentProgram);
+    }
+    return mCachedCurrentProgram;
 }
 
 Texture2D *Context::getTexture2D()
 {
     return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
 }
 
 TextureCubeMap *Context::getTextureCubeMap()
@@ -1609,29 +1624,29 @@ bool Context::applyRenderTarget(bool ign
 
     Framebuffer *framebufferObject = getDrawFramebuffer();
 
     if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
     {
         return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
     }
 
-    IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
-
-    if (!renderTarget)
-    {
-        return false;   // Context must be lost
-    }
-
+    IDirect3DSurface9 *renderTarget = NULL;
     IDirect3DSurface9 *depthStencil = NULL;
 
     bool renderTargetChanged = false;
     unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
     if (renderTargetSerial != mAppliedRenderTargetSerial)
     {
+        renderTarget = framebufferObject->getRenderTarget();
+
+        if (!renderTarget)
+        {
+            return false;   // Context must be lost
+        }
         device->SetRenderTarget(0, renderTarget);
         mAppliedRenderTargetSerial = renderTargetSerial;
         mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets.
         renderTargetChanged = true;
     }
 
     unsigned int depthbufferSerial = 0;
     unsigned int stencilbufferSerial = 0;
@@ -1665,16 +1680,25 @@ bool Context::applyRenderTarget(bool ign
         device->SetDepthStencilSurface(depthStencil);
         mAppliedDepthbufferSerial = depthbufferSerial;
         mAppliedStencilbufferSerial = stencilbufferSerial;
         mDepthStencilInitialized = true;
     }
 
     if (!mRenderTargetDescInitialized || renderTargetChanged)
     {
+        if (!renderTarget)
+        {
+            renderTarget = framebufferObject->getRenderTarget();
+
+            if (!renderTarget)
+            {
+                return false;   // Context must be lost
+            }
+        }
         renderTarget->GetDesc(&mRenderTargetDesc);
         mRenderTargetDescInitialized = true;
     }
 
     D3DVIEWPORT9 viewport;
 
     float zNear = clamp01(mState.zNear);
     float zFar = clamp01(mState.zFar);
@@ -1704,16 +1728,17 @@ bool Context::applyRenderTarget(bool ign
         return false;   // Nothing to render
     }
 
     if (!mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0)
     {
         device->SetViewport(&viewport);
         mSetViewport = viewport;
         mViewportInitialized = true;
+        mDxUniformsDirty = true;
     }
 
     if (mScissorStateDirty)
     {
         if (mState.scissorTest)
         {
             RECT rect = transformPixelRect(mState.scissorX, mState.scissorY, mState.scissorWidth, mState.scissorHeight, mRenderTargetDesc.Height);
             rect.left = clamp(rect.left, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
@@ -1726,17 +1751,17 @@ bool Context::applyRenderTarget(bool ign
         else
         {
             device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
         }
 
         mScissorStateDirty = false;
     }
 
-    if (mState.currentProgram)
+    if (mState.currentProgram && mDxUniformsDirty)
     {
         Program *programObject = getCurrentProgram();
 
         GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
         GLfloat xy[2] = {1.0f / viewport.Width, -1.0f / viewport.Height};
         programObject->setUniform2fv(halfPixelSize, 1, xy);
 
         GLint viewport = programObject->getDxViewportLocation();
@@ -1747,16 +1772,17 @@ bool Context::applyRenderTarget(bool ign
 
         GLint depth = programObject->getDxDepthLocation();
         GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
         programObject->setUniform2fv(depth, 1, dz);
 
         GLint depthRange = programObject->getDxDepthRangeLocation();
         GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
         programObject->setUniform3fv(depthRange, 1, nearFarDiff);
+        mDxUniformsDirty = false;
     }
 
     return true;
 }
 
 // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
 void Context::applyState(GLenum drawMode)
 {
@@ -2084,22 +2110,24 @@ void Context::applyTextures()
 // looks up the corresponding OpenGL texture image unit and texture type,
 // and sets the texture and its addressing/filtering state (or NULL when inactive).
 void Context::applyTextures(SamplerType type)
 {
     IDirect3DDevice9 *device = getDevice();
     Program *programObject = getCurrentProgram();
 
     int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF;   // Range of Direct3D 9 samplers of given sampler type
-
-    for (int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++)
+    unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS;
+    int d3dSamplerOffset = (type == SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+    int samplerRange = programObject->getUsedSamplerRange(type);
+
+    for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
     {
         int textureUnit = programObject->getSamplerMapping(type, samplerIndex);   // OpenGL texture image unit index
-        int d3dSampler = (type == SAMPLER_PIXEL) ? samplerIndex : D3DVERTEXTEXTURESAMPLER0 + samplerIndex;
-        unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS;
+        int d3dSampler = samplerIndex + d3dSamplerOffset;
 
         if (textureUnit != -1)
         {
             TextureType textureType = programObject->getSamplerTextureType(type, samplerIndex);
 
             Texture *texture = getSamplerTexture(textureUnit, textureType);
 
             if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter() || texture->isDirtyImage())
@@ -2143,16 +2171,25 @@ void Context::applyTextures(SamplerType 
         {
             if (appliedTextureSerial[samplerIndex] != 0)
             {
                 device->SetTexture(d3dSampler, NULL);
                 appliedTextureSerial[samplerIndex] = 0;
             }
         }
     }
+
+    for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+    {
+        if (appliedTextureSerial[samplerIndex] != 0)
+        {
+            device->SetTexture(samplerIndex + d3dSamplerOffset, NULL);
+            appliedTextureSerial[samplerIndex] = 0;
+        }
+    }
 }
 
 void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
 {
     Framebuffer *framebuffer = getReadFramebuffer();
 
     if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
     {
@@ -3429,16 +3466,17 @@ void Context::initExtensionString()
     if (supportsDXT3Textures())
     {
         mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
     }
     if (supportsDXT5Textures())
     {
         mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
     }
+    mExtensionString += "GL_ANGLE_translated_shader_source ";
 
     // Other vendor-specific extensions
     if (supportsEventQueries())
     {
         mExtensionString += "GL_NV_fence ";
     }
 
     std::string::size_type end = mExtensionString.find_last_not_of(' ');
--- a/gfx/angle/src/libGLESv2/Context.h
+++ b/gfx/angle/src/libGLESv2/Context.h
@@ -539,16 +539,19 @@ class Context
     unsigned int mAppliedDepthbufferSerial;
     unsigned int mAppliedStencilbufferSerial;
     unsigned int mAppliedIBSerial;
     bool mDepthStencilInitialized;
     bool mViewportInitialized;
     D3DVIEWPORT9 mSetViewport;
     bool mRenderTargetDescInitialized;
     D3DSURFACE_DESC mRenderTargetDesc;
+    bool mDxUniformsDirty;
+    Program *mCachedCurrentProgram;
+    Framebuffer *mBoundDrawFramebuffer;
 
     bool mSupportsShaderModel3;
     bool mSupportsVertexTexture;
     bool mSupportsNonPower2Texture;
     int  mMaxRenderbufferDimension;
     int  mMaxTextureDimension;
     int  mMaxCubeTextureDimension;
     int  mMaxTextureLevel;
--- a/gfx/angle/src/libGLESv2/Framebuffer.cpp
+++ b/gfx/angle/src/libGLESv2/Framebuffer.cpp
@@ -53,29 +53,29 @@ Renderbuffer *Framebuffer::lookupRenderb
         UNREACHABLE();
     }
 
     return buffer;
 }
 
 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
 {
-    mColorbufferType = type;
+    mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
     mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
 }
 
 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
 {
-    mDepthbufferType = type;
+    mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
     mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
 }
 
 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
 {
-    mStencilbufferType = type;
+    mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
     mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
 }
 
 void Framebuffer::detachTexture(GLuint texture)
 {
     if (mColorbufferPointer.id() == texture && IsTextureTarget(mColorbufferType))
     {
         mColorbufferType = GL_NONE;
--- a/gfx/angle/src/libGLESv2/Program.cpp
+++ b/gfx/angle/src/libGLESv2/Program.cpp
@@ -35,17 +35,16 @@ std::string str(int i)
 
 Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize)
     : type(type), _name(_name), name(Program::undecorateUniform(_name)), arraySize(arraySize)
 {
     int bytes = UniformTypeSize(type) * arraySize;
     data = new unsigned char[bytes];
     memset(data, 0, bytes);
     dirty = true;
-    handlesSet = false;
 }
 
 Uniform::~Uniform()
 {
     delete[] data;
 }
 
 bool Uniform::isArray()
@@ -139,18 +138,16 @@ bool Program::detachShader(Shader *shade
             return false;
         }
 
         mFragmentShader->release();
         mFragmentShader = NULL;
     }
     else UNREACHABLE();
 
-    unlink();
-
     return true;
 }
 
 int Program::getAttachedShadersCount() const
 {
     return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
 }
 
@@ -195,21 +192,36 @@ GLuint Program::getAttributeLocation(con
 
 int Program::getSemanticIndex(int attributeIndex)
 {
     ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
     
     return mSemanticIndex[attributeIndex];
 }
 
+// Returns one more than the highest sampler index used.
+GLint Program::getUsedSamplerRange(SamplerType type)
+{
+    switch (type)
+    {
+      case SAMPLER_PIXEL:
+        return mUsedPixelSamplerRange;
+      case SAMPLER_VERTEX:
+        return mUsedVertexSamplerRange;
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+}
+
 // Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
 GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
 {
-    GLuint logicalTextureUnit = -1;
+    GLint logicalTextureUnit = -1;
 
     switch (type)
     {
       case SAMPLER_PIXEL:
         ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
 
         if (mSamplersPS[samplerIndex].active)
         {
@@ -222,17 +234,17 @@ GLint Program::getSamplerMapping(Sampler
         if (mSamplersVS[samplerIndex].active)
         {
             logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
         }
         break;
       default: UNREACHABLE();
     }
 
-    if (logicalTextureUnit >= 0 && logicalTextureUnit < getContext()->getMaximumCombinedTextureImageUnits())
+    if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)getContext()->getMaximumCombinedTextureImageUnits())
     {
         return logicalTextureUnit;
     }
 
     return -1;
 }
 
 // Returns the texture type for a given Direct3D 9 sampler type and
@@ -295,18 +307,27 @@ bool Program::setUniform1fv(GLint locati
     {
         int arraySize = targetUniform->arraySize;
 
         if (arraySize == 1 && count > 1)
             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
 
-        memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat),
-               v, sizeof(GLfloat) * count);
+        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count; i++)
+        {
+            target[0] = v[0];
+            target[1] = 0;
+            target[2] = 0;
+            target[3] = 0;
+            target += 4;
+            v += 1;
+        }
     }
     else if (targetUniform->type == GL_BOOL)
     {
         int arraySize = targetUniform->arraySize;
 
         if (arraySize == 1 && count > 1)
             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
@@ -352,18 +373,27 @@ bool Program::setUniform2fv(GLint locati
     {
         int arraySize = targetUniform->arraySize;
 
         if (arraySize == 1 && count > 1)
             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
 
-        memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 2,
-               v, 2 * sizeof(GLfloat) * count);
+        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count; i++)
+        {
+            target[0] = v[0];
+            target[1] = v[1];
+            target[2] = 0;
+            target[3] = 0;
+            target += 4;
+            v += 2;
+        }
     }
     else if (targetUniform->type == GL_BOOL_VEC2)
     {
         int arraySize = targetUniform->arraySize;
 
         if (arraySize == 1 && count > 1)
             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
@@ -410,18 +440,27 @@ bool Program::setUniform3fv(GLint locati
     {
         int arraySize = targetUniform->arraySize;
 
         if (arraySize == 1 && count > 1)
             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
 
-        memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 3,
-               v, 3 * sizeof(GLfloat) * count);
+        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count; i++)
+        {
+            target[0] = v[0];
+            target[1] = v[1];
+            target[2] = v[2];
+            target[3] = 0;
+            target += 4;
+            v += 3;
+        }
     }
     else if (targetUniform->type == GL_BOOL_VEC3)
     {
         int arraySize = targetUniform->arraySize;
 
         if (arraySize == 1 && count > 1)
             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
@@ -505,16 +544,47 @@ bool Program::setUniform4fv(GLint locati
     else 
     {
         return false;
     }
 
     return true;
 }
 
+template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight>
+void transposeMatrix(T *target, const GLfloat *value)
+{
+    int copyWidth = std::min(targetWidth, srcWidth);
+    int copyHeight = std::min(targetHeight, srcHeight);
+
+    for (int x = 0; x < copyWidth; x++)
+    {
+        for (int y = 0; y < copyHeight; y++)
+        {
+            target[x * targetWidth + y] = value[y * srcWidth + x];
+        }
+    }
+    // clear unfilled right side
+    for (int y = 0; y < copyHeight; y++)
+    {
+        for (int x = srcWidth; x < targetWidth; x++)
+        {
+            target[y * targetWidth + x] = 0;
+        }
+    }
+    // clear unfilled bottom.
+    for (int y = srcHeight; y < targetHeight; y++)
+    {
+        for (int x = 0; x < targetWidth; x++)
+        {
+            target[y * targetWidth + x] = 0;
+        }
+    }
+}
+
 bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
         return false;
     }
 
     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
@@ -527,18 +597,23 @@ bool Program::setUniformMatrix2fv(GLint 
 
     int arraySize = targetUniform->arraySize;
 
     if (arraySize == 1 && count > 1)
         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
     count = std::min(arraySize - (int)mUniformIndex[location].element, count);
 
-    memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
-           value, 4 * sizeof(GLfloat) * count);
+    GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8;
+    for (int i = 0; i < count; i++)
+    {
+        transposeMatrix<GLfloat,4,2,2,2>(target, value);
+        target += 8;
+        value += 4;
+    }
 
     return true;
 }
 
 bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
@@ -555,22 +630,28 @@ bool Program::setUniformMatrix3fv(GLint 
 
     int arraySize = targetUniform->arraySize;
 
     if (arraySize == 1 && count > 1)
         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
     count = std::min(arraySize - (int)mUniformIndex[location].element, count);
 
-    memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 9,
-           value, 9 * sizeof(GLfloat) * count);
+    GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12;
+    for (int i = 0; i < count; i++)
+    {
+        transposeMatrix<GLfloat,4,3,3,3>(target, value);
+        target += 12;
+        value += 9;
+    }
 
     return true;
 }
 
+
 bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
         return false;
     }
 
     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
@@ -583,18 +664,23 @@ bool Program::setUniformMatrix4fv(GLint 
 
     int arraySize = targetUniform->arraySize;
 
     if (arraySize == 1 && count > 1)
         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
 
     count = std::min(arraySize - (int)mUniformIndex[location].element, count);
 
-    memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16,
-           value, 16 * sizeof(GLfloat) * count);
+    GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16);
+    for (int i = 0; i < count; i++)
+    {
+        transposeMatrix<GLfloat,4,4,4,4>(target, value);
+        target += 16;
+        value += 16;
+    }
 
     return true;
 }
 
 bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
@@ -828,88 +914,126 @@ bool Program::getUniformfv(GLint locatio
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
         return false;
     }
 
     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
 
-    unsigned int count = UniformComponentCount(targetUniform->type);
-
-    switch (UniformComponentType(targetUniform->type))
+    switch (targetUniform->type)
     {
-      case GL_BOOL:
+      case GL_FLOAT_MAT2:
+        transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
+        break;
+      case GL_FLOAT_MAT3:
+        transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
+        break;
+      case GL_FLOAT_MAT4:
+        transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
+        break;
+      default:
         {
-            GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * count;
-
-            for (unsigned int i = 0; i < count; ++i)
+            unsigned int count = UniformComponentCount(targetUniform->type);
+            unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
+
+            switch (UniformComponentType(targetUniform->type))
             {
-                params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
+              case GL_BOOL:
+                {
+                    GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+                    for (unsigned int i = 0; i < count; ++i)
+                    {
+                        params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
+                    }
+                }
+                break;
+              case GL_FLOAT:
+                memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLfloat),
+                       count * sizeof(GLfloat));
+                break;
+              case GL_INT:
+                {
+                    GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+                    for (unsigned int i = 0; i < count; ++i)
+                    {
+                        params[i] = (float)intParams[i];
+                    }
+                }
+                break;
+              default: UNREACHABLE();
             }
         }
-        break;
-      case GL_FLOAT:
-        memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLfloat),
-               count * sizeof(GLfloat));
-        break;
-      case GL_INT:
-        {
-            GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * count;
-
-            for (unsigned int i = 0; i < count; ++i)
-            {
-                params[i] = (float)intParams[i];
-            }
-        }
-        break;
-      default: UNREACHABLE();
     }
 
     return true;
 }
 
 bool Program::getUniformiv(GLint location, GLint *params)
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
         return false;
     }
 
     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
 
-    unsigned int count = UniformComponentCount(targetUniform->type);
-
-    switch (UniformComponentType(targetUniform->type))
+    switch (targetUniform->type)
     {
-      case GL_BOOL:
+      case GL_FLOAT_MAT2:
         {
-            GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * count;
-
-            for (unsigned int i = 0; i < count; ++i)
-            {
-                params[i] = (GLint)boolParams[i];
-            }
+            transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
+        }
+        break;
+      case GL_FLOAT_MAT3:
+        {
+            transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
+        }
+        break;
+      case GL_FLOAT_MAT4:
+        {
+            transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
         }
         break;
-      case GL_FLOAT:
+      default:
         {
-            GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * count;
-
-            for (unsigned int i = 0; i < count; ++i)
+            unsigned int count = UniformComponentCount(targetUniform->type);
+            unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
+
+            switch (UniformComponentType(targetUniform->type))
             {
-                params[i] = (GLint)floatParams[i];
+              case GL_BOOL:
+                {
+                    GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * internalCount;
+
+                    for (unsigned int i = 0; i < count; ++i)
+                    {
+                        params[i] = (GLint)boolParams[i];
+                    }
+                }
+                break;
+              case GL_FLOAT:
+                {
+                    GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+                    for (unsigned int i = 0; i < count; ++i)
+                    {
+                        params[i] = (GLint)floatParams[i];
+                    }
+                }
+                break;
+              case GL_INT:
+                memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLint),
+                       count * sizeof(GLint));
+                break;
+              default: UNREACHABLE();
             }
         }
-        break;
-      case GL_INT:
-        memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLint),
-               count * sizeof(GLint));
-        break;
-      default: UNREACHABLE();
     }
 
     return true;
 }
 
 void Program::dirtyAllUniforms()
 {
     unsigned int numUniforms = mUniforms.size();
@@ -917,52 +1041,45 @@ void Program::dirtyAllUniforms()
     {
         mUniforms[index]->dirty = true;
     }
 }
 
 // Applies all the uniforms set for this program object to the Direct3D 9 device
 void Program::applyUniforms()
 {
-    unsigned int numUniforms = mUniformIndex.size();
-    for (unsigned int location = 0; location < numUniforms; location++)
-    {
-        if (mUniformIndex[location].element != 0)
-        {
-            continue;
-        }
-
-        Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) {
+        Uniform *targetUniform = *ub;
 
         if (targetUniform->dirty)
         {
             int arraySize = targetUniform->arraySize;
             GLfloat *f = (GLfloat*)targetUniform->data;
             GLint *i = (GLint*)targetUniform->data;
             GLboolean *b = (GLboolean*)targetUniform->data;
 
             switch (targetUniform->type)
             {
-              case GL_BOOL:       applyUniform1bv(location, arraySize, b);       break;
-              case GL_BOOL_VEC2:  applyUniform2bv(location, arraySize, b);       break;
-              case GL_BOOL_VEC3:  applyUniform3bv(location, arraySize, b);       break;
-              case GL_BOOL_VEC4:  applyUniform4bv(location, arraySize, b);       break;
-              case GL_FLOAT:      applyUniform1fv(location, arraySize, f);       break;
-              case GL_FLOAT_VEC2: applyUniform2fv(location, arraySize, f);       break;
-              case GL_FLOAT_VEC3: applyUniform3fv(location, arraySize, f);       break;
-              case GL_FLOAT_VEC4: applyUniform4fv(location, arraySize, f);       break;
-              case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, arraySize, f); break;
-              case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, arraySize, f); break;
-              case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, arraySize, f); break;
+              case GL_BOOL:       applyUniformnbv(targetUniform, arraySize, 1, b);    break;
+              case GL_BOOL_VEC2:  applyUniformnbv(targetUniform, arraySize, 2, b);    break;
+              case GL_BOOL_VEC3:  applyUniformnbv(targetUniform, arraySize, 3, b);    break;
+              case GL_BOOL_VEC4:  applyUniformnbv(targetUniform, arraySize, 4, b);    break;
+              case GL_FLOAT:
+              case GL_FLOAT_VEC2:
+              case GL_FLOAT_VEC3:
+              case GL_FLOAT_VEC4:
+              case GL_FLOAT_MAT2:
+              case GL_FLOAT_MAT3:
+              case GL_FLOAT_MAT4: applyUniformnfv(targetUniform, f);                  break;
               case GL_SAMPLER_2D:
               case GL_SAMPLER_CUBE:
-              case GL_INT:        applyUniform1iv(location, arraySize, i);       break;
-              case GL_INT_VEC2:   applyUniform2iv(location, arraySize, i);       break;
-              case GL_INT_VEC3:   applyUniform3iv(location, arraySize, i);       break;
-              case GL_INT_VEC4:   applyUniform4iv(location, arraySize, i);       break;
+              case GL_INT:        applyUniform1iv(targetUniform, arraySize, i);       break;
+              case GL_INT_VEC2:   applyUniform2iv(targetUniform, arraySize, i);       break;
+              case GL_INT_VEC3:   applyUniform3iv(targetUniform, arraySize, i);       break;
+              case GL_INT_VEC4:   applyUniform4iv(targetUniform, arraySize, i);       break;
               default:
                 UNREACHABLE();
             }
 
             targetUniform->dirty = false;
         }
     }
 }
@@ -1721,31 +1838,33 @@ bool Program::defineUniform(const D3DXHA
         {
             if (mConstantTablePS->GetConstantByName(NULL, constantDescription.Name) != NULL)
             {
                 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
                 {
                     mSamplersPS[samplerIndex].active = true;
                     mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
                     mSamplersPS[samplerIndex].logicalTextureUnit = 0;
+                    mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
                 }
                 else
                 {
                     appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
                     return false;
                 }
             }
             
             if (mConstantTableVS->GetConstantByName(NULL, constantDescription.Name) != NULL)
             {
                 if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
                 {
                     mSamplersVS[samplerIndex].active = true;
                     mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
                     mSamplersVS[samplerIndex].logicalTextureUnit = 0;
+                    mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
                 }
                 else
                 {
                     appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
                     return false;
                 }
             }
         }
@@ -1811,16 +1930,19 @@ bool Program::defineUniform(const D3DXCO
             return false;
         }
         else
         {
             return true;
         }
     }
 
+    initializeConstantHandles(uniform, &uniform->ps, mConstantTablePS);
+    initializeConstantHandles(uniform, &uniform->vs, mConstantTableVS);
+
     mUniforms.push_back(uniform);
     unsigned int uniformIndex = mUniforms.size() - 1;
 
     for (unsigned int i = 0; i < uniform->arraySize; ++i)
     {
         mUniformIndex.push_back(UniformLocation(_name, i, uniformIndex));
     }
 
@@ -1922,540 +2044,235 @@ std::string Program::undecorateUniform(c
     else if (_name.compare(0, 3, "ar_") == 0)
     {
         return _name.substr(3);
     }
     
     return _name;
 }
 
-bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)
+void Program::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v)
 {
-    BOOL *vector = new BOOL[count];
-    for (int i = 0; i < count; i++)
+    IDirect3DDevice9 *device = getDevice();
+
+    float *vector = NULL;
+    BOOL *boolVector = NULL;
+
+    if (targetUniform->ps.registerCount && targetUniform->ps.registerSet == D3DXRS_FLOAT4 ||
+        targetUniform->vs.registerCount && targetUniform->vs.registerSet == D3DXRS_FLOAT4)
     {
-        if (v[i] == GL_FALSE)
-            vector[i] = 0;
-        else 
-            vector[i] = 1;
+        vector = new float[4 * count];
+
+        for (int i = 0; i < count; i++)
+        {
+            for (int j = 0; j < 4; j++)
+            {
+                if (j < width)
+                {
+                    vector[i * 4 + j] = (v[i * width + j] == GL_FALSE) ? 0.0f : 1.0f;
+                }
+                else
+                {
+                    vector[i * 4 + j] = 0.0f;
+                }
+            }
+        }
     }
 
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
+    if (targetUniform->ps.registerCount && targetUniform->ps.registerSet == D3DXRS_BOOL ||
+        targetUniform->vs.registerCount && targetUniform->vs.registerSet == D3DXRS_BOOL)
+    {
+        boolVector = new BOOL[count * width];
+        for (int i = 0; i < count * width; i++)
+        {
+            boolVector[i] = v[i] != GL_FALSE;
+        }
+    }
+
+    if (targetUniform->ps.registerCount)
     {
-        mConstantTablePS->SetBoolArray(device, constantPS, vector, count);
+        if (targetUniform->ps.registerSet == D3DXRS_FLOAT4)
+        {
+            device->SetPixelShaderConstantF(targetUniform->ps.registerIndex, vector, targetUniform->ps.registerCount);
+        }
+        else if (targetUniform->ps.registerSet == D3DXRS_BOOL)
+        {
+            device->SetPixelShaderConstantB(targetUniform->ps.registerIndex, boolVector, targetUniform->ps.registerCount);
+        }
+        else UNREACHABLE();
     }
 
-    if (constantVS)
+    if (targetUniform->vs.registerCount)
     {
-        mConstantTableVS->SetBoolArray(device, constantVS, vector, count);
+        if (targetUniform->vs.registerSet == D3DXRS_FLOAT4)
+        {
+            device->SetVertexShaderConstantF(targetUniform->vs.registerIndex, vector, targetUniform->vs.registerCount);
+        }
+        else if (targetUniform->vs.registerSet == D3DXRS_BOOL)
+        {
+            device->SetVertexShaderConstantB(targetUniform->vs.registerIndex, boolVector, targetUniform->vs.registerCount);
+        }
+        else UNREACHABLE();
     }
 
     delete [] vector;
-
-    return true;
+    delete [] boolVector;
 }
 
-bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)
+bool Program::applyUniformnfv(Uniform *targetUniform, const GLfloat *v)
 {
-    D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
-
-    for (int i = 0; i < count; i++)
-    {
-        vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
-                                (v[1] == GL_FALSE ? 0.0f : 1.0f), 0, 0);
-
-        v += 2;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
     IDirect3DDevice9 *device = getDevice();
 
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
-    }
-
-    if (constantVS)
+    if (targetUniform->ps.registerCount)
     {
-        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
-    }
-
-    delete[] vector;
-
-    return true;
-}
-
-bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)
-{
-    D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
-
-    for (int i = 0; i < count; i++)
-    {
-        vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
-                                (v[1] == GL_FALSE ? 0.0f : 1.0f), 
-                                (v[2] == GL_FALSE ? 0.0f : 1.0f), 0);
-
-        v += 3;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+        device->SetPixelShaderConstantF(targetUniform->ps.registerIndex, v, targetUniform->ps.registerCount);
     }
 
-    if (constantVS)
-    {
-        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
-    }
-
-    delete[] vector;
-
-    return true;
-}
-
-bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)
-{
-    D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
-
-    for (int i = 0; i < count; i++)
+    if (targetUniform->vs.registerCount)
     {
-        vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
-                                (v[1] == GL_FALSE ? 0.0f : 1.0f), 
-                                (v[2] == GL_FALSE ? 0.0f : 1.0f), 
-                                (v[3] == GL_FALSE ? 0.0f : 1.0f));
-
-        v += 3;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
-    }
-
-    delete [] vector;
-
-    return true;
-}
-
-bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetFloatArray(device, constantPS, v, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetFloatArray(device, constantVS, v, count);
+        device->SetVertexShaderConstantF(targetUniform->vs.registerIndex, v, targetUniform->vs.registerCount);
     }
 
     return true;
 }
 
-bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+bool Program::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v)
 {
     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
 
     for (int i = 0; i < count; i++)
     {
-        vector[i] = D3DXVECTOR4(v[0], v[1], 0, 0);
-
-        v += 2;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
-    }
-
-    delete[] vector;
-
-    return true;
-}
-
-bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
-
-    for (int i = 0; i < count; i++)
-    {
-        vector[i] = D3DXVECTOR4(v[0], v[1], v[2], 0);
-
-        v += 3;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+        vector[i] = D3DXVECTOR4((float)v[i], 0, 0, 0);
     }
 
-    if (constantVS)
-    {
-        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
-    }
-
-    delete[] vector;
-
-    return true;
-}
-
-bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
     IDirect3DDevice9 *device = getDevice();
 
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, (D3DXVECTOR4*)v, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetVectorArray(device, constantVS, (D3DXVECTOR4*)v, count);
-    }
-
-    return true;
-}
-
-bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
-{
-    D3DXMATRIX *matrix = new D3DXMATRIX[count];
-
-    for (int i = 0; i < count; i++)
-    {
-        matrix[i] = D3DXMATRIX(value[0], value[2], 0, 0,
-                               value[1], value[3], 0, 0,
-                               0,        0,        1, 0,
-                               0,        0,        0, 1);
-
-        value += 4;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
+    if (targetUniform->ps.registerCount)
     {
-        mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
-    }
-
-    delete[] matrix;
-
-    return true;
-}
-
-bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
-{
-    D3DXMATRIX *matrix = new D3DXMATRIX[count];
-
-    for (int i = 0; i < count; i++)
-    {
-        matrix[i] = D3DXMATRIX(value[0], value[3], value[6], 0,
-                               value[1], value[4], value[7], 0,
-                               value[2], value[5], value[8], 0,
-                               0,        0,        0,        1);
-
-        value += 9;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
-    }
-
-    delete[] matrix;
-
-    return true;
-}
-
-bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
-{
-    D3DXMATRIX *matrix = new D3DXMATRIX[count];
-
-    for (int i = 0; i < count; i++)
-    {
-        matrix[i] = D3DXMATRIX(value[0], value[4], value[8],  value[12],
-                               value[1], value[5], value[9],  value[13],
-                               value[2], value[6], value[10], value[14],
-                               value[3], value[7], value[11], value[15]);
-
-        value += 16;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
-    }
-
-    delete[] matrix;
-
-    return true;
-}
-
-bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
-{
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        D3DXCONSTANT_DESC constantDescription;
-        UINT descriptionCount = 1;
-        HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
-        ASSERT(SUCCEEDED(result));
-
-        if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
+        if (targetUniform->ps.registerSet == D3DXRS_SAMPLER)
         {
-            unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS);
+            unsigned int firstIndex = targetUniform->ps.registerIndex;
 
             for (int i = 0; i < count; i++)
             {
                 unsigned int samplerIndex = firstIndex + i;
 
                 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
                 {
                     ASSERT(mSamplersPS[samplerIndex].active);
                     mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
                 }
             }
         }
         else
         {
-            mConstantTablePS->SetIntArray(device, constantPS, v, count);
+            ASSERT(targetUniform->ps.registerSet == D3DXRS_FLOAT4);
+            device->SetPixelShaderConstantF(targetUniform->ps.registerIndex, (const float*)vector, targetUniform->ps.registerCount);
         }
     }
 
-    if (constantVS)
+    if (targetUniform->vs.registerCount)
     {
-        D3DXCONSTANT_DESC constantDescription;
-        UINT descriptionCount = 1;
-        HRESULT result = mConstantTableVS->GetConstantDesc(constantVS, &constantDescription, &descriptionCount);
-        ASSERT(SUCCEEDED(result));
-
-        if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
+        if (targetUniform->vs.registerSet == D3DXRS_SAMPLER)
         {
-            unsigned int firstIndex = mConstantTableVS->GetSamplerIndex(constantVS);
+            unsigned int firstIndex = targetUniform->vs.registerIndex;
 
             for (int i = 0; i < count; i++)
             {
                 unsigned int samplerIndex = firstIndex + i;
 
                 if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
                 {
                     ASSERT(mSamplersVS[samplerIndex].active);
                     mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
                 }
             }
         }
         else
         {
-            mConstantTableVS->SetIntArray(device, constantVS, v, count);
+            ASSERT(targetUniform->vs.registerSet == D3DXRS_FLOAT4);
+            device->SetVertexShaderConstantF(targetUniform->vs.registerIndex, (const float *)vector, targetUniform->vs.registerCount);
         }
     }
 
+    delete [] vector;
+
     return true;
 }
 
-bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
+bool Program::applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v)
 {
     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
 
     for (int i = 0; i < count; i++)
     {
         vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], 0, 0);
 
         v += 2;
     }
 
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
-    }
+    applyUniformniv(targetUniform, count, vector);
 
     delete[] vector;
 
     return true;
 }
 
-bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
+bool Program::applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v)
 {
     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
 
     for (int i = 0; i < count; i++)
     {
         vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], 0);
 
         v += 3;
     }
 
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
-    }
+    applyUniformniv(targetUniform, count, vector);
 
     delete[] vector;
 
     return true;
 }
 
-bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
+bool Program::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v)
 {
     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
 
     for (int i = 0; i < count; i++)
     {
         vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
 
         v += 4;
     }
 
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    D3DXHANDLE constantPS;
-    D3DXHANDLE constantVS;
-    getConstantHandles(targetUniform, &constantPS, &constantVS);
-    IDirect3DDevice9 *device = getDevice();
-
-    if (constantPS)
-    {
-        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
-    }
-
-    if (constantVS)
-    {
-        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
-    }
+    applyUniformniv(targetUniform, count, vector);
 
     delete [] vector;
 
     return true;
 }
 
+void Program::applyUniformniv(Uniform *targetUniform, GLsizei count, const D3DXVECTOR4 *vector)
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    if (targetUniform->ps.registerCount)
+    {
+        ASSERT(targetUniform->ps.registerSet == D3DXRS_FLOAT4);
+        device->SetPixelShaderConstantF(targetUniform->ps.registerIndex, (const float *)vector, targetUniform->ps.registerCount);
+    }
+
+    if (targetUniform->vs.registerCount)
+    {
+        ASSERT(targetUniform->vs.registerSet == D3DXRS_FLOAT4);
+        device->SetVertexShaderConstantF(targetUniform->vs.registerIndex, (const float *)vector, targetUniform->vs.registerCount);
+    }
+}
 
 // append a santized message to the program info log.
 // The D3D compiler includes a fake file path in some of the warning or error 
 // messages, so lets remove all occurrences of this fake file path from the log.
 void Program::appendToInfoLogSanitized(const char *message)
 {
     std::string msg(message);
 
@@ -2510,17 +2327,17 @@ void Program::resetInfoLog()
 {
     if (mInfoLog)
     {
         delete [] mInfoLog;
         mInfoLog = NULL;
     }
 }
 
-// Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
+// Returns the program object to an unlinked state, before re-linking, or at destruction
 void Program::unlink(bool destroy)
 {
     if (destroy)   // Object being destructed
     {
         if (mFragmentShader)
         {
             mFragmentShader->release();
             mFragmentShader = NULL;
@@ -2568,16 +2385,19 @@ void Program::unlink(bool destroy)
         mSamplersPS[index].active = false;
     }
 
     for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
     {
         mSamplersVS[index].active = false;
     }
 
+    mUsedVertexSamplerRange = 0;
+    mUsedPixelSamplerRange = 0;
+
     while (!mUniforms.empty())
     {
         delete mUniforms.back();
         mUniforms.pop_back();
     }
 
     mDxDepthRangeLocation = -1;
     mDxDepthLocation = -1;
@@ -2895,17 +2715,17 @@ bool Program::validateSamplers(bool logE
     const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
     TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
 
     for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
     {
         textureUnitType[i] = TEXTURE_UNKNOWN;
     }
 
-    for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+    for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
     {
         if (mSamplersPS[i].active)
         {
             unsigned int unit = mSamplersPS[i].logicalTextureUnit;
             
             if (unit >= maxCombinedTextureImageUnits)
             {
                 if (logErrors)
@@ -2930,17 +2750,17 @@ bool Program::validateSamplers(bool logE
             }
             else
             {
                 textureUnitType[unit] = mSamplersPS[i].textureType;
             }
         }
     }
 
-    for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
+    for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
     {
         if (mSamplersVS[i].active)
         {
             unsigned int unit = mSamplersVS[i].logicalTextureUnit;
             
             if (unit >= maxCombinedTextureImageUnits)
             {
                 if (logErrors)
@@ -2968,27 +2788,33 @@ bool Program::validateSamplers(bool logE
                 textureUnitType[unit] = mSamplersVS[i].textureType;
             }
         }
     }
 
     return true;
 }
 
-void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS)
+void Program::initializeConstantHandles(Uniform *targetUniform, Uniform::RegisterInfo *ri, ID3DXConstantTable *constantTable)
 {
-    if (!targetUniform->handlesSet)
+    D3DXHANDLE handle = constantTable->GetConstantByName(0, targetUniform->_name.c_str());
+    if (handle)
     {
-        targetUniform->psHandle = mConstantTablePS->GetConstantByName(0, targetUniform->_name.c_str());
-        targetUniform->vsHandle = mConstantTableVS->GetConstantByName(0, targetUniform->_name.c_str());
-        targetUniform->handlesSet = true;
+        UINT descriptionCount = 1;
+        D3DXCONSTANT_DESC constantDescription;
+        HRESULT result = constantTable->GetConstantDesc(handle, &constantDescription, &descriptionCount);
+        ASSERT(SUCCEEDED(result));
+        ri->registerIndex = constantDescription.RegisterIndex;
+        ri->registerCount = constantDescription.RegisterCount;
+        ri->registerSet = constantDescription.RegisterSet;
     }
-
-    *constantPS = targetUniform->psHandle;
-    *constantVS = targetUniform->vsHandle;
+    else
+    {
+        ri->registerCount = 0;
+    }
 }
 
 GLint Program::getDxDepthRangeLocation() const
 {
     return mDxDepthRangeLocation;
 }
 
 GLint Program::getDxDepthLocation() const
--- a/gfx/angle/src/libGLESv2/Program.h
+++ b/gfx/angle/src/libGLESv2/Program.h
@@ -37,19 +37,25 @@ struct Uniform
     const GLenum type;
     const std::string _name;   // Decorated name
     const std::string name;    // Undecorated name
     const unsigned int arraySize;
 
     unsigned char *data;
     bool dirty;
 
-    D3DXHANDLE vsHandle;
-    D3DXHANDLE psHandle;
-    bool handlesSet;
+    struct RegisterInfo
+    {
+        int registerSet;
+        int registerIndex;
+        int registerCount;
+    };
+
+    RegisterInfo ps;
+    RegisterInfo vs;
 };
 
 // Struct used for correlating uniforms/elements of uniform arrays to handles
 struct UniformLocation
 {
     UniformLocation(const std::string &_name, unsigned int element, unsigned int index);
 
     std::string name;
@@ -72,16 +78,17 @@ class Program
     IDirect3DVertexShader9 *getVertexShader();
 
     void bindAttributeLocation(GLuint index, const char *name);
     GLuint getAttributeLocation(const char *name);
     int getSemanticIndex(int attributeIndex);
 
     GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex);
     TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
+    GLint getUsedSamplerRange(SamplerType type);
 
     GLint getUniformLocation(std::string name);
     bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
     bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
     bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
     bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
     bool setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);
     bool setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);
@@ -144,33 +151,25 @@ class Program
 
     bool linkAttributes();
     int getAttributeBinding(const std::string &name);
 
     bool linkUniforms(ID3DXConstantTable *constantTable);
     bool defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name = "");
     bool defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
     Uniform *createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
-    bool applyUniform1bv(GLint location, GLsizei count, const GLboolean *v);
-    bool applyUniform2bv(GLint location, GLsizei count, const GLboolean *v);
-    bool applyUniform3bv(GLint location, GLsizei count, const GLboolean *v);
-    bool applyUniform4bv(GLint location, GLsizei count, const GLboolean *v);
-    bool applyUniform1fv(GLint location, GLsizei count, const GLfloat *v);
-    bool applyUniform2fv(GLint location, GLsizei count, const GLfloat *v);
-    bool applyUniform3fv(GLint location, GLsizei count, const GLfloat *v);
-    bool applyUniform4fv(GLint location, GLsizei count, const GLfloat *v);
-    bool applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);
-    bool applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);
-    bool applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);
-    bool applyUniform1iv(GLint location, GLsizei count, const GLint *v);
-    bool applyUniform2iv(GLint location, GLsizei count, const GLint *v);
-    bool applyUniform3iv(GLint location, GLsizei count, const GLint *v);
-    bool applyUniform4iv(GLint location, GLsizei count, const GLint *v);
+    bool applyUniformnfv(Uniform *targetUniform, const GLfloat *v);
+    bool applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+    bool applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+    bool applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+    bool applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+    void applyUniformniv(Uniform *targetUniform, GLsizei count, const D3DXVECTOR4 *vector);
+    void applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v);
 
-    void getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS);
+    void initializeConstantHandles(Uniform *targetUniform, Uniform::RegisterInfo *rs, ID3DXConstantTable *constantTable);
 
     void appendToInfoLogSanitized(const char *message);
     void appendToInfoLog(const char *info, ...);
     void resetInfoLog();
 
     static unsigned int issueSerial();
 
     FragmentShader *mFragmentShader;
@@ -192,16 +191,18 @@ class Program
     {
         bool active;
         GLint logicalTextureUnit;
         TextureType textureType;
     };
 
     Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
     Sampler mSamplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
+    GLuint mUsedVertexSamplerRange;
+    GLuint mUsedPixelSamplerRange;
 
     typedef std::vector<Uniform*> UniformArray;
     UniformArray mUniforms;
     typedef std::vector<UniformLocation> UniformIndex;
     UniformIndex mUniformIndex;
 
     GLint mDxDepthRangeLocation;
     GLint mDxDepthLocation;
--- a/gfx/angle/src/libGLESv2/Shader.cpp
+++ b/gfx/angle/src/libGLESv2/Shader.cpp
@@ -152,40 +152,62 @@ int Shader::getSourceLength() const
         return 0;
     }
     else
     {
        return strlen(mSource) + 1;
     }
 }
 
-void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
+int Shader::getTranslatedSourceLength() const
+{
+    if (!mHlsl)
+    {
+        return 0;
+    }
+    else
+    {
+       return strlen(mHlsl) + 1;
+    }
+}
+
+void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer)
 {
     int index = 0;
 
-    if (mSource)
+    if (source)
     {
-        while (index < bufSize - 1 && index < (int)strlen(mSource))
+        while (index < bufSize - 1 && index < (int)strlen(source))
         {
-            source[index] = mSource[index];
+            buffer[index] = source[index];
             index++;
         }
     }
 
     if (bufSize)
     {
-        source[index] = '\0';
+        buffer[index] = '\0';
     }
 
     if (length)
     {
         *length = index;
     }
 }
 
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer)
+{
+    getSourceImpl(mSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
+{
+    getSourceImpl(mHlsl, bufSize, length, buffer);
+}
+
 bool Shader::isCompiled()
 {
     return mHlsl != NULL;
 }
 
 const char *Shader::getHLSL()
 {
     return mHlsl;
--- a/gfx/angle/src/libGLESv2/Shader.h
+++ b/gfx/angle/src/libGLESv2/Shader.h
@@ -52,17 +52,19 @@ class Shader
     virtual GLenum getType() = 0;
     GLuint getHandle() const;
 
     void deleteSource();
     void setSource(GLsizei count, const char **string, const GLint *length);
     int getInfoLogLength() const;
     void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
     int getSourceLength() const;
-    void getSource(GLsizei bufSize, GLsizei *length, char *source);
+    void getSource(GLsizei bufSize, GLsizei *length, char *buffer);
+    int getTranslatedSourceLength() const;
+    void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer);
 
     virtual void compile() = 0;
     bool isCompiled();
     const char *getHLSL();
 
     void addRef();
     void release();
     unsigned int getRefCount() const;
@@ -73,16 +75,18 @@ class Shader
 
   protected:
     DISALLOW_COPY_AND_ASSIGN(Shader);
 
     void parseVaryings();
 
     void compileToHLSL(void *compiler);
 
+    void getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer);
+
     static GLenum parseType(const std::string &type);
     static bool compareVarying(const Varying &x, const Varying &y);
 
     const GLuint mHandle;
     unsigned int mRefCount;     // Number of program objects this shader is attached to
     bool mDeleteStatus;         // Flag to indicate that the shader can be deleted when no longer in use
 
     char *mSource;
--- a/gfx/angle/src/libGLESv2/libGLESv2.cpp
+++ b/gfx/angle/src/libGLESv2/libGLESv2.cpp
@@ -1982,39 +1982,39 @@ void __stdcall glFlush(void)
 void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
 {
     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
           "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
 
     try
     {
         if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
-            || renderbuffertarget != GL_RENDERBUFFER)
+            || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
         {
             return error(GL_INVALID_ENUM);
         }
 
         gl::Context *context = gl::getContext();
 
         if (context)
         {
             gl::Framebuffer *framebuffer = NULL;
             GLuint framebufferHandle = 0;
             if (target == GL_READ_FRAMEBUFFER_ANGLE)
             {
                 framebuffer = context->getReadFramebuffer();
                 framebufferHandle = context->getReadFramebufferHandle();
             }
-            else 
+            else
             {
                 framebuffer = context->getDrawFramebuffer();
                 framebufferHandle = context->getDrawFramebufferHandle();
             }
 
-            if (framebufferHandle == 0 || !framebuffer)
+            if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
             {
                 return error(GL_INVALID_OPERATION);
             }
 
             switch (attachment)
             {
               case GL_COLOR_ATTACHMENT0:
                 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer);
@@ -3084,16 +3084,19 @@ void __stdcall glGetShaderiv(GLuint shad
                 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
                 return;
               case GL_INFO_LOG_LENGTH:
                 *params = shaderObject->getInfoLogLength();
                 return;
               case GL_SHADER_SOURCE_LENGTH:
                 *params = shaderObject->getSourceLength();
                 return;
+              case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+                *params = shaderObject->getTranslatedSourceLength();
+                return;
               default:
                 return error(GL_INVALID_ENUM);
             }
         }
     }
     catch(std::bad_alloc&)
     {
         return error(GL_OUT_OF_MEMORY);
@@ -3204,16 +3207,48 @@ void __stdcall glGetShaderSource(GLuint 
         }
     }
     catch(std::bad_alloc&)
     {
         return error(GL_OUT_OF_MEMORY);
     }
 }
 
+void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
+          shader, bufsize, length, source);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (!shaderObject)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            shaderObject->getTranslatedSource(bufsize, length, source);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
 const GLubyte* __stdcall glGetString(GLenum name)
 {
     EVENT("(GLenum name = 0x%X)", name);
 
     try
     {
         gl::Context *context = gl::getContext();
 
@@ -5764,16 +5799,17 @@ void __stdcall glTexImage3DOES(GLenum ta
         {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE},
         {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV},
         {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV},
         {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV},
         {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV},
         {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV},
         {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV},
         {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV},
+        {"glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)glGetTranslatedShaderSourceANGLE},
     };
 
     for (int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
     {
         if (strcmp(procname, glExtensions[ext].name) == 0)
         {
             return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
         }
--- a/gfx/angle/src/libGLESv2/libGLESv2.def
+++ b/gfx/angle/src/libGLESv2/libGLESv2.def
@@ -149,16 +149,17 @@ EXPORTS
     glRenderbufferStorageMultisampleANGLE @150
     glDeleteFencesNV                @151
     glFinishFenceNV                 @152
     glGenFencesNV                   @153
     glGetFenceivNV                  @154
     glIsFenceNV                     @155
     glSetFenceNV                    @156
     glTestFenceNV                   @157
+    glGetTranslatedShaderSourceANGLE @159
 
     ; EGL dependencies
     glCreateContext                 @144 NONAME
     glDestroyContext                @145 NONAME
     glMakeCurrent                   @146 NONAME
     glGetCurrentContext             @147 NONAME
     glGetProcAddress                @148 NONAME
     glBindTexImage                  @158 NONAME
--- a/gfx/angle/src/libGLESv2/utilities.cpp
+++ b/gfx/angle/src/libGLESv2/utilities.cpp
@@ -49,16 +49,52 @@ int UniformComponentCount(GLenum type)
           return 16;
       default:
           UNREACHABLE();
     }
 
     return 0;
 }
 
+// This is how much data we actually store for a uniform
+int UniformInternalComponentCount(GLenum type)
+{
+    switch (type)
+    {
+      case GL_BOOL:
+      case GL_INT:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_CUBE:
+          return 1;
+      case GL_BOOL_VEC2:
+      case GL_INT_VEC2:
+          return 2;
+      case GL_INT_VEC3:
+      case GL_BOOL_VEC3:
+          return 3;
+      case GL_FLOAT:
+      case GL_FLOAT_VEC2:
+      case GL_FLOAT_VEC3:
+      case GL_BOOL_VEC4:
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+          return 4;
+      case GL_FLOAT_MAT2:
+          return 8;
+      case GL_FLOAT_MAT3:
+          return 12;
+      case GL_FLOAT_MAT4:
+          return 16;
+      default:
+          UNREACHABLE();
+    }
+
+    return 0;
+}
+
 GLenum UniformComponentType(GLenum type)
 {
     switch(type)
     {
       case GL_BOOL:
       case GL_BOOL_VEC2:
       case GL_BOOL_VEC3:
       case GL_BOOL_VEC4:
@@ -80,26 +116,32 @@ GLenum UniformComponentType(GLenum type)
           return GL_INT;
       default:
           UNREACHABLE();
     }
 
     return GL_NONE;
 }
 
-size_t UniformTypeSize(GLenum type)
+size_t UniformComponentSize(GLenum type)
 {
     switch(type)
     {
       case GL_BOOL:  return sizeof(GLboolean);
       case GL_FLOAT: return sizeof(GLfloat);
       case GL_INT:   return sizeof(GLint);
+      default:       UNREACHABLE();
     }
 
-    return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
+    return 0;
+}
+
+size_t UniformTypeSize(GLenum type)
+{
+    return UniformComponentSize(UniformComponentType(type)) * UniformInternalComponentCount(type);
 }
 
 int VariableRowCount(GLenum type)
 {
     switch (type)
     {
       case GL_NONE:
         return 0;
--- a/gfx/angle/src/libGLESv2/utilities.h
+++ b/gfx/angle/src/libGLESv2/utilities.h
@@ -17,16 +17,17 @@
 #include <string>
 
 namespace gl
 {
 
 struct Color;
 
 int UniformComponentCount(GLenum type);
+int UniformInternalComponentCount(GLenum type);
 GLenum UniformComponentType(GLenum type);
 size_t UniformTypeSize(GLenum type);
 int VariableRowCount(GLenum type);
 int VariableColumnCount(GLenum type);
 
 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
 
 int ComputePixelSize(GLenum format, GLenum type);