Bug 696889 - Upgrade ANGLE to r802 - no review
authorBenoit Jacob <bjacob@mozilla.com>
Tue, 25 Oct 2011 08:58:43 -0400
changeset 79837 dd18ab29d0e834dd771ed085581b2213a48cea1b
parent 79836 df2b31a1e4c43040d153d945573ca56df6342d12
child 79838 3131f4933dd48026d607276cfb72e9148481d149
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs696889
milestone10.0a1
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);