Bug 703917 - Upgrade ANGLE to r885 - no review
authorBenoit Jacob <bjacob@mozilla.com>
Sat, 19 Nov 2011 18:18:59 -0500
changeset 82151 18e1ab585ad04b7f121a1dedb64d5697e4e18de8
parent 82150 4c45c9b2cc0c7196d626caeb8c5f23d49228a69a
child 82152 6d1339ba711e2b89ac15c03a9ae77561bea87d12
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs703917
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 703917 - Upgrade ANGLE to r885 - no review This is syncing us with the upstream http://code.google.com/p/angleproject
gfx/angle/README.mozilla
gfx/angle/angle-intrinsic-msvc2005.patch
gfx/angle/angle-renaming-debug.patch
gfx/angle/angle-use-xmalloc.patch
gfx/angle/extensions/ANGLE_texture_usage.txt
gfx/angle/extensions/EGL_EXT_create_context_robustness.txt
gfx/angle/extensions/EXT_robustness.txt
gfx/angle/extensions/EXT_texture_storage.txt
gfx/angle/include/EGL/eglext.h
gfx/angle/include/GLES2/gl2ext.h
gfx/angle/src/common/version.h
gfx/angle/src/compiler/Initialize.cpp
gfx/angle/src/libEGL/Display.cpp
gfx/angle/src/libEGL/Display.h
gfx/angle/src/libEGL/Surface.cpp
gfx/angle/src/libEGL/libEGL.cpp
gfx/angle/src/libGLESv2/Context.cpp
gfx/angle/src/libGLESv2/Context.h
gfx/angle/src/libGLESv2/Fence.cpp
gfx/angle/src/libGLESv2/Framebuffer.cpp
gfx/angle/src/libGLESv2/Framebuffer.h
gfx/angle/src/libGLESv2/Program.cpp
gfx/angle/src/libGLESv2/Program.h
gfx/angle/src/libGLESv2/Renderbuffer.cpp
gfx/angle/src/libGLESv2/Renderbuffer.h
gfx/angle/src/libGLESv2/Texture.cpp
gfx/angle/src/libGLESv2/Texture.h
gfx/angle/src/libGLESv2/VertexDataManager.cpp
gfx/angle/src/libGLESv2/libGLESv2.cpp
gfx/angle/src/libGLESv2/libGLESv2.def
gfx/angle/src/libGLESv2/main.cpp
gfx/angle/src/libGLESv2/main.h
gfx/angle/src/libGLESv2/utilities.cpp
gfx/angle/src/libGLESv2/utilities.h
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -1,11 +1,11 @@
 This is the ANGLE project, from http://code.google.com/p/angleproject/
 
-Current revision: r809
+Current revision: r885
 
 == Applied local patches ==
 
 In this order:
   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.
--- a/gfx/angle/angle-intrinsic-msvc2005.patch
+++ b/gfx/angle/angle-intrinsic-msvc2005.patch
@@ -1,10 +1,10 @@
 # HG changeset patch
-# Parent b5604c321da4e3b5d6b0a940d18022a827061579
+# Parent d9b887da80f5bc18854fb3e5e43637c18d2a25ae
 diff --git a/gfx/angle/src/libGLESv2/Texture.cpp b/gfx/angle/src/libGLESv2/Texture.cpp
 --- a/gfx/angle/src/libGLESv2/Texture.cpp
 +++ b/gfx/angle/src/libGLESv2/Texture.cpp
 @@ -8,16 +8,22 @@
  // Texture2D and TextureCubeMap. Implements GL texture objects and related
  // functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
  
  #include "libGLESv2/Texture.h"
--- a/gfx/angle/angle-renaming-debug.patch
+++ b/gfx/angle/angle-renaming-debug.patch
@@ -1,10 +1,10 @@
 # HG changeset patch
-# Parent 0239f15c7212413b5cffe66aee9ae5a4feb28f16
+# Parent eae39c479485f310e937d8550afc6596aec20159
 diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
 --- a/gfx/angle/Makefile.in
 +++ b/gfx/angle/Makefile.in
 @@ -73,17 +73,17 @@ CPPSRCS = \
          parseConst.cpp \
          ParseHelper.cpp \
          PoolAlloc.cpp \
          QualifierAlive.cpp \
--- a/gfx/angle/angle-use-xmalloc.patch
+++ b/gfx/angle/angle-use-xmalloc.patch
@@ -1,18 +1,18 @@
 # HG changeset patch
-# Parent fecc64a6df53a9056b21958affad38c80ca38496
+# Parent 85ffde53712cab3c217bbbf0c1ec9b7ec2ae8ea6
 
 diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
 --- a/gfx/angle/Makefile.in
 +++ b/gfx/angle/Makefile.in
 @@ -127,16 +127,18 @@ CSRCS   = \
  	$(NULL)
  
- DEFINES += -DANGLE_USE_NSPR -DANGLE_BUILD
+ DEFINES += -DANGLE_USE_NSPR -DANGLE_BUILD -DCOMPILER_IMPLEMENTATION
  
  #these defines are from ANGLE's build_angle.gyp
  DEFINES += -DANGLE_DISABLE_TRACE
  DEFINES += -DANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0
  
 +EXTRA_DSO_LDOPTS = $(MOZALLOC_LIB)
 +
  ifdef MOZ_ANGLE
@@ -22,47 +22,33 @@ diff --git a/gfx/angle/Makefile.in b/gfx
  
  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
 @@ -3,16 +3,17 @@ This is the ANGLE project, from http://c
- Current revision: r774
+ Current revision: r885
  
  == Applied local patches ==
  
  In this order:
-   angle-renaming.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
-   angle-instrinsic-msvc2005.patch - work around a MSVC 2005 compile error
+   angle-renaming-debug.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
+   angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
    angle-limit-identifiers-to-250-chars.patch - see bug 675625
 +  angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands.
  
  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.
-diff --git a/gfx/angle/angle-limit-identifiers-to-250-chars.patch b/gfx/angle/angle-limit-identifiers-to-250-chars.patch
---- a/gfx/angle/angle-limit-identifiers-to-250-chars.patch
-+++ b/gfx/angle/angle-limit-identifiers-to-250-chars.patch
-@@ -1,8 +1,10 @@
-+# HG changeset patch
-+# Parent f9415c10c3ebd27856500cca7a0ee0f28a16f53c
- diff --git a/gfx/angle/src/compiler/preprocessor/scanner.h b/gfx/angle/src/compiler/preprocessor/scanner.h
- --- a/gfx/angle/src/compiler/preprocessor/scanner.h
- +++ b/gfx/angle/src/compiler/preprocessor/scanner.h
- @@ -44,17 +44,19 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILI
-  //
-  // scanner.h
-  //
-  
 diff --git a/gfx/angle/src/compiler/preprocessor/atom.c b/gfx/angle/src/compiler/preprocessor/atom.c
 --- a/gfx/angle/src/compiler/preprocessor/atom.c
 +++ b/gfx/angle/src/compiler/preprocessor/atom.c
 @@ -48,16 +48,18 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILI
  
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
new file mode 100644
--- /dev/null
+++ b/gfx/angle/extensions/ANGLE_texture_usage.txt
@@ -0,0 +1,202 @@
+Name
+
+    ANGLE_texture_usage
+
+Name Strings
+
+    GL_ANGLE_texture_usage
+
+Contributors
+
+    Nicolas Capens, TransGaming
+    Daniel Koch, TransGaming
+
+Contact
+
+    Daniel Koch, TransGaming (daniel 'at' transgaming.com)
+
+Status
+
+    Complete
+
+Version
+
+    Last Modified Date:  November 10, 2011
+    Version:             2
+
+Number
+
+    TBD 
+
+Dependencies
+
+    This extension is written against the OpenGL ES 2.0 Specification.
+
+Overview
+
+    In some implementations it is advantageous to know the expected
+    usage of a texture before the backing storage for it is allocated.  
+    This can help to inform the implementation's choice of format
+    and type of memory used for the allocation. If the usage is not
+    known in advance, the implementation essentially has to make a 
+    guess as to how it will be used.  If it is later proven wrong,
+    it may need to perform costly re-allocations and/or reformatting 
+    of the texture data, resulting in reduced performance.
+
+    This extension adds a texture usage flag that is specified via
+    the TEXTURE_USAGE_ANGLE TexParameter.  This can be used to 
+    indicate that the application knows that this texture will be 
+    used for rendering.
+
+IP Status
+
+    No known IP claims.
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as a value for <pname> for the TexParameter{if} and 
+    TexParameter{if}v commands and for the <value> parameter of
+    GetTexParameter{if}v: 
+
+        TEXTURE_USAGE_ANGLE                     0x93A2
+
+    Accepted as a value to <param> for the TexParameter{if} and 
+    to <params> for the TexParameter{if}v commands with a <pname> of 
+    TEXTURE_USAGE_ANGLE; returned as possible values for <data> when 
+    GetTexParameter{if}v is queried with a <value> of TEXTURE_USAGE_ANGLE:
+
+        NONE                                    0x0000
+        FRAMEBUFFER_ATTACHMENT_ANGLE            0x93A3
+
+Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
+
+    None
+
+Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
+
+    Add a new row to Table 3.10 (Texture parameters and their values):
+
+    Name                | Type | Legal Values 
+    ------------------------------------------------------------
+    TEXTURE_USAGE_ANGLE | enum | NONE, FRAMEBUFFER_ATTACHMENT_ANGLE
+
+    Add a new section 3.7.x (Texture Usage) before section 3.7.12 and 
+    renumber the subsequent sections: 
+
+    "3.7.x Texture Usage
+
+    Texture usage can be specified via the TEXTURE_USAGE_ANGLE value
+    for the <pname> argument to TexParameter{if}[v]. In order to take effect,
+    the texture usage must be specified before the texture contents are
+    defined either via TexImage2D or TexStorage2DEXT.
+
+    The usage values can impact the layout and type of memory used for the 
+    texture data. Specifying incorrect usage values may result in reduced
+    functionality and/or significantly degraded performance.
+
+    Possible values for <params> when <pname> is TEXTURE_USAGE_ANGLE are:
+
+    NONE - the default. No particular usage has been specified and it is
+        up to the implementation to determine the usage of the texture.
+        Leaving the usage unspecified means that the implementation may 
+        have to reallocate the texture data as the texture is used in 
+        various ways.
+
+    FRAMEBUFFER_ATTACHMENT_ANGLE - this texture will be attached to a 
+        framebuffer object and used as a desination for rendering or blits."
+
+    Modify section 3.7.12 (Texture State) and place the last 3 sentences
+    with the following:
+
+    "Next, there are the three sets of texture properties; each consists of
+    the selected minification and magnification filters, the wrap modes for
+    <s> and <t>, and the usage flags. In the initial state, the value assigned
+    to TEXTURE_MIN_FILTER is NEAREST_MIPMAP_LINEAR, and the value for 
+    TEXTURE_MAG_FILTER is LINEAR. <s> and <t> wrap modes are both set to
+    REPEAT. The initial value for TEXTURE_USAGE_ANGLE is NONE."
+
+
+Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
+Operations and the Framebuffer)
+
+    None
+
+Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special
+Functions):
+
+    None
+
+Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and
+State Requests)
+
+    None
+
+Dependencies on EXT_texture_storage
+
+    If EXT_texture_storage is not supported, omit any references to 
+    TexStorage2DEXT.
+
+Errors
+
+    If TexParameter{if} or TexParamter{if}v is called with a <pname>
+    of TEXTURE_USAGE_ANGLE and the value of <param> or <params> is not
+    NONE or FRAMEBUFFER_ATTACHMENT_ANGLE the error INVALID_VALUE is
+    generated.
+
+Usage Example
+
+    /* create and bind texture */
+    glGenTextures(1, &texture);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, texture);
+
+    /* specify texture parameters */
+    glTexParameteri(GL_TEXTURE_2D, GL_*, ...);  /* as before */
+    
+    /* specify that we'll be rendering to the texture */
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+
+    glTexStorage2DEXT(GL_TEXTURE_2D, levels, ...); // Allocation
+    for(int level = 0; level < levels; ++level)
+        glTexSubImage2D(GL_TEXTURE_2D, level, ...); // Initialisation
+
+Issues
+
+    1. Should there be a dynamic usage value?
+   
+       DISCUSSION: We could accept a dynamic flag to indicate that a texture will
+       be updated frequently. We could map this to D3D9 dynamic textures. This would
+       allow us to avoid creating temporary surfaces when updating the texture.
+       However renderable textures cannot be dynamic in D3D9, which eliminates the 
+       primary use case for this.  Furthermore, the memory usage of dynamic textures
+       typically increases threefold when you lock it.
+
+    2. Should the texture usage be an enum or a bitfield?
+
+       UNRESOLVED.  Using a bitfield would allow combination of values to be specified.
+       On the other hand, if combinations are really required, additional <pnames>
+       could be added as necessary.  Querying a bitfield via the GetTexParameter command
+       feels a bit odd.
+
+    3. What should happen if TEXTURE_USAGE_ANGLE is set/changed after the texture
+       contents have been specified?
+
+       RESOLVED: It will have no effect. However, if the texture is redefined (for 
+       example by TexImage2D) the new allocation will use the updated usage.
+       GetTexParameter is used to query the value of the TEXTURE_USAGE_ANGLE
+       state that was last set by TexParameter for the currently bound texture, or
+       the default value if it has never been set. There is no way to determine the 
+       usage that was in effect at the time the texture was defined.
+
+Revision History
+
+    Rev.    Date      Author     Changes
+    ----  ----------- ---------  ----------------------------------------
+      1   10 Nov 2011 dgkoch     Initial revision
+      2   10 Nov 2011 dgkoch     Add overview
+   
+
new file mode 100644
--- /dev/null
+++ b/gfx/angle/extensions/EGL_EXT_create_context_robustness.txt
@@ -0,0 +1,169 @@
+Name
+
+    EXT_create_context_robustness
+
+Name Strings
+
+    EGL_EXT_create_context_robustness
+
+Contributors
+
+    Daniel Koch, TransGaming
+    Contributors to EGL_KHR_create_context
+
+Contact
+
+    Greg Roth (groth 'at' nvidia.com)
+
+Status
+
+    Complete.
+
+Version
+
+    Version 3, 2011/10/31
+
+Number
+
+    TBD
+
+Dependencies
+
+    Requires EGL 1.4
+
+    Written against the EGL 1.4 specification.
+
+    An OpenGL implementation supporting GL_ARB_robustness, an OpenGL ES
+    implementation supporting GL_EXT_robustness, or an implementation
+    supporting equivalent functionality is required.
+
+Overview
+
+    This extension allows creating an OpenGL or OpenGL ES context
+    supporting robust buffer access behavior and a specified graphics
+    reset notification behavior.
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as an attribute name in the <*attrib_list> argument to
+    eglCreateContext:
+
+        EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT    0x30BF
+        EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT  0x3138
+
+    Accepted as an attribute value for EGL_CONTEXT_RESET_NOTIFICATION_-
+    STRATEGY_EXT in the <*attrib_list> argument to eglCreateContext:
+
+        EGL_NO_RESET_NOTIFICATION_EXT           0x31BE
+        EGL_LOSE_CONTEXT_ON_RESET_EXT           0x31BF
+
+Additions to the EGL 1.4 Specification
+
+    Replace section 3.7.1 "Creating Rendering Contexts" from the
+    fifth paragraph through the seventh paragraph:
+
+    <attrib_list> specifies a list of attributes for the context. The
+    list has the same structure as described for eglChooseConfig. If an
+    attribute is not specified in <attrib_list>, then the default value
+    specified below is used instead. <attrib_list> may be NULL or empty
+    (first attribute is EGL_NONE), in which case attributes assume their
+    default values as described below. Most attributes are only meaningful
+    for specific client APIs, and will generate an EGL_BAD_ATTRIBUTE
+    error when specified to create for another client API context.
+
+    Context Versions
+    ----------------
+
+    EGL_CONTEXT_CLIENT_VERSION determines which version of an OpenGL ES
+    context to create. This attribute may only be specified when creating
+    an OpenGL ES context (e.g. when the current rendering API is
+    EGL_OPENGL_ES_API). An attribute value of 1 specifies creation of an
+    OpenGL ES 1.x context.  An attribute value of 2 specifies creation of an
+    Open GL ES 2.x context. The default value for EGL_CONTEXT_CLIENT_VERSION
+    is 1.
+
+    Context Robust Access
+    -------------
+
+    EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT indicates whether <robust buffer
+    access> should be enabled for the OpenGL ES context. Robust buffer
+    access is defined in the GL_EXT_robustness extension specification,
+    and the resulting context must support GL_EXT_robustness and robust
+    buffer access as described therein. The default value of
+    EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT is EGL_FALSE.
+
+    Context Reset Notification
+    --------------------------
+
+    The attribute name EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_-
+    EXT specifies the <reset notification behavior> of the rendering
+    context. This attribute is only meaningful for OpenGL ES contexts,
+    and specifying it for other types of contexts will generate an
+    EGL_BAD_ATTRIBUTE error.
+
+    Reset notification behavior is defined in the GL_EXT_robustness
+    extension for OpenGL ES, and the resulting context must support
+    GL_EXT_robustness and the specified reset strategy. The attribute
+    value may be either EGL_NO_RESET_NOTIFICATION_EXT or EGL_LOSE_-
+    CONTEXT_ON_RESET_EXT, which respectively result in disabling
+    delivery of reset notifications or the loss of all context state
+    upon reset notification as described by the GL_EXT_robustness. The
+    default value for EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT
+    is EGL_NO_RESET_NOTIFICATION_EXT.
+    
+    Add to the eglCreateContext context creation errors:
+
+    * If <config> does not support a client API context compatible
+      with the requested context flags and context reset notification
+      behavior (for client API types where these attributes are
+      supported), then an EGL_BAD_CONFIG error is generated.
+
+    * If the reset notification behavior of <share_context> and the
+      newly created context are different then an EGL_BAD_MATCH error is
+      generated.
+
+
+Errors
+
+    EGL_BAD_CONFIG is generated if EGL_CONTEXT_OPENGL_ROBUST_ACCESS_-
+    EXT is set to EGL_TRUE and no GL context supporting the GL_EXT_-
+    robustness extension and robust access as described therein can be
+    created.
+
+    EGL_BAD_CONFIG is generated if no GL context supporting the
+    GL_EXT_robustness extension and the specified reset notification
+    behavior (the value of attribute EGL_CONTEXT_RESET_NOTIFICATION_-
+    STRATEGY_EXT) can be created.
+
+    BAD_MATCH is generated if the reset notification behavior of
+    <share_context> does not match the reset notification behavior of
+    the context being created.
+
+New State
+
+    None
+
+Conformance Tests
+
+    TBD
+
+Sample Code
+
+    TBD
+
+Issues
+
+    None
+
+Revision History
+
+    Rev.    Date       Author     Changes
+    ----  ------------ ---------  ----------------------------------------
+      3   31 Oct  2011 groth      Reverted to attribute for robust access. Now it's a
+                                  companion to rather than subset of KHR_create_context
+      2   11 Oct  2011 groth      Merged ANGLE and NV extensions.
+      1   15 July 2011 groth      Initial version
new file mode 100644
--- /dev/null
+++ b/gfx/angle/extensions/EXT_robustness.txt
@@ -0,0 +1,365 @@
+Name
+
+    EXT_robustness
+
+Name Strings
+
+    GL_EXT_robustness
+
+Contributors
+
+    Daniel Koch, TransGaming
+    Nicolas Capens, TransGaming
+    Contributors to ARB_robustness
+
+Contact
+
+    Greg Roth, NVIDIA (groth 'at' nvidia.com)
+
+Status
+
+    Complete.
+
+Version
+
+    Version 3, 2011/10/31
+
+Number
+
+    TBD
+
+Dependencies
+
+    This extension is written against the OpenGL ES 2.0 Specification
+    but can apply to OpenGL ES 1.1 and up.
+
+    EGL_EXT_create_context_robustness is used to determine if a context
+    implementing this extension supports robust buffer access, and if it
+    supports reset notification. 
+
+Overview
+
+    Several recent trends in how OpenGL integrates into modern computer
+    systems have created new requirements for robustness and security
+    for OpenGL rendering contexts.
+    
+    Additionally GPU architectures now support hardware fault detection;
+    for example, video memory supporting ECC (error correcting codes)
+    and error detection.  OpenGL contexts should be capable of recovering
+    from hardware faults such as uncorrectable memory errors.  Along with
+    recovery from such hardware faults, the recovery mechanism can
+    also allow recovery from video memory access exceptions and system
+    software failures.  System software failures can be due to device
+    changes or driver failures.
+
+    OpenGL queries that that return (write) some number of bytes to a
+    buffer indicated by a pointer parameter introduce risk of buffer
+    overflows that might be exploitable by malware. To address this,
+    queries with return value sizes that are not expressed directly by
+    the parameters to the query itself are given additional API
+    functions with an additional parameter that specifies the number of
+    bytes in the buffer and never writing bytes beyond that limit. This
+    is particularly useful for multi-threaded usage of OpenGL contexts
+    in a "share group" where one context can change objects in ways that
+    can cause buffer overflows for another context's OpenGL queries.
+
+    The original ARB_vertex_buffer_object extension includes an issue
+    that explicitly states program termination is allowed when
+    out-of-bounds vertex buffer object fetches occur. Modern graphics
+    hardware is capable well-defined behavior in the case of out-of-
+    bounds vertex buffer object fetches. Older hardware may require
+    extra checks to enforce well-defined (and termination free)
+    behavior, but this expense is warranted when processing potentially
+    untrusted content.
+
+    The intent of this extension is to address some specific robustness
+    goals:
+
+    *   For all existing OpenGL queries, provide additional "safe" APIs 
+        that limit data written to user pointers to a buffer size in 
+        bytes that is an explicit additional parameter of the query.
+
+    *   Provide a mechanism for an OpenGL application to learn about
+        graphics resets that affect the context.  When a graphics reset
+        occurs, the OpenGL context becomes unusable and the application
+        must create a new context to continue operation. Detecting a
+        graphics reset happens through an inexpensive query.
+
+    *   Provide an enable to guarantee that out-of-bounds buffer object
+        accesses by the GPU will have deterministic behavior and preclude
+        application instability or termination due to an incorrect buffer
+        access.  Such accesses include vertex buffer fetches of
+        attributes and indices, and indexed reads of uniforms or
+        parameters from buffers.
+
+New Procedures and Functions
+
+        enum GetGraphicsResetStatusEXT();
+
+        void ReadnPixelsEXT(int x, int y, sizei width, sizei height,
+                            enum format, enum type, sizei bufSize,
+                            void *data);
+
+        void GetnUniformfvEXT(uint program, int location, sizei bufSize,
+                              float *params);
+        void GetnUniformivEXT(uint program, int location, sizei bufSize,
+                              int *params);
+
+New Tokens
+
+    Returned by GetGraphicsResetStatusEXT:
+
+        NO_ERROR                                        0x0000
+        GUILTY_CONTEXT_RESET_EXT                        0x8253
+        INNOCENT_CONTEXT_RESET_EXT                      0x8254
+        UNKNOWN_CONTEXT_RESET_EXT                       0x8255
+
+    Accepted by the <value> parameter of GetBooleanv, GetIntegerv,
+    and GetFloatv:
+
+        CONTEXT_ROBUST_ACCESS_EXT                       0x90F3
+        RESET_NOTIFICATION_STRATEGY_EXT                 0x8256
+
+    Returned by GetIntegerv and related simple queries when <value> is
+    RESET_NOTIFICATION_STRATEGY_EXT :
+
+        LOSE_CONTEXT_ON_RESET_EXT                       0x8252
+        NO_RESET_NOTIFICATION_EXT                       0x8261
+
+Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
+
+Add a new subsection after 2.5 "GL Errors" and renumber subsequent
+sections accordingly.
+
+    2.6 "Graphics Reset Recovery"
+
+    Certain events can result in a reset of the GL context. Such a reset
+    causes all context state to be lost. Recovery from such events
+    requires recreation of all objects in the affected context. The
+    current status of the graphics reset state is returned by
+
+        enum GetGraphicsResetStatusEXT();
+
+    The symbolic constant returned indicates if the GL context has been
+    in a reset state at any point since the last call to
+    GetGraphicsResetStatusEXT. NO_ERROR indicates that the GL context
+    has not been in a reset state since the last call.
+    GUILTY_CONTEXT_RESET_EXT indicates that a reset has been detected
+    that is attributable to the current GL context.
+    INNOCENT_CONTEXT_RESET_EXT indicates a reset has been detected that
+    is not attributable to the current GL context.
+    UNKNOWN_CONTEXT_RESET_EXT indicates a detected graphics reset whose
+    cause is unknown.
+
+    If a reset status other than NO_ERROR is returned and subsequent
+    calls return NO_ERROR, the context reset was encountered and
+    completed. If a reset status is repeatedly returned, the context may
+    be in the process of resetting.
+
+    Reset notification behavior is determined at context creation time,
+    and may be queried by calling GetIntegerv with the symbolic constant
+    RESET_NOTIFICATION_STRATEGY_EXT.
+
+    If the reset notification behavior is NO_RESET_NOTIFICATION_EXT,
+    then the implementation will never deliver notification of reset
+    events, and GetGraphicsResetStatusEXT will always return
+    NO_ERROR[fn1].
+       [fn1: In this case it is recommended that implementations should
+        not allow loss of context state no matter what events occur.
+        However, this is only a recommendation, and cannot be relied
+        upon by applications.]
+
+    If the behavior is LOSE_CONTEXT_ON_RESET_EXT, a graphics reset will
+    result in the loss of all context state, requiring the recreation of
+    all associated objects. In this case GetGraphicsResetStatusEXT may
+    return any of the values described above.
+
+    If a graphics reset notification occurs in a context, a notification
+    must also occur in all other contexts which share objects with that
+    context[fn2].
+       [fn2: The values returned by GetGraphicsResetStatusEXT in the
+        different contexts may differ.]
+
+    Add to Section 2.8 "Vertex Arrays" before subsection "Transferring
+    Array Elements"
+
+    Robust buffer access is enabled by creating a context with robust
+    access enabled through the window system binding APIs. When enabled,
+    indices within the vertex array that lie outside the arrays defined
+    for enabled attributes result in undefined values for the
+    corresponding attributes, but cannot result in application failure.
+    Robust buffer access behavior may be queried by calling GetIntegerv
+    with the symbolic constant CONTEXT_ROBUST_ACCESS_EXT.
+
+Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
+Operations and the Frame Buffer)
+
+    Modify section 4.3.1 "Reading Pixels"
+
+    Pixels are read using
+
+        void ReadPixels(int x, int y, sizei width, sizei height,
+                        enum format, enum type, void *data);
+        void ReadnPixelsEXT(int x, int y, sizei width, sizei height,
+                           enum format, enum type, sizei bufSize,
+                           void *data);
+
+    Add to the description of ReadPixels:
+
+    ReadnPixelsEXT behaves identically to ReadPixels except that it does
+    not write more than <bufSize> bytes into <data>. If the buffer size
+    required to fill all the requested data is greater than <bufSize> an
+    INVALID_OPERATION error is generated and <data> is not altered.
+
+Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special
+Functions):
+
+    None
+
+Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and
+State Requests)
+
+    Modify Section 6.1.8 "Shader and Program Queries"
+
+    The commands
+
+        void GetUniformfv(uint program, int location, float *params);
+        void GetnUniformfvEXT(uint program, int location, sizei bufSize,
+                              float *params);
+        void GetUniformiv(uint program, int location, int *params);
+        void GetnUniformivEXT(uint program, int location, sizei bufSize,
+                              int *params);
+
+    return the value or values of the uniform at location <location>
+    for program object <program> in the array <params>. Calling
+    GetnUniformfvEXT or GetnUniformivEXT ensures that no more than
+    <bufSize> bytes are written into <params>. If the buffer size
+    required to fill all the requested data is greater than <bufSize> an
+    INVALID_OPERATION error is generated and <params> is not altered.
+    ...
+
+Additions to The OpenGL ES Shading Language Specification, Version 1.
+
+    Append to the third paragraph of section 4.1.9 "Arrays"
+
+    If robust buffer access is enabled via the OpenGL ES API, such
+    indexing must not result in abnormal program termination. The
+    results are still undefined, but implementations are encouraged to
+    produce zero values for such accesses.
+
+Interactions with EGL_EXT_create_context_robustness
+
+    If the EGL window-system binding API is used to create a context,
+    the EGL_EXT_create_context_robustness extension is supported, and
+    the attribute EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT is set to
+    EGL_TRUE when eglCreateContext is called, the resulting context will
+    perform robust buffer access as described above in section 2.8, and
+    the CONTEXT_ROBUST_ACCESS_EXT query will return GL_TRUE as described
+    above in section 6.1.5.
+
+    If the EGL window-system binding API is used to create a context and
+    the EGL_EXT_create_context_robustness extension is supported, then
+    the value of attribute EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT
+    determines the reset notification behavior and the value of
+    RESET_NOTIFICATION_STRATEGY_EXT, as described in section 2.6.
+
+Errors
+
+    ReadnPixelsEXT, GetnUniformfvEXT, and GetnUniformivEXT share all the
+    errors of their unsized buffer query counterparts with the addition
+    that INVALID_OPERATION is generated if the buffer size required to
+    fill all the requested data is greater than <bufSize>.
+
+New Implementation Dependent State
+
+    Get Value                       Type  Get Command     Minimum Value    Description                  Sec.  Attribute
+    ---------                       ----  -----------     -------------    ---------------------------  ----- ---------
+    CONTEXT_ROBUST_ACCESS_EXT       B     GetIntegerv     -                Robust access enabled        6.1.5 -
+    RESET_NOTIFICATION_STRATEGY_EXT Z_2   GetIntegerv     See sec. 2.6     Reset notification behavior  2.6   -
+
+Issues
+
+
+    1.  What should this extension be called?
+
+        RESOLVED: EXT_robustness
+
+        Since this is intended to be a version of ARB_robustness for
+        OpenGL ES, it should be named accordingly.
+
+    2.  How does this extension differ from Desktop GL's ARB_robustness?
+
+        RESOLVED: Because EGL_EXT_create_context_robustness uses a
+	separate attribute to enable robust buffer access, a
+	corresponding query is added here.
+
+    3.  Should we provide a context creation mechanism to enable this extension?
+
+        RESOLVED. Yes.
+
+        Currently, EGL_EXT_create_context_robustness provides this
+        mechanism via two unique attributes. These attributes differ
+	from those specified by KHR_create_context to allow for
+	differences in what functionality those attributes define.
+        
+    4. What can cause a graphics reset?
+
+       Either user or implementor errors may result in a graphics reset.
+       If the application attempts to perform a rendering that takes too long
+       whether due to an infinite loop in a shader or even just a rendering
+       operation that takes too long on the given hardware. Implementation
+       errors may produce badly formed hardware commands. Memory access errors
+       may result from user or implementor mistakes. On some systems, power
+       management events such as system sleep, screen saver activation, or
+       pre-emption may also context resets to occur. Any of these events may
+       result in a graphics reset event that will be detectable by the
+       mechanism described in this extension.
+
+    5. How should the application react to a reset context event?
+
+       RESOLVED: For this extension, the application is expected to query
+       the reset status until NO_ERROR is returned. If a reset is encountered,
+       at least one *RESET* status will be returned. Once NO_ERROR is again
+       encountered, the application can safely destroy the old context and
+       create a new one.
+
+       After a reset event, apps should not use a context for any purpose
+       other than determining its reset status, and then destroying it. If a
+       context receives a reset event, all other contexts in its share group
+       will also receive reset events, and should be destroyed and
+       recreated.
+
+       Apps should be cautious in interpreting the GUILTY and INNOCENT reset
+       statuses. These are guidelines to the immediate cause of a reset, but
+       not guarantees of the ultimate cause.
+
+    6. If a graphics reset occurs in a shared context, what happens in
+       shared contexts?
+
+       RESOLVED: A reset in one context will result in a reset in all other
+       contexts in its share group. 
+
+    7. How can an application query for robust buffer access support,
+       since this is now determined at context creation time?
+
+       RESOLVED. The application can query the value of ROBUST_ACCESS_EXT
+       using GetIntegerv. If true, this functionality is enabled.
+
+    8. How is the reset notification behavior controlled?
+
+       RESOLVED: Reset notification behavior is determined at context
+       creation time using EGL/GLX/WGL/etc. mechanisms. In order that shared
+       objects be handled predictably, a context cannot share with
+       another context unless both have the same reset notification
+       behavior.
+
+
+Revision History
+
+    Rev.    Date       Author     Changes
+    ----  ------------ ---------  ----------------------------------------
+      3   31 Oct  2011 groth      Reverted to attribute for robust access. Now it's a
+                                  companion to rather than subset of KHR_create_context
+      2   11 Oct  2011 groth      Merged ANGLE and NV extensions.
+                                  Convert to using flag to indicate robust access.
+      1   15 July 2011 groth      Initial version
new file mode 100644
--- /dev/null
+++ b/gfx/angle/extensions/EXT_texture_storage.txt
@@ -0,0 +1,1090 @@
+Name
+
+    EXT_texture_storage
+
+Name Strings
+
+    GL_EXT_texture_storage
+
+Contact
+
+    Bruce Merry (bmerry 'at' gmail.com)
+    Ian Romanick, Intel (ian.d.romanick 'at' intel.com)
+
+Contributors
+
+    Jeremy Sandmel, Apple
+    Bruce Merry, ARM
+    Tom Olson, ARM
+    Benji Bowman, Imagination Technologies
+    Ian Romanick, Intel
+    Jeff Bolz, NVIDIA
+    Pat Brown, NVIDIA
+    Maurice Ribble, Qualcomm
+    Lingjun Chen, Qualcomm
+    Daniel Koch, Transgaming Inc
+
+Status
+
+    Complete. 
+
+Version
+
+    Last Modified Date: November 11, 2011
+    Author Revision: 24
+
+Number
+
+    XXX - not assigned yet
+
+Dependencies
+
+    OpenGL ES 1.0, OpenGL ES 2.0 or OpenGL 1.2 is required.
+
+    OES_texture_npot, OES_texture_cube_map, OES_texture_3D,
+    OES_depth_texture, OES_packed_depth_stencil,
+    OES_compressed_paletted_texture, OES_texture_float, OES_texture_half_float
+    EXT_texture_type_2_10_10_10_REV, EXT_texture_format_BGRA8888,
+    EXT_texture3D, OES_texture_npot, APPLE_texture_2D_limited_npot,
+    ARB_texture_cube_map, ARB_texture_cube_map_array,
+    ARB_texture_rectangle, SGIS_generate_mipmap,
+    EXT_direct_state_access, OES_EGL_image, WGL_ARB_render_texture,
+    GLX_EXT_texture_from_pixmap, and core specifications that
+    incorporate these extensions affect the definition of this
+    extension.
+
+    This extension is written against the OpenGL 3.2 Core Profile
+    specification.
+
+Overview
+
+    The texture image specification commands in OpenGL allow each level
+    to be separately specified with different sizes, formats, types and
+    so on, and only imposes consistency checks at draw time. This adds
+    overhead for implementations.
+
+    This extension provides a mechanism for specifying the entire
+    structure of a texture in a single call, allowing certain
+    consistency checks and memory allocations to be done up front. Once
+    specified, the format and dimensions of the image array become
+    immutable, to simplify completeness checks in the implementation.
+
+    When using this extension, it is no longer possible to supply texture
+    data using TexImage*. Instead, data can be uploaded using TexSubImage*,
+    or produced by other means (such as render-to-texture, mipmap generation,
+    or rendering to a sibling EGLImage).
+
+    This extension has complicated interactions with other extensions.
+    The goal of most of these interactions is to ensure that a texture
+    is always mipmap complete (and cube complete for cubemap textures).
+
+IP Status
+
+    No known IP claims
+
+New Procedures and Functions
+
+    void TexStorage1DEXT(enum target, sizei levels,
+                         enum internalformat,
+                         sizei width);
+
+    void TexStorage2DEXT(enum target, sizei levels,
+                         enum internalformat,
+                         sizei width, sizei height);
+
+    void TexStorage3DEXT(enum target, sizei levels,
+                         enum internalformat,
+                         sizei width, sizei height, sizei depth);
+
+    void TextureStorage1DEXT(uint texture, enum target, sizei levels,
+                         enum internalformat,
+                         sizei width);
+
+    void TextureStorage2DEXT(uint texture, enum target, sizei levels,
+                         enum internalformat,
+                         sizei width, sizei height);
+
+    void TextureStorage3DEXT(uint texture, enum target, sizei levels,
+                         enum internalformat,
+                         sizei width, sizei height, sizei depth);
+
+New Types
+
+    None
+
+New Tokens
+
+    Accepted by the <value> parameter of GetTexParameter{if}v:
+
+        TEXTURE_IMMUTABLE_FORMAT_EXT   0x912F
+
+    Accepted by the <internalformat> parameter of TexStorage* when
+    implemented on OpenGL ES:
+
+        ALPHA8_EXT                     0x803C  /* reuse tokens from EXT_texture */
+        LUMINANCE8_EXT                 0x8040
+        LUMINANCE8_ALPHA8_EXT          0x8045
+
+      (if OES_texture_float is supported)
+        RGBA32F_EXT                    0x8814  /* reuse tokens from ARB_texture_float */
+        RGB32F_EXT                     0x8815
+        ALPHA32F_EXT                   0x8816
+        LUMINANCE32F_EXT               0x8818
+        LUMINANCE_ALPHA32F_EXT         0x8819
+
+      (if OES_texture_half_float is supported)
+        RGBA16F_EXT                    0x881A  /* reuse tokens from ARB_texture_float */
+        RGB16F_EXT                     0x881B
+        ALPHA16F_EXT                   0x881C
+        LUMINANCE16F_EXT               0x881E
+        LUMINANCE_ALPHA16F_EXT         0x881F
+
+      (if EXT_texture_type_2_10_10_10_REV is supported)
+        RGB10_A2_EXT                   0x8059  /* reuse tokens from EXT_texture */
+        RGB10_EXT                      0x8052
+
+      (if EXT_texture_format_BGRA8888 is supported)
+        BGRA8_EXT                      0x93A1
+
+
+Additions to Chapter 2 of the OpenGL 3.2 Core Profile Specification
+(OpenGL Operation)
+
+    None
+
+Additions to Chapter 3 of the OpenGL 3.2 Core Profile Specification
+(Rasterization)
+
+    After section 3.8.1 (Texture Image Specification) add a new
+    subsection called "Immutable-format texture images":
+
+    "An alterative set of commands is provided for specifying the
+    properties of all levels of a texture at once. Once a texture is
+    specified with such a command, the format and dimensions of all
+    levels becomes immutable, unless it is a proxy texture (since
+    otherwise it would no longer be possible to use the proxy). The
+    contents of the images and the parameters can still be modified.
+    Such a texture is referred to as an "immutable-format" texture. The
+    immutability status of a texture can be determined by calling
+    GetTexParameter with <pname> TEXTURE_IMMUTABLE_FORMAT_EXT.
+
+    Each of the commands below is described by pseudo-code which
+    indicates the effect on the dimensions and format of the texture.
+    For all of the commands, the following apply in addition to the
+    pseudo-code:
+
+    - If the default texture object is bound to <target>, an
+      INVALID_OPERATION error is generated.
+    - If executing the pseudo-code would lead to an error, the error is
+      generated and the command will have no effect.
+    - Any existing levels that are not replaced are reset to their
+      initial state.
+    - If <width>, <height>, <depth> or <levels> is less than 1, the
+      error INVALID_VALUE is generated.
+    - Since no pixel data are provided, the <format> and <type> values
+      used in the pseudo-code are irrelevant; they can be considered to
+      be any values that are legal to use with <internalformat>.
+    - If the command is successful, TEXTURE_IMMUTABLE_FORMAT_EXT becomes
+      TRUE.
+    - If <internalformat> is a specific compressed texture format, then
+      references to TexImage* should be replaced by CompressedTexImage*,
+      with <format>, <type> and <data> replaced by any valid <imageSize> and
+      <data>. If there is no <imageSize> for which this command would have
+      been valid, an INVALID_OPERATION error is generated [fn: This
+      condition is not required for OpenGL, but is necessary for OpenGL
+      ES which does not support on-the-fly compression.]
+    - If <internalformat> is one of the internal formats listed in table
+      3.11, an INVALID_ENUM error is generated. [fn: The corresponding table
+      in OpenGL ES 2.0 is table 3.8.]
+
+    The command
+
+        void TexStorage1DEXT(enum target, sizei levels,
+                             enum internalformat,
+                             sizei width);
+
+    specifies all the levels of a one-dimensional texture (or proxy) at
+    the same time. It is described by the pseudo-code below:
+
+        for (i = 0; i < levels; i++)
+        {
+            TexImage1D(target, i, internalformat, width, 0,
+                       format, type, NULL);
+            width = max(1, floor(width / 2));
+        }
+
+    If <target> is not TEXTURE_1D or PROXY_TEXTURE_1D then INVALID_ENUM
+    is generated. If <levels> is greater than floor(log_2(width)) + 1
+    then INVALID_OPERATION is generated.
+
+    The command
+
+        void TexStorage2DEXT(enum target, sizei levels,
+                             enum internalformat,
+                             sizei width, sizei height);
+
+    specifies all the levels of a two-dimensional, cube-map,
+    one-dimension array or rectangle texture (or proxy) at the same
+    time. The pseudo-code depends on the <target>:
+
+    [PROXY_]TEXTURE_2D, [PROXY_]TEXTURE_RECTANGLE or
+    PROXY_TEXTURE_CUBE_MAP:
+
+        for (i = 0; i < levels; i++)
+        {
+            TexImage2D(target, i, internalformat, width, height, 0,
+                       format, type, NULL);
+            width = max(1, floor(width / 2));
+            height = max(1, floor(height / 2));
+        }
+
+    TEXTURE_CUBE_MAP:
+
+        for (i = 0; i < levels; i++)
+        {
+            for face in (+X, -X, +Y, -Y, +Z, -Z)
+            {
+                TexImage2D(face, i, internalformat, width, height, 0,
+                           format, type, NULL);
+            }
+            width = max(1, floor(width / 2));
+            height = max(1, floor(height / 2));
+        }
+
+    [PROXY_]TEXTURE_1D_ARRAY:
+
+        for (i = 0; i < levels; i++)
+        {
+            TexImage2D(target, i, internalformat, width, height, 0,
+                       format, type, NULL);
+            width = max(1, floor(width / 2));
+        }
+
+    If <target> is not one of those listed above, the error INVALID_ENUM
+    is generated.
+
+    The error INVALID_OPERATION is generated if any of the following
+    conditions hold:
+    - <target> is [PROXY_]TEXTURE_1D_ARRAY and <levels> is greater than
+      floor(log_2(width)) + 1
+    - <target> is not [PROXY_]TEXTURE_1D_ARRAY and <levels> is greater
+    than floor(log_2(max(width, height))) + 1
+
+    The command
+
+        void TexStorage3DEXT(enum target, sizei levels, enum internalformat,
+                             sizei width, sizei height, sizei depth);
+
+    specifies all the levels of a three-dimensional, two-dimensional
+    array texture, or cube-map array texture (or proxy). The pseudo-code
+    depends on <target>:
+
+    [PROXY_]TEXTURE_3D:
+
+        for (i = 0; i < levels; i++)
+        {
+            TexImage3D(target, i, internalformat, width, height, depth, 0,
+                       format, type, NULL);
+            width = max(1, floor(width / 2));
+            height = max(1, floor(height / 2));
+            depth = max(1, floor(depth / 2));
+        }
+
+    [PROXY_]TEXTURE_2D_ARRAY, [PROXY_]TEXTURE_CUBE_MAP_ARRAY_ARB:
+
+        for (i = 0; i < levels; i++)
+        {
+            TexImage3D(target, i, internalformat, width, height, depth, 0,
+                       format, type, NULL);
+            width = max(1, floor(width / 2));
+            height = max(1, floor(height / 2));
+        }
+
+    If <target> is not one of those listed above, the error INVALID_ENUM
+    is generated.
+
+    The error INVALID_OPERATION is generated if any of the following
+    conditions hold:
+    - <target> is [PROXY_]TEXTURE_3D and <levels> is greater than
+      floor(log_2(max(width, height, depth))) + 1
+    - <target> is [PROXY_]TEXTURE_2D_ARRAY or
+      [PROXY_]TEXTURE_CUBE_MAP_ARRAY_EXT and <levels> is greater than
+      floor(log_2(max(width, height))) + 1
+
+    After a successful call to any TexStorage* command with a non-proxy
+    target, the value of TEXTURE_IMMUTABLE_FORMAT_EXT for this texture
+    object is set to TRUE, and no further changes to the dimensions or
+    format of the texture object may be made. Other commands may only
+    alter the texel values and texture parameters. Using any of the
+    following commands with the same texture will result in the error
+    INVALID_OPERATION being generated, even if it does not affect the
+    dimensions or format:
+
+        - TexImage*
+        - CompressedTexImage*
+        - CopyTexImage*
+        - TexStorage*
+
+    The TextureStorage* commands operate identically to the
+    corresponding command where "Texture" is substituted for "Tex"
+    except, rather than updating the current bound texture for the
+    texture unit indicated by the current active texture state and the
+    target parameter, these "Texture" commands update the texture object
+    named by the initial texture parameter. The error INVALID_VALUE
+    is generated if <texture> is zero.
+    "
+
+    In section 3.8.6 (Texture Parameters), after the sentence
+
+    "In the remainder of section 3.8, denote by lod_min, lod_max,
+    level_base, and level_max the values of the texture parameters
+    TEXTURE_MIN_LOD, TEXTURE_MAX_LOD, TEXTURE_BASE_LEVEL, and
+    TEXTURE_MAX_LEVEL respectively."
+
+    add
+
+    "However, if TEXTURE_IMMUTABLE_FORMAT_EXT is
+    TRUE, then level_base is clamped to the range [0, <levels> - 1] and
+    level_max is then clamped to the range [level_base, <levels> - 1],
+    where <levels> is the parameter passed the call to TexStorage* for
+    the texture object.
+
+    In section 3.8.9 (Rendering feedback loops) replace all references
+    to TEXTURE_BASE_LEVEL by level_base.
+
+    In section 3.8.9 (Mipmapping), replace the paragraph starting "Each
+    array in a mipmap is defined..." by
+
+    "Each array in a mipmap is defined using TexImage3D, TexImage2D,
+    CopyTexImage2D, TexImage1D, CopyTexImage1D, or by functions that are
+    defined in terms of these functions. Level-of-detail numbers proceed
+    from level_base for the original texel array through the maximum
+    level p, with each unit increase indicating an array of half the
+    dimensions of the previous one (rounded down to the next integer if
+    fractional) as already described. For immutable-format textures,
+    p is one less than the <levels> parameter passed to TexStorage*;
+    otherwise p = floor(log_2(maxsize)) + level_base.  All arrays from
+    level_base through q = min(p, level_max) must be defined, as
+    discussed in section 3.8.12."
+
+    In section 3.8.12 (Texture Completeness), modify the last sentence
+    to avoid refering to level_base and level_max:
+
+    "An implementation may allow a texture image array of level 1 or
+    greater to be created only if a mipmap complete set of image arrays
+    consistent with the requested array can be supported where the
+    values of TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL are 0 and 1000
+    respectively."
+
+    Modify section 3.8.13 (Texture State and Proxy State) to add the new
+    state:
+
+    "Each set consists of ..., and a boolean flag indicating whether the
+    format and dimensions of the texture are immutable."
+
+    Add
+    "The initial value of TEXTURE_IMMUTABLE_FORMAT_EXT is FALSE."
+
+Additions to Chapter 4 of the OpenGL 3.2 Core Profile Specification
+(Per-Fragment Operations and the Frame Buffer)
+
+    None
+
+Additions to Chapter 5 of the OpenGL 3.2 Compatibility Profile Specification
+(Special Functions)
+
+    In section 5.4.1 (Commands Not Usable in Display Lists), add
+    TexStorage* to the list of commands that cannot be used.
+
+Additions to Chapter 6 of the OpenGL 3.2 Core Profile Specification
+(State and State Requests)
+
+    Replace the following statement in 6.1.3 (Enumerated Queries):
+
+    "<value> must be one of the symbolic values in table 3.10."
+
+    with
+
+    "<value> must be TEXTURE_IMMUTABLE_FORMAT_EXT or one of the symbolic
+    values in table 3.22."
+
+Additions to the AGL/EGL/GLX/WGL Specifications
+
+    None
+
+Additions to OES_compressed_ETC1_RGB8_texture
+
+    Add the following to the additions to Chapter 3:
+
+    "Since ETC1 images are easily edited along 4x4 texel boundaries, the
+    limitations on CompressedTexSubImage2D are relaxed.
+    CompressedTexSubImage2D will result in an INVALID_OPERATION error
+    only if one of the following conditions occurs:
+
+        * <width> is not a multiple of four, and <width> plus <xoffset> is not
+          equal to the texture width;
+
+        * <height> is not a multiple of four, and <height> plus <yoffset> is
+          not equal to the texture height; or
+
+        * <xoffset> or <yoffset> is not a multiple of four.
+
+    Remove CompressedTexSubImage2D from this error:
+
+    "INVALID_OPERATION is generated by CompressedTexSubImage2D,
+    TexSubImage2D, or CopyTexSubImage2D if the texture image <level>
+    bound to <target> has internal format ETC1_RGB8_OES."
+
+    Add the following error:
+
+    "INVALID_OPERATION is generated by CompressedTexSubImage2D
+    if the region to be modified is not aligned to block boundaries
+    (refer to the extension text for details)."
+
+Additions to AMD_compressed_ATC_texture and AMD_compressed_3DC_texture:
+
+    Apply the same changes as for OES_compressed_ETC1_RGB8_texture
+    above, substituting the appropriate internal format tokens from
+    these extensions.
+
+Dependencies on EXT_direct_state_access
+
+    If EXT_direct_state_access is not present, references to
+    TextureStorage* should be ignored.
+
+Dependencies on OpenGL ES
+
+    On OpenGL ES without extensions introducing TEXTURE_MAX_LEVEL,
+    mipmapped textures specified with TexStorage are required to have a
+    full set of mipmaps. If TEXTURE_MAX_LEVEL is not supported, this
+    extension is modified as follows:
+
+    - Where an upper bound is placed on <levels> in this extension (i.e.
+      the maximum number of mipmap levels for a texture of the given
+      target and dimensions), an INVALID_OPERATION error is generated if
+      <levels> is neither 1 nor this upper bound.
+    - q (the effective maximum number of levels) is redefined to clamp
+      to the number of levels present in immutable-format textures.
+
+    OpenGL ES does not accept sized internal formats (e.g., RGBA8) and
+    instead derives an internal format from the <format> and <type>
+    parameters of TexImage2D. Since TexStorage* does not specify texel
+    data, the API doesn't include <format> and <type> parameters.
+    On an OpenGL ES implementation, the values in the <internalformat>
+    column in the tables below are accepted as <internalformat>
+    parameters, and base internal formats are not accepted. The
+    TexImage* calls in the TexStorage* pseudocode are modified so that
+    the <internalformat>, <format> and <type> parameters are
+    taken from the <format>, <format> and <type> columns (respectively)
+    in the tables below, according to the <internalformat>
+    specified in the TexStorage* command.
+
+        <internalformat>       <format>           <type>
+        ----------------       --------           ------
+        RGB565                 RGB                UNSIGNED_SHORT_5_6_5
+        RGBA4                  RGBA               UNSIGNED_SHORT_4_4_4_4
+        RGB5_A1                RGBA               UNSIGNED_SHORT_5_5_5_1
+        RGB8_OES               RGB                UNSIGNED_BYTE
+        RGBA8_OES              RGBA               UNSIGNED_BYTE
+        LUMINANCE8_ALPHA8_EXT  LUMINANCE_ALPHA    UNSIGNED_BYTE
+        LUMINANCE8_EXT         LUMINANCE          UNSIGNED_BYTE
+        ALPHA8_EXT             ALPHA              UNSIGNED_BYTE
+
+    If OES_depth_texture is supported:
+
+        <internalformat>       <format>           <type>
+        ----------------       --------           ------
+        DEPTH_COMPONENT16_OES  DEPTH_COMPONENT    UNSIGNED_SHORT
+        DEPTH_COMPONENT32_OES  DEPTH_COMPONENT    UNSIGNED_INT
+
+    If OES_packed_depth_stencil is supported:
+
+        <internalformat>       <format>           <type>
+        ----------------       --------           ------
+        DEPTH24_STENCIL8_OES   DEPTH_STENCIL_OES  UNSIGNED_INT
+
+    If OES_texture_float is supported:
+
+        <internalformat>       <format>           <type>
+        ----------------       --------           ------
+        RGBA32F_EXT            RGBA               FLOAT
+        RGB32F_EXT             RGB                FLOAT
+        LUMINANCE_ALPHA32F_EXT LUMINANCE_ALPHA    FLOAT
+        LUMINANCE32F_EXT       LUMINANCE          FLOAT 
+        ALPHA32F_EXT           ALPHA              FLOAT
+
+    If OES_texture_half_float is supported:
+
+        <internalformat>       <format>           <type>
+        ----------------       --------           ------
+        RGBA16F_EXT            RGBA               HALF_FLOAT_OES
+        RGB16F_EXT             RGB                HALF_FLOAT_OES
+        LUMINANCE_ALPHA16F_EXT LUMINANCE_ALPHA    HALF_FLOAT_OES
+        LUMINANCE16F_EXT       LUMINANCE          HALF_FLOAT_OES 
+        ALPHA16F_EXT           ALPHA              HALF_FLOAT_OES
+
+    If EXT_texture_type_2_10_10_10_REV is supported:
+
+        <internalformat>    <format>   <type>
+        ----------------    --------   ------
+        RGB10_A2_EXT        RGBA       UNSIGNED_INT_2_10_10_10_REV_EXT
+        RGB10_EXT           RGB        UNSIGNED_INT_2_10_10_10_REV_EXT
+
+    If EXT_texture_format_BGRA8888 is supported:
+
+        <internalformat>    <format>   <type>
+        ----------------    --------   ------
+        BGRA8_EXT           BGRA_EXT   UNSIGNED_BYTE
+
+
+Dependencies on texture targets
+
+    If a particular texture target is not supported by the
+    implementation, passing it as a <target> to TexStorage* will
+    generate an INVALID_ENUM error. If as a result, any of the commands
+    defined in this extension would no longer have any valid <target>,
+    all references to the command should be ignored.
+
+    In particular, note that OpenGL ES 1.x/2.0 do not have proxy textures,
+    1D textures, or 3D textures, and thus only the TexStorage2DEXT
+    entry point is required. If OES_texture_3D is supported, the
+    TexStorage3DEXT entry point is also required.
+
+Dependencies on OES_texture_npot
+
+    If OpenGL ES 2.0 or APPLE_texture_2D_limited_npot is present but
+    OES_texture_npot is not present, then INVALID_OPERATION is
+    generated by TexStorage* and TexStorage3DEXT if <levels> is
+    not one and <width>, <height> or <depth> is not a power of
+    two.
+
+Dependencies on WGL_ARB_render_texture, GLX_EXT_texture_from_pixmap, EGL
+1.4 and GL_OES_EGL_image
+
+    The commands eglBindTexImage, wglBindTexImageARB, glXBindTexImageEXT or
+    EGLImageTargetTexture2DOES are not permitted on an immutable-format
+    texture.
+    They will generate the following errors:
+      - EGLImageTargetTexture2DOES: INVALID_OPERATION
+      - eglBindTexImage: EGL_BAD_MATCH
+      - wglBindTexImage: ERROR_INVALID_OPERATION
+      - glXBindTexImageEXT: BadMatch
+
+Dependencies on OES_compressed_paletted_texture
+
+    The compressed texture formats exposed by
+    OES_compressed_paletted_texture are not supported by TexStorage*.
+    Passing one of these tokens to TexStorage* will generate an
+    INVALID_ENUM error.
+
+Errors
+
+    Note that dependencies above modify the errors.
+
+    If TexStorage* is called with a <width>, <height>, <depth> or
+    <levels> parameter that is less than one, then the error
+    INVALID_VALUE is generated.
+
+    If the <target> parameter to TexStorage1DEXT is not
+    [PROXY_]TEXTURE_1D, then the error INVALID_ENUM is generated.
+
+    If the <target> parameter to TexStorage2DEXT is not
+    [PROXY_]TEXTURE_2D, [PROXY_]TEXTURE_CUBE_MAP,
+    [PROXY_]TEXTURE_RECTANGLE or [PROXY_]TEXTURE_1D_ARRAY, then the
+    error INVALID_ENUM is generated.
+
+    If the <target> parameter to TexStorage3DEXT is not
+    [PROXY_]TEXTURE_3D, [PROXY_]TEXTURE_2D_ARRAY or
+    [PROXY_]TEXTURE_CUBE_MAP_ARRAY then the error INVALID_ENUM is
+    generated.
+
+    If the <levels> parameter to TexStorage* is greater than the
+    <target>-specific value listed below then the error
+    INVALID_OPERATION is generated:
+        [PROXY_]TEXTURE_{1D,1D_ARRAY}:
+            floor(log_2(width)) + 1
+        [PROXY_]TEXTURE_{2D,2D_ARRAY,CUBE_MAP,CUBE_MAP_ARRAY}:
+            floor(log_2(max(width, height))) + 1
+        [PROXY_]TEXTURE_3D:
+            floor(log_2(max(width, height, depth))) + 1
+        [PROXY_]TEXTURE_RECTANGLE:
+            1
+
+    If the default texture object is bound to the <target> passed to
+    TexStorage*, then the error INVALID_OPERATION is generated.
+
+    If the <target> parameter to TextureStorage* does not match the
+    dimensionality of <texture>, then the error INVALID_OPERATION is
+    generated.
+
+    If the <texture> parameter to TextureStorage* is zero, then the
+    INVALID_VALUE is generated.
+
+    If any pseudo-code listed in this extension would generate an error,
+    then that error is generated.
+
+    Calling any of the following functions on a texture for which
+    TEXTURE_IMMUTABLE_FORMAT_EXT is TRUE will generate an
+    INVALID_OPERATION error:
+        - TexImage*
+        - CompressedTexImage*
+        - CopyTexImage*
+
+New State
+
+    Additions to Table 6.8 Textures (state per texture object)
+
+                                                               Initial
+        Get Value                      Type   Get Command      Value    Description                Sec.
+        ---------                      ----   -----------      -------  -----------                ----
+        TEXTURE_IMMUTABLE_FORMAT_EXT   B      GetTexParameter  FALSE    Size and format immutable  2.6
+
+New Implementation Dependent State
+
+    None
+
+Issues
+
+    1. What should this extension be called?
+
+    RESOLVED: EXT_texture_storage is chosen for consistency with the
+    glRenderbufferStorage entry point.
+
+    2. Should TexStorage* accept a border parameter?
+
+    RESOLVED: no.
+
+    DISCUSSION: Currently it does not, since borders are a deprecated
+    feature which is not supported by all hardware. Users of the
+    compatibility profile can continue to use the existing texture
+    specification functions, but there is an argument that users of
+    compatibility profile may also want to use this extension.
+
+    3. What is the correct error when <levels> specifies a partial
+    mipmap pyramid for OpenGL ES?
+
+    RESOLVED: INVALID_OPERATION, since it is an interaction between
+    parameters rather than a single value being invalid. It also makes
+    sense to relax this condition for desktop GL where it makes sense to
+    use a truncated pyramid with TEXTURE_MAX_LEVEL.
+
+    4. Should use of these entry-points make the metadata (format and
+    dimensions) immutable?
+
+    RESOLVED: Yes.
+
+    DISCUSSION: The benefits of knowing metadata can't change will
+    probably outweigh the extra cost of checking the
+    TEXTURE_IMMUTABLE_FORMAT_EXT flag on each texture specification
+    call.
+
+    5. Should it be legal to completely replace the texture using a new call
+    to TexStorage*?
+
+    RESOLVED. It will not be allowed.
+
+    DISCUSSION: This is useful to invalidate all levels of a texture.
+    Allowing the metadata to be changed here seems easier than trying to
+    define a portable definition of what it means to change the metadata
+    (e.g. what if you used an unsized internal format the first time and
+    the corresponding sized internal format the second time, or vice
+    versa)?
+
+    However, while this is largely similar to deleting the old texture
+    object and replacing it with a new one, it does lose some of the
+    advantages of immutability. Specifically, because doing so does not
+    reset bindings, it doesn't allow a migration path to an API that
+    validates the texture format at bind time.
+
+    6. Should it be legal to use TexImage* after TexStorage* if it doesn't
+    affect the metadata?
+
+    RESOLVED: No.
+
+    DISCUSSION: A potential use case is to allow a single level of a
+    texture to be invalidated using a NULL pointer. However, as noted
+    above it is non-trivial to determine what constitutes a change.
+
+    7. How does this extension interact with APPLE_texture_2D_limited_npot?
+
+    RESOLVED. APPLE_texture_2D_limited_npot is equivalent to the NPOT
+    support in OpenGL ES 2.0.
+
+    8. Should this extension be written to work with desktop OpenGL?
+
+    RESOLVED: Yes.
+
+    DISCUSSION: There has been been interest and it will future-proof it
+    against further additions to OpenGL ES.
+
+    9. Which texture targets should be supported?
+
+    RESOLVED. All targets except multisample and buffer textures are
+    supported.
+
+    Initially all targets except TEXTURE_BUFFER were supported. It was
+    noted that the entrypoints for multisample targets added no useful
+    functionality, since multisample textures have no completeness
+    checks beyond being non-empty.
+
+    Rectangle textures have completeness checks to prevent filtering of
+    integer textures. However, since we decided to only force mipmap
+    completeness, this becomes less useful.
+
+    10. Should this extension support proxy textures?
+
+    RESOLVED: Yes.
+
+    DISCUSSION: It should be orthogonal.
+
+    11. Are the <format> and <type> parameters necessary?
+
+    RESOLVED. No, they will be removed.
+
+    DISCUSSION: For OpenGL ES the type parameter was necessary to
+    determine the precision of the texture, but this can be solved by
+    having these functions accept sized internal formats (which are
+    already accepted by renderbuffers).
+
+    12. Should it be legal to make the default texture (id 0)
+    immutable-format?
+
+    RESOLVED: No.
+
+    DISCUSSION: This would make it impossible to restore the context to
+    it's default state, which is deemed undesirable. There is no good
+    reason not to use named texture objects.
+
+    13. Should we try to guarantee that textures made through this path
+    will always be complete?
+
+    RESOLVED: It should be guaranteed that the texture will be mipmap
+    complete.
+
+    DISCUSSION: Future separation between images and samplers will still
+    allow users to create combinations that are invalid, but
+    constraining the simple cases will make these APIs easier to use for
+    beginners.
+
+    14. Should these functions use a EXT_direct_state_access approach to
+    specifying the texture objects?
+
+    UNRESOLVED.
+
+    DISCUSSION: as a standalone extension, no DSA-like functions will be
+    added. However, interactions with EXT_direct_state_access and
+    ARB_direct_state_access need to be resolved.
+
+    15. Should these functions accept generic compressed formats?
+
+    RESOLVED: Yes. Note that the spec language will need to be modified
+    to allow this for ES, since the pseudocode is written in terms of
+    TexImage2D, which does not allow compressed texture formats in ES.
+    See also issues 23 and 27.
+
+    16. How should completeness be forced when TEXTURE_MAX_LEVEL is not
+    present?
+
+    RESOLVED. The maximum level q will be redefined to clamp to the
+    highest level available.
+
+    DISCUSSION: A single-level texture can be made complete either by
+    making it mipmap complete (by setting TEXTURE_MAX_LEVEL to 0) or by
+    turning off mipmapping (by choose an appropriate minification
+    filter).
+
+    Some options:
+
+    A: Specify that TexStorage* changes the default minification filter
+    for OpenGL ES. This makes it awkward to add TEXTURE_MAX_LEVEL
+    support to OpenGL ES later, since switching to match GL would break
+    compatibility. The two mechanisms also do not give identical
+    results, since the magnification threshold depends on the
+    minification filter.
+
+    B: Specify that the texture behaves as though TEXTURE_MAX_LEVEL were
+    zero. To specify this properly probably requires fairly intrusive
+    changes to the OpenGL ES full specification to add back all the
+    language relating to the max level. It also does not solve the
+    similar problem of what to do with NPOT textures; and it may have
+    hardware impacts due to the change in the min/mag crossover.
+
+    C: Specify that TexStorage* changes the default minification filter
+    for all implementations when a single-level texture is specified.
+    This may be slightly counter-intuitive to desktop GL users, but will
+    give consistent behaviour across variants of GL and avoids changing
+    the functional behaviour of this extension based on the presence or
+    absence of some other feature.
+
+    Currently B is specified. This has potential hardware implications
+    for OpenGL ES because of the effect of the minification filter on
+    the min/mag crossover. However, C has potential hardware implications
+    for OpenGL due to the separation of texture and sampler state.
+
+    17. How should completeness be forced when only ES2-style NPOT is
+    available?
+
+    RESOLVED. It is not worth trying to do this, in light of issue 13.
+
+    Previous revisions of this extension overrode the minification
+    filter and wrap modes, but that is no longer the case. Since
+    OES_texture_npot removes the caveats on NPOT textures anyway, it
+    might not be worth trying to "fix" this.
+
+    18. For OpenGL ES, how do the new sized internal formats interact
+    with OES_required_internal_format?
+
+    RESOLVED.
+
+    If OES_required_internal_format is not present, then the
+    <internalformat> parameter is intended merely to indicate what the
+    corresponding <format> and <type> would have been, had TexImage*
+    been used instead. If OES_required_internal_format is present, then
+    it is intended that the <internalformat> will be interpreted as if
+    it had been passed directly to TexImage*.
+
+    19. Should there be some hinting mechanism to indicate whether data
+    is coming immediately or later?
+
+    RESOLVED. No parameter is needed. An extension can be added to provide
+    a TexParameter value which is latched at TexStorage time.
+
+    DISCUSSION: Some members felt that this would be useful so that they
+    could defer allocation when suitable, particularly if higher-
+    resolution images will be streamed in later; or to choose a memory
+    type or layout appropriate to the usage. However, implementation
+    experience with BufferData is that developers frequently provide
+    wrong values and implementations have to guess anyway.
+
+    One option suggested was the <usage> parameter currently passed to
+    BufferData. Another option was to set it with TexParameter.
+
+    20. How should this extension interact with
+    EGLImageTargetTexture2DOES, eglBindTexImage, glXBindTexImage and
+    wglBindTexImage?
+
+    RESOLVED. These functions will not be permitted after glTexStorage*.
+
+    Several options are possible:
+
+    A) Disallow these functions.
+    B) Allow them, but have them reset the TEXTURE_IMMUTABLE_FORMAT_EXT
+       flag.
+    C) Allow them unconditionally.
+
+    C would violate the design principle that the dimensions and format
+    of the mipmap array are immutable. B does not so much modify the
+    dimension and formats as replace them with an entirely different
+    set.
+
+    21. Should there be a single function for specifying 1D, 2D and 3D
+    targets?
+
+    RESOLVED. No, we will stick with existing precedent.
+
+    22. Is it possible to use GenerateMipmap with an incomplete mipmap
+    pyramid?
+
+    RESOLVED. Yes, because the effective max level is limited to the
+    levels that were specified, and so GenerateMipmap does not generate
+    any new levels.
+
+    However, to make automatic mipmap generation work, it is necessary
+    to redefine p rather than q, since automatic mipmap generation
+    ignores the max level.
+
+    23. How should this extension interact with
+    OES_compressed_paletted_texture?
+
+    RESOLVED. Paletted textures will not be permitted, and will
+    generate INVALID_ENUM.
+
+    DISCUSSION: OES_compressed_paletted_texture supplies all the mipmaps
+    in a single function call, with the palette specified once. That's
+    incompatible with the upload model in this extension.
+
+    24. How can ETC1 textures be used with this extension?
+
+    RESOLVED. Add language in this extension to allow subregion uploads
+    for ETC1.
+
+    DISCUSSION: GL_OES_compressed_ETC1_RGB8_texture doesn't allow
+    CompressedTexSubImage*, so it would be impossible to use this
+    extension with ETC1. This is seen as an oversight in the ETC1
+    extension. While it cannot be fixed in that extension (since it is
+    already shipping), this extension can add that capability.
+
+    25. Should any other compressed formats be similarly modified?
+
+    RESOLVED. Yes, AMD_compressed_ATC_texture and
+    AMD_compressed_3DC_texture can be modified similarly to ETC1
+    (Maurice Ribble indicated that both formats use 4x4 blocks). Desktop
+    OpenGL requires that whole-image replacement is supported for any
+    compressed texture format, and the OpenGL ES extensions
+    EXT_texture_compression_dxt1 and IMG_texture_compression_pvrtc
+    already allow whole-image replacement, so it is not necessary to
+    modify them to be used with this extension.
+
+    26. Should these commands be permitted in display lists?
+
+    RESOLVED. No.
+
+    DISCUSSION: Display lists are most useful for repeating commands,
+    and TexStorage* commands cannot be repeated because the first call
+    makes the format immutable.
+
+    27. Should these commands accept unsized internal formats?
+
+    RESOLVED: No, for both OpenGL and OpenGL ES.
+
+    DISCUSSION: normally the <type> parameter to TexImage* can serve as
+    a hint to select a sized format (and in OpenGL ES, this is the only
+    mechanism available); since TexStorage* does not have a <type>
+    parameter, the implementation has no information on which to base a
+    decision.
+
+Revision History
+
+    Revision 24, 2011/11/11 (dgkoch)
+      - Mark complete. Clarify ES clarifications.
+
+    Revision 23, 2011/11/10 (dgkoch)
+      - Add GLES clarifcations and interactions with more GLES extensions
+
+    Revision 22, 2011/11/10 (bmerry)
+      - Update my contact details
+
+    Revision 21, 2011/07/25 (bmerry)
+      - Remove dangling references to MultiTexStorage in Errors section
+
+    Revision 20, 2011/07/21 (bmerry)
+      - Remove dangling reference to <samples> in Errors section
+
+    Revision 19, 2011/05/02 (Jon Leech)
+      - Assign enum value
+
+    Revision 18, 2011/01/24 (bmerry)
+      - Disallow unsized internal formats (oversight in revision 17).
+
+    Revision 17, 2011/01/24 (bmerry)
+      - Added and resolved issue 26.
+      - Split issue 27 out from issue 15.
+      - Disallow TexStorage* in display lists.
+      - Use the term "immutable-format" consistently (bug 7281).
+
+    Revision 16, 2010/11/23 (bmerry)
+      - Disallowed TexStorage on an immutable-format texture
+        (resolves issue 5).
+      - Deleted MultiTexStorage* commands (other DSA functions still
+        unresolved).
+      - Some minor wording changes suggested by Pat Brown (bug 7002).
+
+    Revision 15, 2010/11/09 (bmerry)
+      - Reopened issue 5.
+      - Reopened issue 14, pending stabilisation of
+        ARB_direct_state_access.
+      - Marked issue 9 resolved, pending any objections.
+      - Fix references to no object being bound (was meant to refer to
+        the default object).
+      - Adding missing pseudocode for TEXTURE_1D_ARRAY.
+      - Corrected TEXTURE_2D_ARRAY -> TEXTURE_1D_ARRAY in error checks.
+      - Changed "levels... are removed" to "levels... are reset to their
+        init state", since desktop GL has per-level state apart from the
+        texels.
+      - Miscellaneous wording fixes.
+
+    Revision 14, 2010/09/25 (bmerry)
+      - Add issues 24-25 and alterations to
+        OES_compressed_ETC1_RGB8_texture, AMD_compressed_ATC_texture and
+        AMD_compressed_3DC_texture.
+
+    Revision 13, 2010/09/19 (bmerry)
+      - Two typo fixes from Daniel Koch
+
+    Revision 12, 2010/09/18 (bmerry)
+      - Changed resolution to issue 20
+      - Added and resolved issue 23
+      - Added explanation of how to upload data (in overview)
+      - Added spec language to implement resolution to issue 15
+
+    Revision 11, 2010/07/21 (bmerry)
+      - Resolved issue 16
+      - Reopen issue 20
+      - Fix some typos
+
+    Revision 10, 2010/07/15 (bmerry)
+      - Update some issues to match core text
+      - Resolved issue 17
+
+    Revision 9, 2010/05/24 (bmerry)
+      - Marked issue 2 as resolved
+      - Resolved issue 19 (as no change)
+      - Resolved issue 20
+      - Add issues 21-22
+      - Add in spec language to forbid use on default textures
+      - Redefine level_base, level_max to be clamped forms of
+        TEXTURE_BASE_LEVEL/TEXTURE_MAX_LEVEL when using immutable
+        textures
+      - Redefine p to also be clamped to the provided levels for
+        immutable textures, to support automatic mipmap generation
+      - Removed multisample functions
+      - Removed language stating that texture parameters were reset to
+        defaults
+
+    Revision 8, 2010/05/18 (bmerry)
+      - Added issue about EGLimage
+      - Marked issue 14 as resolved
+
+    Revision 7, 2010/05/04 (bmerry)
+      - Removed some lingering <format>, <type> parameters to the new
+        functions that should have been removed in revision 4
+      - Trivial typo fixes
+
+    Revision 6, 2010/02/18 (bmerry)
+      - Resolved issues 5, 6 and 18
+      - Added MultiTexStorage* functions for DSA interaction
+      - Added error for texture-target mismatch in DSA
+      - Allowed TexStorage* to be called again
+
+    Revision 5, 2010/01/25 (bmerry)
+      - Added to contributors list
+      - Require OpenGL 1.2, to simplify interactions with
+        TEXTURE_BASE_LEVEL/TEXTURE_MAX_LEVEL and CLAMP_TO_EDGE
+      - Change default wrap modes to always be CLAMP_TO_EDGE
+      - Change default filters to always be NEAREST
+      - Moved language about generating new levels into an interaction,
+        since it can only happen on OpenGL ES
+      - Added interaction with EXT_direct_state_access
+      - Added extra <internalformats> for GL ES when OES_depth_texture,
+        OES_packed_depth_stencil and EXT_texture_type_2_10_10_10_REV are
+        present.
+      - Minor non-functional wording fixes and typos
+      - Resolved issue 16
+      - Added issues 17-19
+
+    Revision 4, 2010/01/13 (bmerry)
+      - Changed suffix from ARM to EXT
+      - Added list of contributors
+      - Added language to force the texture to always be complete
+      - Removed <format> and <type> arguments
+      - Added issues 14-16
+      - Reopened issue 2
+      - Reformatted issues to separate resolution and discussion
+      - Resolved issues 1, 9 and 11-13
+      - Fixed the max number of levels in a cube map array
+
+    Revision 3, 2009/12/17 (bmerry)
+      - Added missing vendor suffix to TEXTURE_IMMUTABLE_FORMAT_ARM
+      - Rewritten to against desktop OpenGL
+      - Added prototypes for 1D and multisample storage functions
+      - Added issues 8-13
+
+    Revision 2, 2009/08/20 (bmerry)
+      - Resolved issue 2 (no border parameter)
+      - Resolved issue 4 (metadata becomes immutable)
+      - Added interaction with OES_texture_cube_map
+      - Added error if width != height in a cube map
+      - Added issues 5-7
+
+    Revision 1, 2009/05/06 (bmerry)
+      - First draft
--- a/gfx/angle/include/EGL/eglext.h
+++ b/gfx/angle/include/EGL/eglext.h
@@ -313,16 +313,24 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQ
 
 #ifndef EGL_NV_coverage_sample_resolve
 #define EGL_NV_coverage_sample_resolve 1
 #define EGL_COVERAGE_SAMPLE_RESOLVE_NV		0x3131
 #define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV	0x3132
 #define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV	0x3133
 #endif
 
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT                0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT  0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT                       0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT                       0x31BF
+#endif
+
 #if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
 #ifndef EGL_NV_system_time
 #define EGL_NV_system_time 1
 
 typedef khronos_utime_nanoseconds_t EGLuint64NV;
 
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
--- a/gfx/angle/include/GLES2/gl2ext.h
+++ b/gfx/angle/include/GLES2/gl2ext.h
@@ -217,16 +217,22 @@ typedef void* GLeglImageOES;
 #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
 
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_TEXTURE_USAGE_ANGLE                                  0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE                         0x93A3
+#endif
+
 /*------------------------------------------------------------------------*
  * APPLE extension tokens
  *------------------------------------------------------------------------*/
 
 /* GL_APPLE_rgb_422 */
 #ifndef GL_APPLE_rgb_422
 #define GL_RGB_422_APPLE                                        0x8A1F
 #define GL_UNSIGNED_SHORT_8_8_APPLE                             0x85BA
@@ -320,16 +326,52 @@ typedef void* GLeglImageOES;
 
 /* GL_EXT_unpack_subimage */
 #ifndef GL_EXT_unpack_subimage
 #define GL_UNPACK_ROW_LENGTH                                    0x0CF2
 #define GL_UNPACK_SKIP_ROWS                                     0x0CF3
 #define GL_UNPACK_SKIP_PIXELS                                   0x0CF4
 #endif
 
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+#define GL_GUILTY_CONTEXT_RESET_EXT                             0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT                           0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT                            0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT                            0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT                      0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT                            0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT                            0x8261
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT                         0x912F
+#define GL_ALPHA8_EXT                                           0x803C
+#define GL_LUMINANCE8_EXT                                       0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT                                0x8045
+/* OES_texture_float dependent internal formats */
+#define GL_RGBA32F_EXT                                          0x8814  /* reuse tokens from ARB_texture_float */
+#define GL_RGB32F_EXT                                           0x8815
+#define GL_ALPHA32F_EXT                                         0x8816
+#define GL_LUMINANCE32F_EXT                                     0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT                               0x8819
+/* OES_texture_half_float dependent internal formats */
+#define GL_RGBA16F_EXT                                          0x881A /* reuse tokens from ARB_texture_float */
+#define GL_RGB16F_EXT                                           0x881B
+#define GL_ALPHA16F_EXT                                         0x881C
+#define GL_LUMINANCE16F_EXT                                     0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT                               0x881F
+/* EXT_texture_type_2_10_10_10_REV dependent internal formats */
+#define GL_RGB10_A2_EXT                                         0x8059  /* reuse tokens from EXT_texture */
+#define GL_RGB10_EXT                                            0x8052
+/* EXT_texture_format_BGRA8888 dependent internal formats */
+#define GL_BGRA8_EXT                                            0x93A1
+#endif
+
 /*------------------------------------------------------------------------*
  * DMP extension tokens
  *------------------------------------------------------------------------*/
 
 /* GL_DMP_shader_binary */
 #ifndef GL_DMP_shader_binary
 #define GL_SHADER_BINARY_DMP                                    0x9250
 #endif
@@ -819,16 +861,21 @@ typedef void (GL_APIENTRYP PFNGLRENDERBU
 #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
 
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+#endif
+
 /*------------------------------------------------------------------------*
  * APPLE extension functions
  *------------------------------------------------------------------------*/
 
 /* GL_APPLE_rgb_422 */
 #ifndef GL_APPLE_rgb_422
 #define GL_APPLE_rgb_422 1
 #endif
@@ -926,16 +973,40 @@ typedef void (GL_APIENTRYP PFNGLMULTIDRA
 #define GL_EXT_texture_compression_dxt1 1
 #endif
 
 /* GL_EXT_unpack_subimage */
 #ifndef GL_EXT_unpack_subimage
 #define GL_EXT_unpack_subimage 1
 #endif
 
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+#define GL_EXT_robustness 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
+GL_APICALL void   GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+GL_APICALL void   GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void   GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void   (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+typedef void   (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void   (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_EXT_texture_storage 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY TexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXT) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
 /*------------------------------------------------------------------------*
  * DMP extension functions
  *------------------------------------------------------------------------*/
 
 /* GL_DMP_shader_binary */
 #ifndef GL_DMP_shader_binary
 #define GL_DMP_shader_binary 1
 #endif
--- 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 809
+#define BUILD_REVISION 885
 
 #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/Initialize.cpp
+++ b/gfx/angle/src/compiler/Initialize.cpp
@@ -619,17 +619,17 @@ void IdentifyBuiltIns(ShShaderType type,
         break;
     default: break;
     }
 
     // Finally add resource-specific variables.
     switch(type) {
     case SH_FRAGMENT_SHADER: {
             // Set up gl_FragData.  The array size.
-            TType fragData(EbtFloat, EbpMedium, EvqFragColor,   4, false, true);
+            TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true);
             fragData.setArraySize(resources.MaxDrawBuffers);
             symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"),    fragData));
         }
         break;
     default: break;
     }
 }
 
--- a/gfx/angle/src/libEGL/Display.cpp
+++ b/gfx/angle/src/libEGL/Display.cpp
@@ -83,16 +83,17 @@ Display::Display(EGLNativeDisplayType di
     #else
         mDeviceType = D3DDEVTYPE_HAL;
     #endif
 
     mMinSwapInterval = 1;
     mMaxSwapInterval = 1;
     mSoftwareDevice = software;
     mDisplayId = displayId;
+    mDeviceLost = false;
 }
 
 Display::~Display()
 {
     terminate();
 
     DisplayMap::iterator thisDisplay = displays.find(mDisplayId);
 
@@ -299,17 +300,17 @@ void Display::terminate()
     while (!mContextSet.empty())
     {
         destroyContext(*mContextSet.begin());
     }
 
     if (mDevice)
     {
         // If the device is lost, reset it first to prevent leaving the driver in an unstable state
-        if (isDeviceLost())
+        if (testDeviceLost())
         {
             resetDevice();
         }
 
         mDevice->Release();
         mDevice = NULL;
     }
 
@@ -452,33 +453,54 @@ bool Display::createDevice()
     mSceneStarted = false;
 
     return true;
 }
 
 bool Display::resetDevice()
 {
     D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
-    HRESULT result;
-    
-    do
+
+    HRESULT result = D3D_OK;
+    bool lost = testDeviceLost();
+    int attempts = 3;    
+
+    while (lost && attempts > 0)
     {
-        Sleep(0);   // Give the graphics driver some CPU time
+        if (mDeviceEx)
+        {
+            Sleep(500);   // Give the graphics driver some CPU time
+            result = mDeviceEx->ResetEx(&presentParameters, NULL);
+        }
+        else
+        {
+            result = mDevice->TestCooperativeLevel();
+            
+            while (result == D3DERR_DEVICELOST)
+            {
+                Sleep(100);   // Give the graphics driver some CPU time
+                result = mDevice->TestCooperativeLevel();
+            }
 
-        result = mDevice->Reset(&presentParameters);
+            if (result == D3DERR_DEVICENOTRESET)
+            {
+                result = mDevice->Reset(&presentParameters);
+            }
+        }
+
+        lost = testDeviceLost();
+        attempts --;
     }
-    while (result == D3DERR_DEVICELOST);
 
     if (FAILED(result))
     {
+        ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
         return error(EGL_BAD_ALLOC, false);
     }
 
-    ASSERT(SUCCEEDED(result));
-
     return true;
 }
 
 EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
 {
     const Config *configuration = mConfigSet.get(config);
 
     if (attribList)
@@ -510,17 +532,18 @@ EGLSurface Display::createWindowSurface(
         }
     }
 
     if (hasExistingWindowSurface(window))
     {
         return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
     }
 
-    if (isDeviceLost()) {
+    if (testDeviceLost()) 
+    {
         if (!restoreLostDevice())
             return EGL_NO_SURFACE;
     }
 
     Surface *surface = new Surface(this, configuration, window);
 
     if (!surface->initialize())
     {
@@ -622,17 +645,18 @@ EGLSurface Display::createOffscreenSurfa
     }
 
     if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
         (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
     {
         return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
     }
 
-    if (isDeviceLost()) {
+    if (testDeviceLost()) 
+    {
         if (!restoreLostDevice())
             return EGL_NO_SURFACE;
     }
 
     Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
 
     if (!surface->initialize())
     {
@@ -640,41 +664,48 @@ EGLSurface Display::createOffscreenSurfa
         return EGL_NO_SURFACE;
     }
 
     mSurfaceSet.insert(surface);
 
     return success(surface);
 }
 
-EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
+EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
 {
     if (!mDevice)
     {
         if (!createDevice())
         {
             return NULL;
         }
     }
-    else if (isDeviceLost())   // Lost device
+    else if (testDeviceLost())   // Lost device
     {
         if (!restoreLostDevice())
             return NULL;
     }
 
     const egl::Config *config = mConfigSet.get(configHandle);
 
-    gl::Context *context = glCreateContext(config, shareContext);
+    gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess);
     mContextSet.insert(context);
+    mDeviceLost = false;
 
     return context;
 }
 
 bool Display::restoreLostDevice()
 {
+    for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
+    {
+        if ((*ctx)->isResetNotificationEnabled())
+            return false;   // If reset notifications have been requested, application must delete all contexts first
+    }
+ 
     // Release surface resources to make the Reset() succeed
     for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
     {
         (*surface)->release();
     }
 
     if (!resetDevice())
     {
@@ -698,16 +729,31 @@ void Display::destroySurface(egl::Surfac
 }
 
 void Display::destroyContext(gl::Context *context)
 {
     glDestroyContext(context);
     mContextSet.erase(context);
 }
 
+void Display::notifyDeviceLost()
+{
+    for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
+    {
+        (*context)->markContextLost();
+    }
+    mDeviceLost = true;
+    error(EGL_CONTEXT_LOST);
+}
+
+bool Display::isDeviceLost()
+{
+    return mDeviceLost;
+}
+
 bool Display::isInitialized() const
 {
     return mD3d9 != NULL && mConfigSet.size() > 0;
 }
 
 bool Display::isValidConfig(EGLConfig config)
 {
     return mConfigSet.get(config) != NULL;
@@ -764,30 +810,53 @@ D3DCAPS9 Display::getDeviceCaps()
     return mDeviceCaps;
 }
 
 D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier()
 {
     return &mAdapterIdentifier;
 }
 
-bool Display::isDeviceLost()
+bool Display::testDeviceLost()
 {
     if (mDeviceEx)
     {
         return FAILED(mDeviceEx->CheckDeviceState(NULL));
     }
-    else if(mDevice)
+    else if (mDevice)
     {
         return FAILED(mDevice->TestCooperativeLevel());
     }
 
     return false;   // No device yet, so no reset required
 }
 
+bool Display::testDeviceResettable()
+{
+    HRESULT status = D3D_OK;
+
+    if (mDeviceEx)
+    {
+        status = mDeviceEx->CheckDeviceState(NULL);
+    }
+    else if (mDevice)
+    {
+        status = mDevice->TestCooperativeLevel();
+    }
+
+    switch (status)
+    {
+      case D3DERR_DEVICENOTRESET:
+      case D3DERR_DEVICEHUNG:
+        return true;
+      default:
+        return false;
+    }
+}
+
 void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
 {
     for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
     {
         HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
                                                            TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
 
         multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
@@ -813,17 +882,17 @@ bool Display::getDXT3TextureSupport()
 bool Display::getDXT5TextureSupport()
 {
     D3DDISPLAYMODE currentDisplayMode;
     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
 
     return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
 }
 
-bool Display::getFloatTextureSupport(bool *filtering, bool *renderable)
+bool Display::getFloat32TextureSupport(bool *filtering, bool *renderable)
 {
     D3DDISPLAYMODE currentDisplayMode;
     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
 
     *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, 
                                                     D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
                  SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
                                                     D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
@@ -841,17 +910,17 @@ bool Display::getFloatTextureSupport(boo
                                                   D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
     }
     else
     {
         return true;
     }
 }
 
-bool Display::getHalfFloatTextureSupport(bool *filtering, bool *renderable)
+bool Display::getFloat16TextureSupport(bool *filtering, bool *renderable)
 {
     D3DDISPLAYMODE currentDisplayMode;
     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
 
     *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, 
                                                     D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
                  SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
                                                     D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
@@ -902,16 +971,33 @@ D3DPOOL Display::getBufferPool(DWORD usa
         {
             return D3DPOOL_MANAGED;
         }
     }
 
     return D3DPOOL_DEFAULT;
 }
 
+D3DPOOL Display::getTexturePool(bool renderable) const
+{
+    if (mD3d9Ex != NULL)
+    {
+        return D3DPOOL_DEFAULT;
+    }
+    else
+    {
+        if (!renderable)
+        {
+            return D3DPOOL_MANAGED;
+        }
+    }
+
+    return D3DPOOL_DEFAULT;
+}
+
 bool Display::getEventQuerySupport()
 {
     IDirect3DQuery9 *query;
     HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
     if (SUCCEEDED(result))
     {
         query->Release();
     }
@@ -943,16 +1029,20 @@ D3DPRESENT_PARAMETERS Display::getDefaul
 
 void Display::initExtensionString()
 {
     HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
     bool isd3d9ex = isD3d9ExDevice();
 
     mExtensionString = "";
 
+    // Multi-vendor (EXT) extensions
+    mExtensionString += "EGL_EXT_create_context_robustness ";
+
+    // ANGLE-specific extensions
     if (isd3d9ex) {
         mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
     }
 
     mExtensionString += "EGL_ANGLE_query_surface_pointer ";
 
     if (swiftShader)
     {
--- a/gfx/angle/src/libEGL/Display.h
+++ b/gfx/angle/src/libEGL/Display.h
@@ -39,46 +39,51 @@ class Display
 
     static egl::Display *getDisplay(EGLNativeDisplayType displayId);
 
     bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
     bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
 
     EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList);
     EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
-    EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);
+    EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
 
     void destroySurface(egl::Surface *surface);
     void destroyContext(gl::Context *context);
 
     bool isInitialized() const;
     bool isValidConfig(EGLConfig config);
     bool isValidContext(gl::Context *context);
     bool isValidSurface(egl::Surface *surface);
     bool hasExistingWindowSurface(HWND window);
 
     EGLint getMinSwapInterval();
     EGLint getMaxSwapInterval();
 
     virtual IDirect3DDevice9 *getDevice();
     virtual D3DCAPS9 getDeviceCaps();
     virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier();
-    bool isDeviceLost();
+    virtual bool testDeviceLost();
+    virtual bool testDeviceResettable();
     virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
     virtual bool getDXT1TextureSupport();
     virtual bool getDXT3TextureSupport();
     virtual bool getDXT5TextureSupport();
     virtual bool getEventQuerySupport();
-    virtual bool getFloatTextureSupport(bool *filtering, bool *renderable);
-    virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable);
+    virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
+    virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
     virtual bool getLuminanceTextureSupport();
     virtual bool getLuminanceAlphaTextureSupport();
     virtual bool getVertexTextureSupport() const;
     virtual bool getNonPower2TextureSupport() const;
     virtual D3DPOOL getBufferPool(DWORD usage) const;
+    virtual D3DPOOL getTexturePool(bool renderable) const;
+
+    virtual void notifyDeviceLost();
+    bool isDeviceLost();
 
     bool isD3d9ExDevice() { return mD3d9Ex != NULL; }
     const char *getExtensionString() const;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Display);
 
     Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software);
@@ -109,16 +114,17 @@ class Display
     
     typedef std::set<Surface*> SurfaceSet;
     SurfaceSet mSurfaceSet;
 
     ConfigSet mConfigSet;
 
     typedef std::set<gl::Context*> ContextSet;
     ContextSet mContextSet;
+    bool mDeviceLost;
 
     bool createDevice();
     bool resetDevice();
 
     void initExtensionString();
     std::string mExtensionString;
 };
 }
--- a/gfx/angle/src/libEGL/Surface.cpp
+++ b/gfx/angle/src/libEGL/Surface.cpp
@@ -101,17 +101,17 @@ bool Surface::initialize()
       if (SUCCEEDED(result) && isComposited) {
         DWM_PRESENT_PARAMETERS presentParams;
         memset(&presentParams, 0, sizeof(presentParams));
         presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
         presentParams.cBuffer = 2;
 
         result = DwmSetPresentParameters(mWindow, &presentParams);
         if (FAILED(result))
-          ERR("Unable to set present parameters: %081X", result);
+          ERR("Unable to set present parameters: 0x%08X", result);
       }
     }
 
     return true;
 }
 
 void Surface::release()
 {
@@ -245,35 +245,44 @@ bool Surface::resetSwapChain(int backbuf
         }
 
         result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
                                        presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
     }
 
     if (FAILED(result))
     {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
 
         ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
         release();
-        return error(EGL_BAD_ALLOC, false);
+
+        if(isDeviceLostError(result))
+        {
+            mDisplay->notifyDeviceLost();
+            return false;
+        }
+        else
+        {
+            return error(EGL_BAD_ALLOC, false);
+        }
     }
 
     if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
     {
         result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
                                                    presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
                                                    presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL);
     }
 
     if (FAILED(result))
     {
         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
 
-        ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
+        ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
         release();
         return error(EGL_BAD_ALLOC, false);
     }
 
     if (mWindow) {
         mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget);
         InvalidateRect(mWindow, NULL, FALSE);
     } else {
@@ -408,24 +417,25 @@ DWORD Surface::convertInterval(EGLint in
 bool Surface::swap()
 {
     if (mSwapChain)
     {
         mDisplay->endScene();
 
         HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0);
 
-        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
         {
             return error(EGL_BAD_ALLOC, false);
         }
 
-        if (result == D3DERR_DEVICELOST || result == D3DERR_DEVICEHUNG || result == D3DERR_DEVICEREMOVED)
+        if (isDeviceLostError(result))
         {
-            return error(EGL_CONTEXT_LOST, false);
+            mDisplay->notifyDeviceLost();
+            return false;
         }
 
         ASSERT(SUCCEEDED(result));
 
         checkForOutOfDateSwapChain();
     }
 
     return true;
--- a/gfx/angle/src/libEGL/libEGL.cpp
+++ b/gfx/angle/src/libEGL/libEGL.cpp
@@ -710,17 +710,20 @@ EGLBoolean __stdcall eglBindTexImage(EGL
             return error(EGL_BAD_ACCESS, EGL_FALSE);
         }
 
         if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
         {
             return error(EGL_BAD_MATCH, EGL_FALSE);
         }
 
-        glBindTexImage(eglSurface);
+        if (!glBindTexImage(eglSurface))
+        {
+            return error(EGL_BAD_MATCH, EGL_FALSE);
+        }
 
         return success(EGL_TRUE);
     }
     catch(std::bad_alloc&)
     {
         return error(EGL_BAD_ALLOC, EGL_FALSE);
     }
 
@@ -809,46 +812,72 @@ EGLContext __stdcall eglCreateContext(EG
 {
     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
           "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
 
     try
     {
         // Get the requested client version (default is 1) and check it is two.
         EGLint client_version = 1;
+        bool reset_notification = false;
+        bool robust_access = false;
+
         if (attrib_list)
         {
             for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
             {
-                if (attribute[0] == EGL_CONTEXT_CLIENT_VERSION)
+                switch (attribute[0])
                 {
+                  case EGL_CONTEXT_CLIENT_VERSION:
                     client_version = attribute[1];
-                }
-                else
-                {
+                    break;
+                  case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+                    if (attribute[1] == EGL_TRUE)
+                    {
+                        return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);   // Unimplemented
+                        robust_access = true;
+                    }
+                    else if (attribute[1] != EGL_FALSE)
+                        return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                    break;
+                  case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+                    if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
+                        reset_notification = true;
+                    else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
+                        return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                    break;
+                  default:
                     return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
                 }
             }
         }
 
         if (client_version != 2)
         {
             return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
         }
 
+        if (share_context && static_cast<gl::Context*>(share_context)->isResetNotificationEnabled() != reset_notification)
+        {
+            return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+        }
+
         egl::Display *display = static_cast<egl::Display*>(dpy);
 
         if (!validateConfig(display, config))
         {
             return EGL_NO_CONTEXT;
         }
 
-        EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context));
+        EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
 
-        return success(context);
+        if (context)
+            return success(context);
+        else
+            return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
     }
     catch(std::bad_alloc&)
     {
         return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
     }
 
     return EGL_NO_CONTEXT;
 }
@@ -890,17 +919,23 @@ EGLBoolean __stdcall eglMakeCurrent(EGLD
           dpy, draw, read, ctx);
 
     try
     {
         egl::Display *display = static_cast<egl::Display*>(dpy);
         gl::Context *context = static_cast<gl::Context*>(ctx);
         IDirect3DDevice9 *device = display->getDevice();
 
-        if (!device || display->isDeviceLost())
+        if (!device || display->testDeviceLost())
+        {
+            display->notifyDeviceLost();
+            return EGL_FALSE;
+        }
+
+        if (display->isDeviceLost())
         {
             return error(EGL_CONTEXT_LOST, EGL_FALSE);
         }
 
         if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
         {
             return EGL_FALSE;
         }
@@ -1072,16 +1107,21 @@ EGLBoolean __stdcall eglSwapBuffers(EGLD
         egl::Display *display = static_cast<egl::Display*>(dpy);
         egl::Surface *eglSurface = (egl::Surface*)surface;
 
         if (!validateSurface(display, eglSurface))
         {
             return EGL_FALSE;
         }
 
+        if (display->isDeviceLost())
+        {
+            return error(EGL_CONTEXT_LOST, EGL_FALSE);
+        }
+
         if (surface == EGL_NO_SURFACE)
         {
             return error(EGL_BAD_SURFACE, EGL_FALSE);
         }
 
         if (eglSurface->swap())
         {
             return success(EGL_TRUE);
@@ -1104,16 +1144,21 @@ EGLBoolean __stdcall eglCopyBuffers(EGLD
         egl::Display *display = static_cast<egl::Display*>(dpy);
         egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
 
         if (!validateSurface(display, eglSurface))
         {
             return EGL_FALSE;
         }
 
+        if (display->isDeviceLost())
+        {
+            return error(EGL_CONTEXT_LOST, EGL_FALSE);
+        }
+
         UNIMPLEMENTED();   // FIXME
 
         return success(0);
     }
     catch(std::bad_alloc&)
     {
         return error(EGL_BAD_ALLOC, EGL_FALSE);
     }
--- a/gfx/angle/src/libGLESv2/Context.cpp
+++ b/gfx/angle/src/libGLESv2/Context.cpp
@@ -33,18 +33,20 @@
 
 namespace
 {
     enum { CLOSING_INDEX_BUFFER_SIZE = 4096 };
 }
 
 namespace gl
 {
-Context::Context(const egl::Config *config, const gl::Context *shareContext) : mConfig(config)
+Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config)
 {
+    ASSERT(robustAccess == false);   // Unimplemented
+
     mDisplay = NULL;
     mDevice = NULL;
 
     mFenceHandleAllocator.setBaseHandle(0);
 
     setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
     mState.depthClearValue = 1.0f;
@@ -153,16 +155,20 @@ Context::Context(const egl::Config *conf
 
     mInvalidEnum = false;
     mInvalidValue = false;
     mInvalidOperation = false;
     mOutOfMemory = false;
     mInvalidFramebufferOperation = false;
 
     mHasBeenCurrent = false;
+    mContextLost = false;
+    mResetStatus = GL_NO_ERROR;
+    mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
+    mRobustAccess = robustAccess;
 
     mSupportsDXT1Textures = false;
     mSupportsDXT3Textures = false;
     mSupportsDXT5Textures = false;
     mSupportsEventQueries = false;
     mNumCompressedTextureFormats = 0;
     mMaxSupportedSamples = 0;
     mMaskedClearSavedState = NULL;
@@ -285,18 +291,18 @@ void Context::makeCurrent(egl::Display *
         }
 
         mMaxSupportedSamples = max;
 
         mSupportsEventQueries = mDisplay->getEventQuerySupport();
         mSupportsDXT1Textures = mDisplay->getDXT1TextureSupport();
         mSupportsDXT3Textures = mDisplay->getDXT3TextureSupport();
         mSupportsDXT5Textures = mDisplay->getDXT5TextureSupport();
-        mSupportsFloatTextures = mDisplay->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures);
-        mSupportsHalfFloatTextures = mDisplay->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures);
+        mSupportsFloat32Textures = mDisplay->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures);
+        mSupportsFloat16Textures = mDisplay->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures);
         mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport();
         mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport();
 
         mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
 
         mNumCompressedTextureFormats = 0;
         if (supportsDXT1Textures())
         {
@@ -384,16 +390,28 @@ void Context::markAllStateDirty()
     mScissorStateDirty = true;
     mSampleStateDirty = true;
     mDitherStateDirty = true;
     mFrontFaceDirty = true;
     mDxUniformsDirty = true;
     mCachedCurrentProgram = NULL;
 }
 
+void Context::markContextLost()
+{
+    if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
+        mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
+    mContextLost = true;
+}
+
+bool Context::isContextLost()
+{
+    return mContextLost;
+}
+
 void Context::setClearColor(float red, float green, float blue, float alpha)
 {
     mState.colorClearValue.red = red;
     mState.colorClearValue.green = green;
     mState.colorClearValue.blue = blue;
     mState.colorClearValue.alpha = alpha;
 }
 
@@ -1153,34 +1171,35 @@ Texture *Context::getSamplerTexture(unsi
 
     return mState.samplerTexture[type][sampler].get();
 }
 
 bool Context::getBooleanv(GLenum pname, GLboolean *params)
 {
     switch (pname)
     {
-      case GL_SHADER_COMPILER:          *params = GL_TRUE;                          break;
-      case GL_SAMPLE_COVERAGE_INVERT:   *params = mState.sampleCoverageInvert;      break;
-      case GL_DEPTH_WRITEMASK:          *params = mState.depthMask;                 break;
+      case GL_SHADER_COMPILER:           *params = GL_TRUE;                            break;
+      case GL_SAMPLE_COVERAGE_INVERT:    *params = mState.sampleCoverageInvert;        break;
+      case GL_DEPTH_WRITEMASK:           *params = mState.depthMask;                   break;
       case GL_COLOR_WRITEMASK:
         params[0] = mState.colorMaskRed;
         params[1] = mState.colorMaskGreen;
         params[2] = mState.colorMaskBlue;
         params[3] = mState.colorMaskAlpha;
         break;
-      case GL_CULL_FACE:                *params = mState.cullFace;                  break;
-      case GL_POLYGON_OFFSET_FILL:      *params = mState.polygonOffsetFill;         break;
-      case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;     break;
-      case GL_SAMPLE_COVERAGE:          *params = mState.sampleCoverage;            break;
-      case GL_SCISSOR_TEST:             *params = mState.scissorTest;               break;
-      case GL_STENCIL_TEST:             *params = mState.stencilTest;               break;
-      case GL_DEPTH_TEST:               *params = mState.depthTest;                 break;
-      case GL_BLEND:                    *params = mState.blend;                     break;
-      case GL_DITHER:                   *params = mState.dither;                    break;
+      case GL_CULL_FACE:                 *params = mState.cullFace;                    break;
+      case GL_POLYGON_OFFSET_FILL:       *params = mState.polygonOffsetFill;           break;
+      case GL_SAMPLE_ALPHA_TO_COVERAGE:  *params = mState.sampleAlphaToCoverage;       break;
+      case GL_SAMPLE_COVERAGE:           *params = mState.sampleCoverage;              break;
+      case GL_SCISSOR_TEST:              *params = mState.scissorTest;                 break;
+      case GL_STENCIL_TEST:              *params = mState.stencilTest;                 break;
+      case GL_DEPTH_TEST:                *params = mState.depthTest;                   break;
+      case GL_BLEND:                     *params = mState.blend;                       break;
+      case GL_DITHER:                    *params = mState.dither;                      break;
+      case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
       default:
         return false;
     }
 
     return true;
 }
 
 bool Context::getFloatv(GLenum pname, GLfloat *params)
@@ -1370,17 +1389,17 @@ bool Context::getIntegerv(GLenum pname, 
       case GL_CULL_FACE_MODE:                   *params = mState.cullMode;                 break;
       case GL_FRONT_FACE:                       *params = mState.frontFace;                break;
       case GL_RED_BITS:
       case GL_GREEN_BITS:
       case GL_BLUE_BITS:
       case GL_ALPHA_BITS:
         {
             gl::Framebuffer *framebuffer = getDrawFramebuffer();
-            gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
+            gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
 
             if (colorbuffer)
             {
                 switch (pname)
                 {
                   case GL_RED_BITS:   *params = colorbuffer->getRedSize();   break;
                   case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
                   case GL_BLUE_BITS:  *params = colorbuffer->getBlueSize();  break;
@@ -1391,32 +1410,32 @@ bool Context::getIntegerv(GLenum pname, 
             {
                 *params = 0;
             }
         }
         break;
       case GL_DEPTH_BITS:
         {
             gl::Framebuffer *framebuffer = getDrawFramebuffer();
-            gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
+            gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
 
             if (depthbuffer)
             {
                 *params = depthbuffer->getDepthSize();
             }
             else
             {
                 *params = 0;
             }
         }
         break;
       case GL_STENCIL_BITS:
         {
             gl::Framebuffer *framebuffer = getDrawFramebuffer();
-            gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
+            gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
 
             if (stencilbuffer)
             {
                 *params = stencilbuffer->getStencilSize();
             }
             else
             {
                 *params = 0;
@@ -1440,16 +1459,19 @@ bool Context::getIntegerv(GLenum pname, 
             {
                 error(GL_INVALID_OPERATION);
                 return false;
             }
 
             *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
         }
         break;
+      case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+        *params = mResetStrategy;
+        break;
       default:
         return false;
     }
 
     return true;
 }
 
 bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
@@ -1529,16 +1551,17 @@ bool Context::getQueryParameterInfo(GLen
       case GL_MAX_TEXTURE_SIZE:
       case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
       case GL_SAMPLE_BUFFERS:
       case GL_SAMPLES:
       case GL_IMPLEMENTATION_COLOR_READ_TYPE:
       case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
       case GL_TEXTURE_BINDING_2D:
       case GL_TEXTURE_BINDING_CUBE_MAP:
+      case GL_RESET_NOTIFICATION_STRATEGY_EXT:
         {
             *type = GL_INT;
             *numParams = 1;
         }
         break;
       case GL_MAX_SAMPLES_ANGLE:
         {
             if (getMaxSupportedSamples() != 0)
@@ -1572,16 +1595,17 @@ bool Context::getQueryParameterInfo(GLen
       case GL_POLYGON_OFFSET_FILL:      // but can be retrieved through the Get{Type}v queries.
       case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
       case GL_SAMPLE_COVERAGE:
       case GL_SCISSOR_TEST:
       case GL_STENCIL_TEST:
       case GL_DEPTH_TEST:
       case GL_BLEND:
       case GL_DITHER:
+      case GL_CONTEXT_ROBUST_ACCESS_EXT:
         {
             *type = GL_BOOL;
             *numParams = 1;
         }
         break;
       case GL_COLOR_WRITEMASK:
         {
             *type = GL_BOOL;
@@ -1725,17 +1749,17 @@ bool Context::applyRenderTarget(bool ign
         viewport.MaxZ = zFar;
     }
 
     if (viewport.Width <= 0 || viewport.Height <= 0)
     {
         return false;   // Nothing to render
     }
 
-    if (!mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0)
+    if (renderTargetChanged || !mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0)
     {
         mDevice->SetViewport(&viewport);
         mSetViewport = viewport;
         mViewportInitialized = true;
         mDxUniformsDirty = true;
     }
 
     if (mScissorStateDirty)
@@ -1906,17 +1930,17 @@ void Context::applyState(GLenum drawMode
                 mState.stencilRef != mState.stencilBackRef || 
                 mState.stencilMask != mState.stencilBackMask)
             {
                 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
                 return error(GL_INVALID_OPERATION);
             }
 
             // get the maximum size of the stencil ref
-            gl::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
+            gl::Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
             GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
 
             mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
             mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 
                                    es2dx::ConvertComparison(mState.stencilFunc));
 
             mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
             mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
@@ -1973,17 +1997,17 @@ void Context::applyState(GLenum drawMode
 
         mMaskStateDirty = false;
     }
 
     if (mPolygonOffsetStateDirty)
     {
         if (mState.polygonOffsetFill)
         {
-            gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
+            gl::Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer();
             if (depthbuffer)
             {
                 mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
                 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
                 mDevice->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
             }
         }
         else
@@ -2122,50 +2146,50 @@ void Context::applyTextures(SamplerType 
         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())
+            if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyParameters() || texture->hasDirtyImages())
             {
                 IDirect3DBaseTexture9 *d3dTexture = texture->getTexture();
 
                 if (d3dTexture)
                 {
-                    if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter())
+                    if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyParameters())
                     {
                         GLenum wrapS = texture->getWrapS();
                         GLenum wrapT = texture->getWrapT();
                         GLenum minFilter = texture->getMinFilter();
                         GLenum magFilter = texture->getMagFilter();
 
                         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
                         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
 
                         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
                         D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
                         es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
                         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
                         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
                     }
 
-                    if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyImage())
+                    if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyImages())
                     {
                         mDevice->SetTexture(d3dSampler, d3dTexture);
                     }
                 }
                 else
                 {
                     mDevice->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture());
                 }
 
-                appliedTextureSerial[samplerIndex] = texture->getSerial();
+                appliedTextureSerial[samplerIndex] = texture->getTextureSerial();
                 texture->resetDirty();
             }
         }
         else
         {
             if (appliedTextureSerial[samplerIndex] != 0)
             {
                 mDevice->SetTexture(d3dSampler, NULL);
@@ -2179,30 +2203,42 @@ void Context::applyTextures(SamplerType 
         if (appliedTextureSerial[samplerIndex] != 0)
         {
             mDevice->SetTexture(samplerIndex + d3dSamplerOffset, NULL);
             appliedTextureSerial[samplerIndex] = 0;
         }
     }
 }
 
-void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
+void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
 {
     Framebuffer *framebuffer = getReadFramebuffer();
 
     if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
     {
         return error(GL_INVALID_FRAMEBUFFER_OPERATION);
     }
 
     if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
     {
         return error(GL_INVALID_OPERATION);
     }
 
+    GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
+    // sized query sanity check
+    if (bufSize)
+    {
+        int requiredSize = outputPitch * height;
+        if (requiredSize > *bufSize)
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+    }
+
     IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
 
     if (!renderTarget)
     {
         return;   // Context must be lost, return silently
     }
 
     D3DSURFACE_DESC desc;
@@ -2224,28 +2260,26 @@ void Context::readPixels(GLint x, GLint 
     }
 
     result = mDevice->GetRenderTargetData(renderTarget, systemSurface);
 
     if (FAILED(result))
     {
         systemSurface->Release();
 
-        switch (result)
+        // It turns out that D3D will sometimes produce more error
+        // codes than those documented.
+        if (checkDeviceLost(result))
+            return error(GL_OUT_OF_MEMORY);
+        else
         {
-          // It turns out that D3D will sometimes produce more error
-          // codes than those documented.
-          case D3DERR_DRIVERINTERNALERROR:
-          case D3DERR_DEVICELOST:
-          case D3DERR_DEVICEHUNG:
-            return error(GL_OUT_OF_MEMORY);
-          default:
             UNREACHABLE();
-            return;   // No sensible error to generate
+            return;
         }
+
     }
 
     D3DLOCKED_RECT lock;
     RECT rect = transformPixelRect(x, y, width, height, desc.Height);
     rect.left = clamp(rect.left, 0L, static_cast<LONG>(desc.Width));
     rect.top = clamp(rect.top, 0L, static_cast<LONG>(desc.Height));
     rect.right = clamp(rect.right, 0L, static_cast<LONG>(desc.Width));
     rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(desc.Height));
@@ -2259,17 +2293,16 @@ void Context::readPixels(GLint x, GLint 
 
         return;   // No sensible error to generate
     }
 
     unsigned char *source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
     unsigned char *dest = (unsigned char*)pixels;
     unsigned short *dest16 = (unsigned short*)pixels;
     int inputPitch = -lock.Pitch;
-    GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
 
     for (int j = 0; j < rect.bottom - rect.top; j++)
     {
         if (desc.Format == D3DFMT_A8R8G8B8 &&
             format == GL_BGRA_EXT &&
             type == GL_UNSIGNED_BYTE)
         {
             // Fast path for EXT_read_format_bgra, given
@@ -2821,17 +2854,17 @@ void Context::sync(bool block)
             // Keep polling, but allow other threads to do something useful first
             Sleep(0);
         }
     }
     while(block && result == S_FALSE);
 
     eventQuery->Release();
 
-    if (result == D3DERR_DEVICELOST)
+    if (checkDeviceLost(result))
     {
         error(GL_OUT_OF_MEMORY);
     }
 }
 
 void Context::drawClosingLine(unsigned int first, unsigned int last)
 {
     IDirect3DIndexBuffer9 *indexBuffer = NULL;
@@ -2989,16 +3022,46 @@ GLenum Context::getError()
         mInvalidFramebufferOperation = false;
 
         return GL_INVALID_FRAMEBUFFER_OPERATION;
     }
 
     return GL_NO_ERROR;
 }
 
+GLenum Context::getResetStatus()
+{
+    if (mResetStatus == GL_NO_ERROR)
+    {
+        bool lost = mDisplay->testDeviceLost();
+
+        if (lost)
+        {
+            mDisplay->notifyDeviceLost();   // Sets mResetStatus
+        }
+    }
+
+    GLenum status = mResetStatus;
+
+    if (mResetStatus != GL_NO_ERROR)
+    {
+        if (mDisplay->testDeviceResettable())
+        {
+            mResetStatus = GL_NO_ERROR;
+        }
+    }
+    
+    return status;
+}
+
+bool Context::isResetNotificationEnabled()
+{
+    return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
 bool Context::supportsShaderModel3() const
 {
     return mSupportsShaderModel3;
 }
 
 int Context::getMaximumVaryingVectors() const
 {
     return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
@@ -3063,44 +3126,44 @@ bool Context::supportsDXT3Textures() con
     return mSupportsDXT3Textures;
 }
 
 bool Context::supportsDXT5Textures() const
 {
     return mSupportsDXT5Textures;
 }
 
-bool Context::supportsFloatTextures() const
+bool Context::supportsFloat32Textures() const
 {
-    return mSupportsFloatTextures;
+    return mSupportsFloat32Textures;
 }
 
-bool Context::supportsFloatLinearFilter() const
+bool Context::supportsFloat32LinearFilter() const
 {
-    return mSupportsFloatLinearFilter;
+    return mSupportsFloat32LinearFilter;
 }
 
-bool Context::supportsFloatRenderableTextures() const
+bool Context::supportsFloat32RenderableTextures() const
 {
-    return mSupportsFloatRenderableTextures;
+    return mSupportsFloat32RenderableTextures;
 }
 
-bool Context::supportsHalfFloatTextures() const
+bool Context::supportsFloat16Textures() const
 {
-    return mSupportsHalfFloatTextures;
+    return mSupportsFloat16Textures;
 }
 
-bool Context::supportsHalfFloatLinearFilter() const
+bool Context::supportsFloat16LinearFilter() const
 {
-    return mSupportsHalfFloatLinearFilter;
+    return mSupportsFloat16LinearFilter;
 }
 
-bool Context::supportsHalfFloatRenderableTextures() const
+bool Context::supportsFloat16RenderableTextures() const
 {
-    return mSupportsHalfFloatRenderableTextures;
+    return mSupportsFloat16RenderableTextures;
 }
 
 int Context::getMaximumRenderbufferDimension() const
 {
     return mMaxRenderbufferDimension;
 }
 
 int Context::getMaximumTextureDimension() const
@@ -3339,63 +3402,67 @@ void Context::initExtensionString()
     {
         mExtensionString += "GL_OES_element_index_uint ";
     }
 
     mExtensionString += "GL_OES_packed_depth_stencil ";
     mExtensionString += "GL_OES_rgb8_rgba8 ";
     mExtensionString += "GL_OES_standard_derivatives ";
 
-    if (supportsHalfFloatTextures())
+    if (supportsFloat16Textures())
     {
         mExtensionString += "GL_OES_texture_half_float ";
     }
-    if (supportsHalfFloatLinearFilter())
+    if (supportsFloat16LinearFilter())
     {
         mExtensionString += "GL_OES_texture_half_float_linear ";
     }
-    if (supportsFloatTextures())
+    if (supportsFloat32Textures())
     {
         mExtensionString += "GL_OES_texture_float ";
     }
-    if (supportsFloatLinearFilter())
+    if (supportsFloat32LinearFilter())
     {
         mExtensionString += "GL_OES_texture_float_linear ";
     }
 
     if (supportsNonPower2Texture())
     {
         mExtensionString += "GL_OES_texture_npot ";
     }
 
     // Multi-vendor (EXT) extensions
     mExtensionString += "GL_EXT_read_format_bgra ";
+    mExtensionString += "GL_EXT_robustness ";
 
     if (supportsDXT1Textures())
     {
         mExtensionString += "GL_EXT_texture_compression_dxt1 ";
     }
 
     mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
+    mExtensionString += "GL_EXT_texture_storage ";
 
     // ANGLE-specific extensions
     mExtensionString += "GL_ANGLE_framebuffer_blit ";
     if (getMaxSupportedSamples() != 0)
     {
         mExtensionString += "GL_ANGLE_framebuffer_multisample ";
     }
 
     if (supportsDXT3Textures())
     {
         mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
     }
     if (supportsDXT5Textures())
     {
         mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
     }
+
+    mExtensionString += "GL_ANGLE_texture_usage ";
     mExtensionString += "GL_ANGLE_translated_shader_source ";
 
     // Other vendor-specific extensions
     if (supportsEventQueries())
     {
         mExtensionString += "GL_NV_fence ";
     }
 
@@ -3611,18 +3678,18 @@ void Context::blitFramebuffer(GLint srcX
         }
 
         blitRenderTarget = true;
 
     }
 
     if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
     {
-        DepthStencilbuffer *readDSBuffer = NULL;
-        DepthStencilbuffer *drawDSBuffer = NULL;
+        Renderbuffer *readDSBuffer = NULL;
+        Renderbuffer *drawDSBuffer = NULL;
 
         // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
         // both a depth and stencil buffer, it will be the same buffer.
 
         if (mask & GL_DEPTH_BUFFER_BIT)
         {
             if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
             {
@@ -3800,19 +3867,19 @@ void VertexDeclarationCache::markStateDi
 
     mLastSetVDecl = NULL;
 }
 
 }
 
 extern "C"
 {
-gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
 {
-    return new gl::Context(config, shareContext);
+    return new gl::Context(config, shareContext, notifyResets, robustAccess);
 }
 
 void glDestroyContext(gl::Context *context)
 {
     delete context;
 
     if (context == gl::getContext())
     {
--- a/gfx/angle/src/libGLESv2/Context.h
+++ b/gfx/angle/src/libGLESv2/Context.h
@@ -253,24 +253,27 @@ class VertexDeclarationCache
         UINT lruCount;
         IDirect3DVertexDeclaration9 *vertexDeclaration;
     } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
 };
 
 class Context
 {
   public:
-    Context(const egl::Config *config, const gl::Context *shareContext);
+    Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
 
     ~Context();
 
     void makeCurrent(egl::Display *display, egl::Surface *surface);
 
     void markAllStateDirty();
 
+    virtual void markContextLost();
+    bool isContextLost();
+
     // State manipulation
     void setClearColor(float red, float green, float blue, float alpha);
 
     void setClearDepth(float depth);
 
     void setClearStencil(int stencil);
 
     void setCullFace(bool enabled);
@@ -412,33 +415,35 @@ class Context
     Framebuffer *getDrawFramebuffer();
 
     bool getFloatv(GLenum pname, GLfloat *params);
     bool getIntegerv(GLenum pname, GLint *params);
     bool getBooleanv(GLenum pname, GLboolean *params);
 
     bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
 
-    void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+    void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
     void clear(GLbitfield mask);
     void drawArrays(GLenum mode, GLint first, GLsizei count);
     void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
     void sync(bool block);   // flush/finish
 
 	// Draw the last segment of a line loop
     void drawClosingLine(unsigned int first, unsigned int last);
     void drawClosingLine(GLsizei count, GLenum type, const void *indices);
 
     void recordInvalidEnum();
     void recordInvalidValue();
     void recordInvalidOperation();
     void recordOutOfMemory();
     void recordInvalidFramebufferOperation();
 
     GLenum getError();
+    GLenum getResetStatus();
+    virtual bool isResetNotificationEnabled();
 
     bool supportsShaderModel3() const;
     int getMaximumVaryingVectors() const;
     unsigned int getMaximumVertexTextureImageUnits() const;
     unsigned int getMaximumCombinedTextureImageUnits() const;
     int getMaximumFragmentUniformVectors() const;
     int getMaximumRenderbufferDimension() const;
     int getMaximumTextureDimension() const;
@@ -447,22 +452,22 @@ class Context
     GLsizei getMaxSupportedSamples() const;
     int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
     const char *getExtensionString() const;
     const char *getRendererString() const;
     bool supportsEventQueries() const;
     bool supportsDXT1Textures() const;
     bool supportsDXT3Textures() const;
     bool supportsDXT5Textures() const;
-    bool supportsFloatTextures() const;
-    bool supportsFloatLinearFilter() const;
-    bool supportsFloatRenderableTextures() const;
-    bool supportsHalfFloatTextures() const;
-    bool supportsHalfFloatLinearFilter() const;
-    bool supportsHalfFloatRenderableTextures() const;
+    bool supportsFloat32Textures() const;
+    bool supportsFloat32LinearFilter() const;
+    bool supportsFloat32RenderableTextures() const;
+    bool supportsFloat16Textures() const;
+    bool supportsFloat16LinearFilter() const;
+    bool supportsFloat16RenderableTextures() const;
     bool supportsLuminanceTextures() const;
     bool supportsLuminanceAlphaTextures() const;
     bool supports32bitIndices() const;
     bool supportsNonPower2Texture() const;
 
     void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 
                          GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                          GLbitfield mask);
@@ -526,17 +531,22 @@ class Context
 
     // Recorded errors
     bool mInvalidEnum;
     bool mInvalidValue;
     bool mInvalidOperation;
     bool mOutOfMemory;
     bool mInvalidFramebufferOperation;
 
+    // Current/lost context flags
     bool mHasBeenCurrent;
+    bool mContextLost;
+    GLenum mResetStatus;
+    GLenum mResetStrategy;
+    bool mRobustAccess;
 
     unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS];
     unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
     unsigned int mAppliedProgramSerial;
     unsigned int mAppliedRenderTargetSerial;
     unsigned int mAppliedDepthbufferSerial;
     unsigned int mAppliedStencilbufferSerial;
     unsigned int mAppliedIBSerial;
@@ -557,22 +567,22 @@ class Context
     int  mMaxCubeTextureDimension;
     int  mMaxTextureLevel;
     std::map<D3DFORMAT, bool *> mMultiSampleSupport;
     GLsizei mMaxSupportedSamples;
     bool mSupportsEventQueries;
     bool mSupportsDXT1Textures;
     bool mSupportsDXT3Textures;
     bool mSupportsDXT5Textures;
-    bool mSupportsFloatTextures;
-    bool mSupportsFloatLinearFilter;
-    bool mSupportsFloatRenderableTextures;
-    bool mSupportsHalfFloatTextures;
-    bool mSupportsHalfFloatLinearFilter;
-    bool mSupportsHalfFloatRenderableTextures;
+    bool mSupportsFloat32Textures;
+    bool mSupportsFloat32LinearFilter;
+    bool mSupportsFloat32RenderableTextures;
+    bool mSupportsFloat16Textures;
+    bool mSupportsFloat16LinearFilter;
+    bool mSupportsFloat16RenderableTextures;
     bool mSupportsLuminanceTextures;
     bool mSupportsLuminanceAlphaTextures;
     bool mSupports32bitIndices;
     int mNumCompressedTextureFormats;
 
     // state caching flags
     bool mClearStateDirty;
     bool mCullStateDirty;
@@ -595,17 +605,17 @@ class Context
 
     VertexDeclarationCache mVertexDeclarationCache;
 };
 }
 
 extern "C"
 {
 // Exported functions for use by EGL
-gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext);
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
 void glDestroyContext(gl::Context *context);
 void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
 gl::Context *glGetCurrentContext();
 __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
-void __stdcall glBindTexImage(egl::Surface *surface);
+bool __stdcall glBindTexImage(egl::Surface *surface);
 }
 
 #endif   // INCLUDE_CONTEXT_H_
--- a/gfx/angle/src/libGLESv2/Fence.cpp
+++ b/gfx/angle/src/libGLESv2/Fence.cpp
@@ -60,17 +60,17 @@ GLboolean Fence::testFence()
 {
     if (mQuery == NULL)
     {
         return error(GL_INVALID_OPERATION, GL_TRUE);
     }
 
     HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
 
-    if (result == D3DERR_DEVICELOST)
+    if (checkDeviceLost(result))
     {
        return error(GL_OUT_OF_MEMORY, GL_TRUE);
     }
 
     ASSERT(result == S_OK || result == S_FALSE);
     mStatus = result == S_OK;
     return mStatus;
 }
@@ -105,17 +105,17 @@ void Fence::getFenceiv(GLenum pname, GLi
             if (mStatus)
             {
                 params[0] = GL_TRUE;
                 return;
             }
             
             HRESULT result = mQuery->GetData(NULL, 0, 0);
             
-            if (result == D3DERR_DEVICELOST)
+            if (checkDeviceLost(result))
             {
                 params[0] = GL_TRUE;
                 return error(GL_OUT_OF_MEMORY);
             }
 
             ASSERT(result == S_OK || result == S_FALSE);
             mStatus = result == S_OK;
             params[0] = mStatus;
--- a/gfx/angle/src/libGLESv2/Framebuffer.cpp
+++ b/gfx/angle/src/libGLESv2/Framebuffer.cpp
@@ -176,56 +176,29 @@ unsigned int Framebuffer::getStencilbuff
     if (stencilbuffer)
     {
         return stencilbuffer->getSerial();
     }
 
     return 0;
 }
 
-Colorbuffer *Framebuffer::getColorbuffer()
+Renderbuffer *Framebuffer::getColorbuffer()
 {
-    Renderbuffer *rb = mColorbufferPointer.get();
-
-    if (rb != NULL && rb->isColorbuffer())
-    {
-        return static_cast<Colorbuffer*>(rb->getStorage());
-    }
-    else
-    {
-        return NULL;
-    }
+    return mColorbufferPointer.get();
 }
 
-DepthStencilbuffer *Framebuffer::getDepthbuffer()
+Renderbuffer *Framebuffer::getDepthbuffer()
 {
-    Renderbuffer *rb = mDepthbufferPointer.get();
-
-    if (rb != NULL && rb->isDepthbuffer())
-    {
-        return static_cast<DepthStencilbuffer*>(rb->getStorage());
-    }
-    else
-    {
-        return NULL;
-    }
+    return mDepthbufferPointer.get();
 }
 
-DepthStencilbuffer *Framebuffer::getStencilbuffer()
+Renderbuffer *Framebuffer::getStencilbuffer()
 {
-    Renderbuffer *rb = mStencilbufferPointer.get();
-
-    if (rb != NULL && rb->isStencilbuffer())
-    {
-        return static_cast<DepthStencilbuffer*>(rb->getStorage());
-    }
-    else
-    {
-        return NULL;
-    }
+    return mStencilbufferPointer.get();
 }
 
 GLenum Framebuffer::getColorbufferType()
 {
     return mColorbufferType;
 }
 
 GLenum Framebuffer::getDepthbufferType()
@@ -252,17 +225,17 @@ GLuint Framebuffer::getStencilbufferHand
 {
     return mStencilbufferPointer.id();
 }
 
 bool Framebuffer::hasStencil()
 {
     if (mStencilbufferType != GL_NONE)
     {
-        DepthStencilbuffer *stencilbufferObject = getStencilbuffer();
+        Renderbuffer *stencilbufferObject = getStencilbuffer();
 
         if (stencilbufferObject)
         {
             return stencilbufferObject->getStencilSize() > 0;
         }
     }
 
     return false;
@@ -271,17 +244,17 @@ bool Framebuffer::hasStencil()
 GLenum Framebuffer::completeness()
 {
     int width = 0;
     int height = 0;
     int samples = -1;
 
     if (mColorbufferType != GL_NONE)
     {
-        Colorbuffer *colorbuffer = getColorbuffer();
+        Renderbuffer *colorbuffer = getColorbuffer();
 
         if (!colorbuffer)
         {
             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
         }
 
         if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
         {
@@ -297,18 +270,18 @@ GLenum Framebuffer::completeness()
         }
         else if (IsTextureTarget(mColorbufferType))
         {
             if (IsCompressed(colorbuffer->getInternalFormat()))
             {
                 return GL_FRAMEBUFFER_UNSUPPORTED;
             }
 
-            if ((colorbuffer->getType() == GL_FLOAT && !getContext()->supportsFloatRenderableTextures()) || 
-                (colorbuffer->getType() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatRenderableTextures()))
+            if ((dx2es::IsFloat32Format(colorbuffer->getD3DFormat()) && !getContext()->supportsFloat32RenderableTextures()) || 
+                (dx2es::IsFloat16Format(colorbuffer->getD3DFormat()) && !getContext()->supportsFloat16RenderableTextures()))
             {
                 return GL_FRAMEBUFFER_UNSUPPORTED;
             }
 
             if (colorbuffer->getInternalFormat() == GL_LUMINANCE || colorbuffer->getInternalFormat() == GL_LUMINANCE_ALPHA)
             {
                 return GL_FRAMEBUFFER_UNSUPPORTED;
             }
@@ -319,18 +292,18 @@ GLenum Framebuffer::completeness()
         height = colorbuffer->getHeight();
         samples = colorbuffer->getSamples();
     }
     else
     {
         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
     }
 
-    DepthStencilbuffer *depthbuffer = NULL;
-    DepthStencilbuffer *stencilbuffer = NULL;
+    Renderbuffer *depthbuffer = NULL;
+    Renderbuffer *stencilbuffer = NULL;
 
     if (mDepthbufferType != GL_NONE)
     {
         if (mDepthbufferType != GL_RENDERBUFFER)
         {
             return GL_FRAMEBUFFER_UNSUPPORTED;   // Requires GL_OES_depth_texture
         }
 
@@ -413,27 +386,27 @@ GLenum Framebuffer::completeness()
         {
             return GL_FRAMEBUFFER_UNSUPPORTED;
         }
     }
 
     return GL_FRAMEBUFFER_COMPLETE;
 }
 
-DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil)
+DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
 {
-    mColorbufferType = GL_RENDERBUFFER;
-    mDepthbufferType = (depthStencil->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
-    mStencilbufferType = (depthStencil->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
-
-    mColorbufferPointer.set(new Renderbuffer(0, color));
+    mColorbufferPointer.set(new Renderbuffer(0, colorbuffer));
 
     Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
     mDepthbufferPointer.set(depthStencilRenderbuffer);
     mStencilbufferPointer.set(depthStencilRenderbuffer);
+
+    mColorbufferType = GL_RENDERBUFFER;
+    mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+    mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
 }
 
 int Framebuffer::getSamples()
 {
     if (completeness() == GL_FRAMEBUFFER_COMPLETE)
     {
         return getColorbuffer()->getSamples();
     }
--- a/gfx/angle/src/libGLESv2/Framebuffer.h
+++ b/gfx/angle/src/libGLESv2/Framebuffer.h
@@ -41,19 +41,19 @@ class Framebuffer
 
     IDirect3DSurface9 *getRenderTarget();
     IDirect3DSurface9 *getDepthStencil();
 
     unsigned int getRenderTargetSerial();
     unsigned int getDepthbufferSerial();
     unsigned int getStencilbufferSerial();
 
-    Colorbuffer *getColorbuffer();
-    DepthStencilbuffer *getDepthbuffer();
-    DepthStencilbuffer *getStencilbuffer();
+    Renderbuffer *getColorbuffer();
+    Renderbuffer *getDepthbuffer();
+    Renderbuffer *getStencilbuffer();
 
     GLenum getColorbufferType();
     GLenum getDepthbufferType();
     GLenum getStencilbufferType();
 
     GLuint getColorbufferHandle();
     GLuint getDepthbufferHandle();
     GLuint getStencilbufferHandle();
@@ -77,17 +77,17 @@ class Framebuffer
     DISALLOW_COPY_AND_ASSIGN(Framebuffer);
 
     Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const;
 };
 
 class DefaultFramebuffer : public Framebuffer
 {
   public:
-    DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil);
+    DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
 
     virtual GLenum completeness();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer);
 };
 
 }
--- a/gfx/angle/src/libGLESv2/Program.cpp
+++ b/gfx/angle/src/libGLESv2/Program.cpp
@@ -31,17 +31,17 @@ std::string str(int i)
     char buffer[20];
     sprintf(buffer, "%d", i);
     return buffer;
 }
 
 Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize)
     : type(type), _name(_name), name(Program::undecorateUniform(_name)), arraySize(arraySize)
 {
-    int bytes = UniformTypeSize(type) * arraySize;
+    int bytes = UniformInternalSize(type) * arraySize;
     data = new unsigned char[bytes];
     memset(data, 0, bytes);
     dirty = true;
 }
 
 Uniform::~Uniform()
 {
     delete[] data;
@@ -555,33 +555,33 @@ void transposeMatrix(T *target, const GL
 {
     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];
+            target[x * targetWidth + y] = (T)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;
+            target[y * targetWidth + x] = (T)0;
         }
     }
     // clear unfilled bottom.
     for (int y = srcHeight; y < targetHeight; y++)
     {
         for (int x = 0; x < targetWidth; x++)
         {
-            target[y * targetWidth + x] = 0;
+            target[y * targetWidth + x] = (T)0;
         }
     }
 }
 
 bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
@@ -906,39 +906,49 @@ bool Program::setUniform4iv(GLint locati
     else
     {
         return false;
     }
 
     return true;
 }
 
-bool Program::getUniformfv(GLint location, GLfloat *params)
+bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
         return false;
     }
 
     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
 
+    // sized queries -- ensure the provided buffer is large enough
+    if (bufSize)
+    {
+        int requiredBytes = UniformExternalSize(targetUniform->type);
+        if (*bufSize < requiredBytes)
+        {
+            return false;
+        }
+    }
+
     switch (targetUniform->type)
     {
       case GL_FLOAT_MAT2:
         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:
         {
-            unsigned int count = UniformComponentCount(targetUniform->type);
+            unsigned int count = UniformExternalComponentCount(targetUniform->type);
             unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
 
             switch (UniformComponentType(targetUniform->type))
             {
               case GL_BOOL:
                 {
                     GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * internalCount;
 
@@ -965,25 +975,35 @@ bool Program::getUniformfv(GLint locatio
               default: UNREACHABLE();
             }
         }
     }
 
     return true;
 }
 
-bool Program::getUniformiv(GLint location, GLint *params)
+bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
         return false;
     }
 
     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
 
+    // sized queries -- ensure the provided buffer is large enough
+    if (bufSize)
+    {
+        int requiredBytes = UniformExternalSize(targetUniform->type);
+        if (*bufSize < requiredBytes)
+        {
+            return false;
+        }
+    }
+
     switch (targetUniform->type)
     {
       case GL_FLOAT_MAT2:
         {
             transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
         }
         break;
       case GL_FLOAT_MAT3:
@@ -993,17 +1013,17 @@ bool Program::getUniformiv(GLint locatio
         break;
       case GL_FLOAT_MAT4:
         {
             transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
         }
         break;
       default:
         {
-            unsigned int count = UniformComponentCount(targetUniform->type);
+            unsigned int count = UniformExternalComponentCount(targetUniform->type);
             unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
 
             switch (UniformComponentType(targetUniform->type))
             {
               case GL_BOOL:
                 {
                     GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * internalCount;
 
@@ -1829,36 +1849,43 @@ bool Program::linkUniforms(ID3DXConstant
 }
 
 // Adds the description of a constant found in the binary shader to the list of uniforms
 // Returns true if succesful (uniform not already defined)
 bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
 {
     if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
     {
-        for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++)
+        for (unsigned int i = 0; i < constantDescription.RegisterCount; i++)
         {
-            if (mConstantTablePS->GetConstantByName(NULL, constantDescription.Name) != NULL)
+            D3DXHANDLE psConstant = mConstantTablePS->GetConstantByName(NULL, constantDescription.Name);
+            D3DXHANDLE vsConstant = mConstantTableVS->GetConstantByName(NULL, constantDescription.Name);
+
+            if (psConstant)
             {
+                unsigned int samplerIndex = mConstantTablePS->GetSamplerIndex(psConstant) + i;
+
                 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
                 {
                     mSamplersPS[samplerIndex].active = true;
                     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 (vsConstant)
             {
+                unsigned int samplerIndex = mConstantTableVS->GetSamplerIndex(vsConstant) + i;
+
                 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
--- a/gfx/angle/src/libGLESv2/Program.h
+++ b/gfx/angle/src/libGLESv2/Program.h
@@ -93,18 +93,18 @@ class Program
     bool setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);
     bool setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);
     bool setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);
     bool setUniform1iv(GLint location, GLsizei count, const GLint *v);
     bool setUniform2iv(GLint location, GLsizei count, const GLint *v);
     bool setUniform3iv(GLint location, GLsizei count, const GLint *v);
     bool setUniform4iv(GLint location, GLsizei count, const GLint *v);
 
-    bool getUniformfv(GLint location, GLfloat *params);
-    bool getUniformiv(GLint location, GLint *params);
+    bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params);
+    bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params);
 
     GLint getDxDepthRangeLocation() const;
     GLint getDxDepthLocation() const;
     GLint getDxViewportLocation() const;
     GLint getDxHalfPixelSizeLocation() const;
     GLint getDxFrontCCWLocation() const;
     GLint getDxPointsOrLinesLocation() const;
 
--- a/gfx/angle/src/libGLESv2/Renderbuffer.cpp
+++ b/gfx/angle/src/libGLESv2/Renderbuffer.cpp
@@ -13,143 +13,200 @@
 #include "libGLESv2/main.h"
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/utilities.h"
 
 namespace gl
 {
 unsigned int RenderbufferStorage::mCurrentSerial = 1;
 
-Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *storage) : RefCountObject(id)
+RenderbufferInterface::RenderbufferInterface()
+{
+}
+
+GLuint RenderbufferInterface::getRedSize() const
+{
+    return dx2es::GetRedSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getGreenSize() const
+{
+    return dx2es::GetGreenSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getBlueSize() const
+{
+    return dx2es::GetBlueSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getAlphaSize() const
+{
+    return dx2es::GetAlphaSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getDepthSize() const
+{
+    return dx2es::GetDepthSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getStencilSize() const
+{
+    return dx2es::GetStencilSize(getD3DFormat());
+}
+
+RenderbufferTexture::RenderbufferTexture(Texture *texture, GLenum target) : mTexture(texture), mTarget(target)
+{
+}
+
+RenderbufferTexture::~RenderbufferTexture()
 {
-    ASSERT(storage != NULL);
-    mStorage = storage;
+}
+
+IDirect3DSurface9 *RenderbufferTexture::getRenderTarget()
+{
+    return mTexture->getRenderTarget(mTarget);
+}
+
+IDirect3DSurface9 *RenderbufferTexture::getDepthStencil()
+{
+    return NULL;
+}
+
+GLsizei RenderbufferTexture::getWidth() const
+{
+    return mTexture->getWidth();
+}
+ 
+GLsizei RenderbufferTexture::getHeight() const
+{
+    return mTexture->getHeight();
+}
+ 
+GLenum RenderbufferTexture::getInternalFormat() const
+{
+    return mTexture->getInternalFormat();
+}
+
+D3DFORMAT RenderbufferTexture::getD3DFormat() const
+{
+    return mTexture->getD3DFormat();
+}
+
+GLsizei RenderbufferTexture::getSamples() const
+{
+    return 0;
+}
+
+unsigned int RenderbufferTexture::getSerial() const
+{
+    return mTexture->getRenderTargetSerial(mTarget);
+}
+
+Renderbuffer::Renderbuffer(GLuint id, RenderbufferInterface *instance) : RefCountObject(id)
+{
+    ASSERT(instance != NULL);
+    mInstance = instance;
 }
 
 Renderbuffer::~Renderbuffer()
 {
-    delete mStorage;
-}
-
-bool Renderbuffer::isColorbuffer() const
-{
-    return mStorage->isColorbuffer();
-}
-
-bool Renderbuffer::isDepthbuffer() const
-{
-    return mStorage->isDepthbuffer();
-}
-
-bool Renderbuffer::isStencilbuffer() const
-{
-    return mStorage->isStencilbuffer();
+    delete mInstance;
 }
 
 IDirect3DSurface9 *Renderbuffer::getRenderTarget()
 {
-    return mStorage->getRenderTarget();
+    return mInstance->getRenderTarget();
 }
 
 IDirect3DSurface9 *Renderbuffer::getDepthStencil()
 {
-    return mStorage->getDepthStencil();
+    return mInstance->getDepthStencil();
 }
 
 GLsizei Renderbuffer::getWidth() const
 {
-    return mStorage->getWidth();
+    return mInstance->getWidth();
 }
 
 GLsizei Renderbuffer::getHeight() const
 {
-    return mStorage->getHeight();
+    return mInstance->getHeight();
 }
 
 GLenum Renderbuffer::getInternalFormat() const
 {
-    return mStorage->getInternalFormat();
+    return mInstance->getInternalFormat();
+}
+
+D3DFORMAT Renderbuffer::getD3DFormat() const
+{
+    return mInstance->getD3DFormat();
 }
 
 GLuint Renderbuffer::getRedSize() const
 {
-    return mStorage->getRedSize();
+    return mInstance->getRedSize();
 }
 
 GLuint Renderbuffer::getGreenSize() const
 {
-    return mStorage->getGreenSize();
+    return mInstance->getGreenSize();
 }
 
 GLuint Renderbuffer::getBlueSize() const
 {
-    return mStorage->getBlueSize();
+    return mInstance->getBlueSize();
 }
 
 GLuint Renderbuffer::getAlphaSize() const
 {
-    return mStorage->getAlphaSize();
+    return mInstance->getAlphaSize();
 }
 
 GLuint Renderbuffer::getDepthSize() const
 {
-    return mStorage->getDepthSize();
+    return mInstance->getDepthSize();
 }
 
 GLuint Renderbuffer::getStencilSize() const
 {
-    return mStorage->getStencilSize();
+    return mInstance->getStencilSize();
 }
 
 GLsizei Renderbuffer::getSamples() const
 {
-    return mStorage->getSamples();
+    return mInstance->getSamples();
 }
 
 unsigned int Renderbuffer::getSerial() const
 {
-    return mStorage->getSerial();
+    return mInstance->getSerial();
 }
 
 void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
 {
     ASSERT(newStorage != NULL);
 
-    delete mStorage;
-    mStorage = newStorage;
+    delete mInstance;
+    mInstance = newStorage;
 }
 
 RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial())
 {
     mWidth = 0;
     mHeight = 0;
     mInternalFormat = GL_RGBA4;
     mD3DFormat = D3DFMT_A8R8G8B8;
     mSamples = 0;
 }
 
 RenderbufferStorage::~RenderbufferStorage()
 {
 }
 
-bool RenderbufferStorage::isColorbuffer() const
-{
-    return false;
-}
-
-bool RenderbufferStorage::isDepthbuffer() const
-{
-    return false;
-}
-
-bool RenderbufferStorage::isStencilbuffer() const
-{
-    return false;
-}
-
 IDirect3DSurface9 *RenderbufferStorage::getRenderTarget()
 {
     return NULL;
 }
 
 IDirect3DSurface9 *RenderbufferStorage::getDepthStencil()
 {
     return NULL;
@@ -165,98 +222,61 @@ GLsizei RenderbufferStorage::getHeight()
     return mHeight;
 }
 
 GLenum RenderbufferStorage::getInternalFormat() const
 {
     return mInternalFormat;
 }
 
-GLuint RenderbufferStorage::getRedSize() const
-{
-    return dx2es::GetRedSize(getD3DFormat());
-}
-
-GLuint RenderbufferStorage::getGreenSize() const
-{
-    return dx2es::GetGreenSize(getD3DFormat());
-}
-
-GLuint RenderbufferStorage::getBlueSize() const
+D3DFORMAT RenderbufferStorage::getD3DFormat() const
 {
-    return dx2es::GetBlueSize(getD3DFormat());
-}
-
-GLuint RenderbufferStorage::getAlphaSize() const
-{
-    return dx2es::GetAlphaSize(getD3DFormat());
-}
-
-GLuint RenderbufferStorage::getDepthSize() const
-{
-    return dx2es::GetDepthSize(getD3DFormat());
-}
-
-GLuint RenderbufferStorage::getStencilSize() const
-{
-    return dx2es::GetStencilSize(getD3DFormat());
+    return mD3DFormat;
 }
 
 GLsizei RenderbufferStorage::getSamples() const
 {
     return mSamples;
 }
 
-D3DFORMAT RenderbufferStorage::getD3DFormat() const
-{
-    return mD3DFormat;
-}
-
 unsigned int RenderbufferStorage::getSerial() const
 {
     return mSerial;
 }
 
 unsigned int RenderbufferStorage::issueSerial()
 {
     return mCurrentSerial++;
 }
 
-Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget), mTexture(NULL)
+unsigned int RenderbufferStorage::issueCubeSerials()
+{
+    unsigned int firstSerial = mCurrentSerial;
+    mCurrentSerial += 6;
+    return firstSerial;
+}
+
+Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
 {
     if (renderTarget)
     {
         renderTarget->AddRef();
 
         D3DSURFACE_DESC description;
         renderTarget->GetDesc(&description);
 
         mWidth = description.Width;
         mHeight = description.Height;
         mInternalFormat = dx2es::ConvertBackBufferFormat(description.Format);
         mD3DFormat = description.Format;
         mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType);
     }
 }
 
-Colorbuffer::Colorbuffer(Texture *texture, GLenum target) : mRenderTarget(NULL), mTexture(texture), mTarget(target)
-{
-    if (texture)
-    {
-        mWidth = texture->getWidth();
-        mHeight = texture->getHeight();
-        mInternalFormat = texture->getInternalFormat();
-        mD3DFormat = texture->getD3DFormat();
-        mSamples = 0;
-
-        mRenderTarget = texture->getRenderTarget(target);
-    }
-}
-
-Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL), mTexture(NULL)
+Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
 {
     IDirect3DDevice9 *device = getDevice();
 
     D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
     int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
 
     if (supportedSamples == -1)
     {
@@ -290,81 +310,21 @@ Colorbuffer::Colorbuffer(int width, int 
 Colorbuffer::~Colorbuffer()
 {
     if (mRenderTarget)
     {
         mRenderTarget->Release();
     }
 }
 
-GLsizei Colorbuffer::getWidth() const
-{
-    if (mTexture)
-    {
-        return mTexture->getWidth();
-    }
-
-    return mWidth;
-}
-
-GLsizei Colorbuffer::getHeight() const
-{
-    if (mTexture)
-    {
-        return mTexture->getHeight();
-    }
-
-    return mHeight;
-}
-
-GLenum Colorbuffer::getInternalFormat() const
-{
-    if (mTexture)
-    {
-        return mTexture->getInternalFormat();
-    }
-
-    return mInternalFormat;
-}
-
-GLenum Colorbuffer::getType() const
-{
-    if (mTexture)
-    {
-        return mTexture->getType();
-    }
-
-    return GL_UNSIGNED_BYTE;
-}
-
-D3DFORMAT Colorbuffer::getD3DFormat() const
-{
-    if (mTexture)
-    {
-        return mTexture->getD3DFormat();
-    }
-
-    return mD3DFormat;
-}
-
-bool Colorbuffer::isColorbuffer() const
-{
-    return true;
-}
-
 IDirect3DSurface9 *Colorbuffer::getRenderTarget()
 {
-    if (mTexture)
+    if (mRenderTarget)
     {
-        if (mRenderTarget)
-        {
-            mRenderTarget->Release();
-        }
-
-        mRenderTarget = mTexture->getRenderTarget(mTarget);
+        mRenderTarget->AddRef();
     }
 
     return mRenderTarget;
 }
 
 DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil)
 {
     if (depthStencil)
@@ -422,26 +382,16 @@ DepthStencilbuffer::DepthStencilbuffer(i
 DepthStencilbuffer::~DepthStencilbuffer()
 {
     if (mDepthStencil)
     {
         mDepthStencil->Release();
     }
 }
 
-bool DepthStencilbuffer::isDepthbuffer() const
-{
-    return true;
-}
-
-bool DepthStencilbuffer::isStencilbuffer() const
-{
-    return true;
-}
-
 IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
 {
     return mDepthStencil;
 }
 
 Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
 {
     if (depthStencil)
@@ -449,64 +399,45 @@ Depthbuffer::Depthbuffer(IDirect3DSurfac
         mInternalFormat = GL_DEPTH_COMPONENT16;   // If the renderbuffer parameters are queried, the calling function
                                                   // will expect one of the valid renderbuffer formats for use in 
                                                   // glRenderbufferStorage
     }
 }
 
 Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
 {
-    if (getDepthStencil())
+    if (mDepthStencil)
     {
         mInternalFormat = GL_DEPTH_COMPONENT16;   // If the renderbuffer parameters are queried, the calling function
                                                   // will expect one of the valid renderbuffer formats for use in 
                                                   // glRenderbufferStorage
     }
 }
 
 Depthbuffer::~Depthbuffer()
 {
 }
 
-bool Depthbuffer::isDepthbuffer() const
-{
-    return true;
-}
-
-bool Depthbuffer::isStencilbuffer() const
-{
-    return false;
-}
-
 Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
 {
     if (depthStencil)
     {
         mInternalFormat = GL_STENCIL_INDEX8;   // If the renderbuffer parameters are queried, the calling function
                                                // will expect one of the valid renderbuffer formats for use in 
                                                // glRenderbufferStorage
     }
 }
 
 Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
 {
-    if (getDepthStencil())
+    if (mDepthStencil)
     {
         mInternalFormat = GL_STENCIL_INDEX8;   // If the renderbuffer parameters are queried, the calling function
                                                // will expect one of the valid renderbuffer formats for use in 
                                                // glRenderbufferStorage
     }
 }
 
 Stencilbuffer::~Stencilbuffer()
 {
 }
 
-bool Stencilbuffer::isDepthbuffer() const
-{
-    return false;
 }
-
-bool Stencilbuffer::isStencilbuffer() const
-{
-    return true;
-}
-}
--- a/gfx/angle/src/libGLESv2/Renderbuffer.h
+++ b/gfx/angle/src/libGLESv2/Renderbuffer.h
@@ -17,79 +17,121 @@
 #include <d3d9.h>
 
 #include "common/angleutils.h"
 #include "libGLESv2/RefCountObject.h"
 
 namespace gl
 {
 class Texture;
+class Colorbuffer;
+class DepthStencilbuffer;
+
+class RenderbufferInterface
+{
+  public:
+    RenderbufferInterface();
+
+    virtual ~RenderbufferInterface() {};
+
+    virtual IDirect3DSurface9 *getRenderTarget() = 0;
+    virtual IDirect3DSurface9 *getDepthStencil() = 0;
+
+    virtual GLsizei getWidth() const = 0;
+    virtual GLsizei getHeight() const = 0;
+    virtual GLenum getInternalFormat() const = 0;
+    virtual D3DFORMAT getD3DFormat() const = 0;
+    virtual GLsizei getSamples() const = 0;
+
+    GLuint getRedSize() const;
+    GLuint getGreenSize() const;
+    GLuint getBlueSize() const;
+    GLuint getAlphaSize() const;
+    GLuint getDepthSize() const;
+    GLuint getStencilSize() const;
+
+    virtual unsigned int getSerial() const = 0;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface);
+};
+
+class RenderbufferTexture : public RenderbufferInterface
+{
+  public:
+    RenderbufferTexture(Texture *texture, GLenum target);
+
+    virtual ~RenderbufferTexture();
+
+    IDirect3DSurface9 *getRenderTarget();
+    IDirect3DSurface9 *getDepthStencil();
+
+    virtual GLsizei getWidth() const;
+    virtual GLsizei getHeight() const;
+    virtual GLenum getInternalFormat() const;
+    virtual D3DFORMAT getD3DFormat() const;
+    virtual GLsizei getSamples() const;
+
+    virtual unsigned int getSerial() const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture);
+
+    Texture *mTexture;
+    GLenum mTarget;
+};
 
 // A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
 // is called. The specific concrete type depends on whether the internal format is
 // colour depth, stencil or packed depth/stencil.
-class RenderbufferStorage
+class RenderbufferStorage : public RenderbufferInterface
 {
   public:
     RenderbufferStorage();
 
     virtual ~RenderbufferStorage() = 0;
 
-    virtual bool isColorbuffer() const;
-    virtual bool isDepthbuffer() const;
-    virtual bool isStencilbuffer() const;
-
     virtual IDirect3DSurface9 *getRenderTarget();
     virtual IDirect3DSurface9 *getDepthStencil();
 
     virtual GLsizei getWidth() const;
     virtual GLsizei getHeight() const;
     virtual GLenum getInternalFormat() const;
-    GLuint getRedSize() const;
-    GLuint getGreenSize() const;
-    GLuint getBlueSize() const;
-    GLuint getAlphaSize() const;
-    GLuint getDepthSize() const;
-    GLuint getStencilSize() const;
+    virtual D3DFORMAT getD3DFormat() const;
     virtual GLsizei getSamples() const;
 
-    virtual D3DFORMAT getD3DFormat() const;
+    virtual unsigned int getSerial() const;
 
-    unsigned int getSerial() const;
+    static unsigned int issueSerial();
+    static unsigned int issueCubeSerials();
 
   protected:
     GLsizei mWidth;
     GLsizei mHeight;
     GLenum mInternalFormat;
     D3DFORMAT mD3DFormat;
     GLsizei mSamples;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
 
-    static unsigned int issueSerial();
-
     const unsigned int mSerial;
 
     static unsigned int mCurrentSerial;
 };
 
 // Renderbuffer implements the GL renderbuffer object.
-// It's only a proxy for a RenderbufferStorage instance; the internal object
+// It's only a proxy for a RenderbufferInterface instance; the internal object
 // can change whenever glRenderbufferStorage is called.
 class Renderbuffer : public RefCountObject
 {
   public:
-    Renderbuffer(GLuint id, RenderbufferStorage *storage);
-
-    ~Renderbuffer();
+    Renderbuffer(GLuint id, RenderbufferInterface *storage);
 
-    bool isColorbuffer() const;
-    bool isDepthbuffer() const;
-    bool isStencilbuffer() const;
+    virtual ~Renderbuffer();
 
     IDirect3DSurface9 *getRenderTarget();
     IDirect3DSurface9 *getDepthStencil();
 
     GLsizei getWidth() const;
     GLsizei getHeight() const;
     GLenum getInternalFormat() const;
     D3DFORMAT getD3DFormat() const;
@@ -99,94 +141,74 @@ class Renderbuffer : public RefCountObje
     GLuint getAlphaSize() const;
     GLuint getDepthSize() const;
     GLuint getStencilSize() const;
     GLsizei getSamples() const;
 
     unsigned int getSerial() const;
 
     void setStorage(RenderbufferStorage *newStorage);
-    RenderbufferStorage *getStorage() { return mStorage; }
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
 
-    RenderbufferStorage *mStorage;
+    RenderbufferInterface *mInstance;
 };
 
 class Colorbuffer : public RenderbufferStorage
 {
   public:
     explicit Colorbuffer(IDirect3DSurface9 *renderTarget);
-    Colorbuffer(Texture *texture, GLenum target);
     Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples);
 
     virtual ~Colorbuffer();
 
-    virtual bool isColorbuffer() const;
-
     virtual IDirect3DSurface9 *getRenderTarget();
 
-    virtual GLsizei getWidth() const;
-    virtual GLsizei getHeight() const;
-    virtual GLenum getInternalFormat() const;
-    virtual GLenum getType() const;
-
-    virtual D3DFORMAT getD3DFormat() const;
-
   private:
     DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
 
     IDirect3DSurface9 *mRenderTarget;
-    Texture *mTexture;
-    GLenum mTarget;
 };
 
 class DepthStencilbuffer : public RenderbufferStorage
 {
   public:
     explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil);
     DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
 
     ~DepthStencilbuffer();
 
-    virtual bool isDepthbuffer() const;
-    virtual bool isStencilbuffer() const;
+    virtual IDirect3DSurface9 *getDepthStencil();
 
-    virtual IDirect3DSurface9 *getDepthStencil();
+  protected:
+    IDirect3DSurface9 *mDepthStencil;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
-    IDirect3DSurface9 *mDepthStencil;
 };
 
 class Depthbuffer : public DepthStencilbuffer
 {
   public:
     explicit Depthbuffer(IDirect3DSurface9 *depthStencil);
     Depthbuffer(GLsizei width, GLsizei height, GLsizei samples);
 
     virtual ~Depthbuffer();
 
-    virtual bool isDepthbuffer() const;
-    virtual bool isStencilbuffer() const;
-
   private:
     DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
 };
 
 class Stencilbuffer : public DepthStencilbuffer
 {
   public:
     explicit Stencilbuffer(IDirect3DSurface9 *depthStencil);
     Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
 
     virtual ~Stencilbuffer();
 
-    virtual bool isDepthbuffer() const;
-    virtual bool isStencilbuffer() const;
-
   private:
     DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
 };
 }
 
 #endif   // LIBGLESV2_RENDERBUFFER_H_
--- a/gfx/angle/src/libGLESv2/Texture.cpp
+++ b/gfx/angle/src/libGLESv2/Texture.cpp
@@ -28,32 +28,141 @@
 #include "libGLESv2/main.h"
 #include "libGLESv2/mathutil.h"
 #include "libGLESv2/utilities.h"
 #include "libGLESv2/Blit.h"
 #include "libGLESv2/Framebuffer.h"
 
 namespace gl
 {
-unsigned int Texture::mCurrentSerial = 1;
-
-Texture::Image::Image()
-  : width(0), height(0), dirty(false), surface(NULL), format(GL_NONE), type(GL_UNSIGNED_BYTE)
+unsigned int TextureStorage::mCurrentTextureSerial = 1;
+
+Image::Image()
 {
+    mWidth = 0; 
+    mHeight = 0;
+    mFormat = GL_NONE;
+    mType = GL_UNSIGNED_BYTE;
+
+    mSurface = NULL;
+
+    mDirty = false;
+    mManaged = false;
 }
 
-Texture::Image::~Image()
+Image::~Image()
 {
-    if (surface)
+    if (mSurface)
     {
-        surface->Release();
+        mSurface->Release();
     }
 }
 
-bool Texture::Image::isRenderable() const
+bool Image::redefine(GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRelease)
+{
+    if (mWidth != width ||
+        mHeight != height ||
+        mFormat != format ||
+        mType != type ||
+        forceRelease)
+    {
+        mWidth = width;
+        mHeight = height;
+        mFormat = format;
+        mType = type;
+
+        if (mSurface)
+        {
+            mSurface->Release();
+            mSurface = NULL;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+void Image::createSurface()
+{
+    if(mSurface)
+    {
+        return;
+    }
+
+    IDirect3DTexture9 *newTexture = NULL;
+    IDirect3DSurface9 *newSurface = NULL;
+
+    if (mWidth != 0 && mHeight != 0)
+    {
+        int levelToFetch = 0;
+        GLsizei requestWidth = mWidth;
+        GLsizei requestHeight = mHeight;
+        if (IsCompressed(mFormat) && (mWidth % 4 != 0 || mHeight % 4 != 0))
+        {
+            bool isMult4 = false;
+            int upsampleCount = 0;
+            while (!isMult4)
+            {
+                requestWidth <<= 1;
+                requestHeight <<= 1;
+                upsampleCount++;
+                if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
+                {
+                    isMult4 = true;
+                }
+            }
+            levelToFetch = upsampleCount;
+        }
+
+        HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, getD3DFormat(),
+                                                    D3DPOOL_SYSTEMMEM, &newTexture, NULL);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            ERR("Creating image surface failed.");
+            return error(GL_OUT_OF_MEMORY);
+        }
+
+        newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
+        newTexture->Release();
+    }
+
+    mSurface = newSurface;
+    mDirty = false;
+}
+
+HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
+{
+    createSurface();
+
+    HRESULT result = D3DERR_INVALIDCALL;
+
+    if (mSurface)
+    {
+        result = mSurface->LockRect(lockedRect, rect, 0);
+        ASSERT(SUCCEEDED(result));
+
+        mDirty = true;
+    }
+
+    return result;
+}
+
+void Image::unlock()
+{
+    if (mSurface)
+    {
+        HRESULT result = mSurface->UnlockRect();
+        ASSERT(SUCCEEDED(result));
+    }
+}
+
+bool Image::isRenderable() const
 {    
     switch(getD3DFormat())
     {
       case D3DFMT_L8:
       case D3DFMT_A8L8:
       case D3DFMT_DXT1:
       case D3DFMT_DXT3:
       case D3DFMT_DXT5:
@@ -65,307 +174,219 @@ bool Texture::Image::isRenderable() cons
         return true;
       default:
         UNREACHABLE();
     }
 
     return false;
 }
 
-D3DFORMAT Texture::Image::getD3DFormat() const
+D3DFORMAT Image::getD3DFormat() const
 {
-    if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
-        format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+    if (mFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+        mFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
     {
         return D3DFMT_DXT1;
     }
-    else if (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
+    else if (mFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
     {
         return D3DFMT_DXT3;
     }
-    else if (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
+    else if (mFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
     {
         return D3DFMT_DXT5;
     }
-    else if (type == GL_FLOAT)
+    else if (mType == GL_FLOAT)
     {
         return D3DFMT_A32B32G32R32F;
     }
-    else if (type == GL_HALF_FLOAT_OES)
+    else if (mType == GL_HALF_FLOAT_OES)
     {
         return D3DFMT_A16B16G16R16F;
     }
-    else if (type == GL_UNSIGNED_BYTE)
+    else if (mType == GL_UNSIGNED_BYTE)
     {
-        if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
+        if (mFormat == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
         {
             return D3DFMT_L8;
         }
-        else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
+        else if (mFormat == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
         {
             return D3DFMT_A8L8;
         }
-        else if (format == GL_RGB)
+        else if (mFormat == GL_RGB)
         {
             return D3DFMT_X8R8G8B8;
         }
 
         return D3DFMT_A8R8G8B8;
     }
 
     return D3DFMT_A8R8G8B8;
 }
 
-Texture::Texture(GLuint id) : RefCountObject(id), mSerial(issueSerial())
+IDirect3DSurface9 *Image::getSurface()
 {
-    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
-    mMagFilter = GL_LINEAR;
-    mWrapS = GL_REPEAT;
-    mWrapT = GL_REPEAT;
-    mDirtyParameter = true;
-    
-    mDirtyImage = true;
-    
-    mIsRenderable = false;
+    createSurface();
+
+    return mSurface;
 }
 
-Texture::~Texture()
-{
-}
-
-Blit *Texture::getBlitter()
+void Image::setManagedSurface(IDirect3DSurface9 *surface)
 {
-    Context *context = getContext();
-    return context->getBlitter();
-}
-
-// Returns true on successful filter state update (valid enum parameter)
-bool Texture::setMinFilter(GLenum filter)
-{
-    switch (filter)
+    if (mSurface)
     {
-      case GL_NEAREST:
-      case GL_LINEAR:
-      case GL_NEAREST_MIPMAP_NEAREST:
-      case GL_LINEAR_MIPMAP_NEAREST:
-      case GL_NEAREST_MIPMAP_LINEAR:
-      case GL_LINEAR_MIPMAP_LINEAR:
-        {
-            if (mMinFilter != filter)
-            {
-                mMinFilter = filter;
-                mDirtyParameter = true;
-            }
-            return true;
-        }
-      default:
-        return false;
+        D3DXLoadSurfaceFromSurface(surface, NULL, NULL, mSurface, NULL, NULL, D3DX_FILTER_BOX, 0);
+        mSurface->Release();
     }
+
+    mSurface = surface;
+    mManaged = true;
 }
 
-// Returns true on successful filter state update (valid enum parameter)
-bool Texture::setMagFilter(GLenum filter)
+void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
 {
-    switch (filter)
+    IDirect3DSurface9 *sourceSurface = getSurface();
+
+    if (sourceSurface != destSurface)
     {
-      case GL_NEAREST:
-      case GL_LINEAR:
+        RECT rect = transformPixelRect(xoffset, yoffset, width, height, mHeight);
+
+        if (mManaged)
         {
-            if (mMagFilter != filter)
-            {
-                mMagFilter = filter;
-                mDirtyParameter = true;
-            }
-            return true;
+            HRESULT result = D3DXLoadSurfaceFromSurface(destSurface, NULL, &rect, sourceSurface, NULL, &rect, D3DX_FILTER_BOX, 0);
+            ASSERT(SUCCEEDED(result));
         }
-      default:
-        return false;
-    }
-}
-
-// Returns true on successful wrap state update (valid enum parameter)
-bool Texture::setWrapS(GLenum wrap)
-{
-    switch (wrap)
-    {
-      case GL_REPEAT:
-      case GL_CLAMP_TO_EDGE:
-      case GL_MIRRORED_REPEAT:
+        else
         {
-            if (mWrapS != wrap)
-            {
-                mWrapS = wrap;
-                mDirtyParameter = true;
-            }
-            return true;
+            POINT point = {rect.left, rect.top};
+            HRESULT result = getDevice()->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+            ASSERT(SUCCEEDED(result));
         }
-      default:
-        return false;
     }
 }
 
-// Returns true on successful wrap state update (valid enum parameter)
-bool Texture::setWrapT(GLenum wrap)
-{
-    switch (wrap)
-    {
-      case GL_REPEAT:
-      case GL_CLAMP_TO_EDGE:
-      case GL_MIRRORED_REPEAT:
-        {
-            if (mWrapT != wrap)
-            {
-                mWrapT = wrap;
-                mDirtyParameter = true;
-            }
-            return true;
-        }
-      default:
-        return false;
-    }
-}
-
-GLenum Texture::getMinFilter() const
-{
-    return mMinFilter;
-}
-
-GLenum Texture::getMagFilter() const
-{
-    return mMagFilter;
-}
-
-GLenum Texture::getWrapS() const
-{
-    return mWrapS;
-}
-
-GLenum Texture::getWrapT() const
-{
-    return mWrapT;
-}
-
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
 // into the target pixel rectangle at output with outputPitch bytes in between each line.
-void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
-                            GLint unpackAlignment, const void *input, size_t outputPitch, void *output, D3DSURFACE_DESC *description) const
+void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum type,
+                     GLint unpackAlignment, const void *input, size_t outputPitch, void *output) const
 {
-    GLsizei inputPitch = -ComputePitch(width, format, type, unpackAlignment);
+    GLsizei inputPitch = -ComputePitch(width, mFormat, type, unpackAlignment);
     input = ((char*)input) - inputPitch * (height - 1);
 
     switch (type)
     {
       case GL_UNSIGNED_BYTE:
-        switch (format)
+        switch (mFormat)
         {
           case GL_ALPHA:
-            loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadAlphaData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_LUMINANCE:
-            loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_L8);
+            loadLuminanceData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, getD3DFormat() == D3DFMT_L8);
             break;
           case GL_LUMINANCE_ALPHA:
-            loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_A8L8);
+            loadLuminanceAlphaData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, getD3DFormat() == D3DFMT_A8L8);
             break;
           case GL_RGB:
-            loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadRGBUByteData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_RGBA:
             if (supportsSSE2())
             {
-                loadRGBAUByteImageDataSSE2(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+                loadRGBAUByteDataSSE2(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             }
             else
             {
-                loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+                loadRGBAUByteData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             }
             break;
           case GL_BGRA_EXT:
-            loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadBGRAData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           default: UNREACHABLE();
         }
         break;
       case GL_UNSIGNED_SHORT_5_6_5:
-        switch (format)
+        switch (mFormat)
         {
           case GL_RGB:
-            loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadRGB565Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           default: UNREACHABLE();
         }
         break;
       case GL_UNSIGNED_SHORT_4_4_4_4:
-        switch (format)
+        switch (mFormat)
         {
           case GL_RGBA:
-            loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadRGBA4444Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           default: UNREACHABLE();
         }
         break;
       case GL_UNSIGNED_SHORT_5_5_5_1:
-        switch (format)
+        switch (mFormat)
         {
           case GL_RGBA:
-            loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadRGBA5551Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           default: UNREACHABLE();
         }
         break;
       case GL_FLOAT:
-        switch (format)
+        switch (mFormat)
         {
           // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
           case GL_ALPHA:
-            loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadAlphaFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_LUMINANCE:
-            loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadLuminanceFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_LUMINANCE_ALPHA:
-            loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadLuminanceAlphaFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_RGB:
-            loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadRGBFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_RGBA:
-            loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadRGBAFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           default: UNREACHABLE();
         }
         break;
       case GL_HALF_FLOAT_OES:
-        switch (format)
+        switch (mFormat)
         {
           // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
           case GL_ALPHA:
-            loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadAlphaHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_LUMINANCE:
-            loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadLuminanceHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_LUMINANCE_ALPHA:
-            loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadLuminanceAlphaHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_RGB:
-            loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadRGBHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_RGBA:
-            loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            loadRGBAHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           default: UNREACHABLE();
         }
         break;
       default: UNREACHABLE();
     }
 }
 
-void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                 int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
     
     for (int y = 0; y < height; y++)
     {
         source = static_cast<const unsigned char*>(input) + y * inputPitch;
         dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
@@ -374,18 +395,18 @@ void Texture::loadAlphaImageData(GLint x
             dest[4 * x + 0] = 0;
             dest[4 * x + 1] = 0;
             dest[4 * x + 2] = 0;
             dest[4 * x + 3] = source[x];
         }
     }
 }
 
-void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                      int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                               int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const float *source = NULL;
     float *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch  + xoffset * 16);
@@ -394,18 +415,18 @@ void Texture::loadAlphaFloatImageData(GL
             dest[4 * x + 0] = 0;
             dest[4 * x + 1] = 0;
             dest[4 * x + 2] = 0;
             dest[4 * x + 3] = source[x];
         }
     }
 }
 
-void Texture::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                          int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                   int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned short *source = NULL;
     unsigned short *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
@@ -414,18 +435,18 @@ void Texture::loadAlphaHalfFloatImageDat
             dest[4 * x + 0] = 0;
             dest[4 * x + 1] = 0;
             dest[4 * x + 2] = 0;
             dest[4 * x + 3] = source[x];
         }
     }
 }
 
-void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
+void Image::loadLuminanceData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
 {
     const int destBytesPerPixel = native? 1: 4;
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = static_cast<const unsigned char*>(input) + y * inputPitch;
@@ -443,18 +464,18 @@ void Texture::loadLuminanceImageData(GLi
         }
         else   // L8 destination format
         {
             memcpy(dest, source, width);
         }
     }
 }
 
-void Texture::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                          int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadLuminanceFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                   int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const float *source = NULL;
     float *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch  + xoffset * 16);
@@ -463,18 +484,18 @@ void Texture::loadLuminanceFloatImageDat
             dest[4 * x + 0] = source[x];
             dest[4 * x + 1] = source[x];
             dest[4 * x + 2] = source[x];
             dest[4 * x + 3] = 1.0f;
         }
     }
 }
 
-void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                                   int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadLuminanceHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                       int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned short *source = NULL;
     unsigned short *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
@@ -483,18 +504,18 @@ void Texture::loadLuminanceHalfFloatImag
             dest[4 * x + 0] = source[x];
             dest[4 * x + 1] = source[x];
             dest[4 * x + 2] = source[x];
             dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
         }
     }
 }
 
-void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                          int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
+void Image::loadLuminanceAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                   int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
 {
     const int destBytesPerPixel = native? 2: 4;
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = static_cast<const unsigned char*>(input) + y * inputPitch;
@@ -512,18 +533,18 @@ void Texture::loadLuminanceAlphaImageDat
         }
         else
         {
             memcpy(dest, source, width * 2);
         }
     }
 }
 
-void Texture::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                               int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadLuminanceAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                        int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const float *source = NULL;
     float *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch  + xoffset * 16);
@@ -532,18 +553,18 @@ void Texture::loadLuminanceAlphaFloatIma
             dest[4 * x + 0] = source[2*x+0];
             dest[4 * x + 1] = source[2*x+0];
             dest[4 * x + 2] = source[2*x+0];
             dest[4 * x + 3] = source[2*x+1];
         }
     }
 }
 
-void Texture::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                                   int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadLuminanceAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                            int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned short *source = NULL;
     unsigned short *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
@@ -552,18 +573,18 @@ void Texture::loadLuminanceAlphaHalfFloa
             dest[4 * x + 0] = source[2*x+0];
             dest[4 * x + 1] = source[2*x+0];
             dest[4 * x + 2] = source[2*x+0];
             dest[4 * x + 3] = source[2*x+1];
         }
     }
 }
 
-void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                             int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = static_cast<const unsigned char*>(input) + y * inputPitch;
         dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
@@ -572,18 +593,18 @@ void Texture::loadRGBUByteImageData(GLin
             dest[4 * x + 0] = source[x * 3 + 2];
             dest[4 * x + 1] = source[x * 3 + 1];
             dest[4 * x + 2] = source[x * 3 + 0];
             dest[4 * x + 3] = 0xFF;
         }
     }
 }
 
-void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                  int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGB565Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned short *source = NULL;
     unsigned char *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
@@ -593,18 +614,18 @@ void Texture::loadRGB565ImageData(GLint 
             dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
             dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
             dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
             dest[4 * x + 3] = 0xFF;
         }
     }
 }
 
-void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                             int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const float *source = NULL;
     float *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch  + xoffset * 16);
@@ -613,18 +634,18 @@ void Texture::loadRGBFloatImageData(GLin
             dest[4 * x + 0] = source[x * 3 + 0];
             dest[4 * x + 1] = source[x * 3 + 1];
             dest[4 * x + 2] = source[x * 3 + 2];
             dest[4 * x + 3] = 1.0f;
         }
     }
 }
 
-void Texture::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                 int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned short *source = NULL;
     unsigned short *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch  + xoffset * 8);
@@ -633,18 +654,18 @@ void Texture::loadRGBHalfFloatImageData(
             dest[4 * x + 0] = source[x * 3 + 0];
             dest[4 * x + 1] = source[x * 3 + 1];
             dest[4 * x + 2] = source[x * 3 + 2];
             dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
         }
     }
 }
 
-void Texture::loadRGBAUByteImageDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBAUByteDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                  int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned int *source = NULL;
     unsigned int *dest = NULL;
     __m128i brMask = _mm_set1_epi32(0x00ff00ff);
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
@@ -675,36 +696,36 @@ void Texture::loadRGBAUByteImageDataSSE2
         for (; x < width; x++)
         {
             unsigned int rgba = source[x];
             dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
         }
     }
 }
 
-void Texture::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBAUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned int *source = NULL;
     unsigned int *dest = NULL;
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
 
         for (int x = 0; x < width; x++)
         {
             unsigned int rgba = source[x];
             dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
         }
     }
 }
 
-void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBA4444Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                             int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned short *source = NULL;
     unsigned char *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
@@ -714,18 +735,18 @@ void Texture::loadRGBA4444ImageData(GLin
             dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
             dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
             dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
             dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
         }
     }
 }
 
-void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBA5551Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                             int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned short *source = NULL;
     unsigned char *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
@@ -735,70 +756,70 @@ void Texture::loadRGBA5551ImageData(GLin
             dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
             dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
             dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
             dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
         }
     }
 }
 
-void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBAFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const float *source = NULL;
     float *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
         dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch  + xoffset * 16);
         memcpy(dest, source, width * 16);
     }
 }
 
-void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBAHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                  int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = static_cast<const unsigned char*>(input) + y * inputPitch;
         dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch  + xoffset * 8;
         memcpy(dest, source, width * 8);
     }
 }
 
-void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadBGRAData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                         int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
         source = static_cast<const unsigned char*>(input) + y * inputPitch;
         dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
         memcpy(dest, source, width*4);
     }
 }
 
-void Texture::loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                      int inputPitch, const void *input, size_t outputPitch, void *output) const {
+void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                               int inputPitch, const void *input, size_t outputPitch, void *output) const {
     switch (getD3DFormat())
     {
         case D3DFMT_DXT1:
-          loadDXT1ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+          loadDXT1Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
           break;
         case D3DFMT_DXT3:
-          loadDXT3ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+          loadDXT3Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
           break;
         case D3DFMT_DXT5:
-          loadDXT5ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+          loadDXT5Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
           break;
     }
 }
 
 static void FlipCopyDXT1BlockFull(const unsigned int* source, unsigned int* dest) {
   // A DXT1 block layout is:
   // [0-1] color0.
   // [2-3] color1.
@@ -903,18 +924,18 @@ static void FlipCopyDXT5BlockHalf(const 
   destBytes[0] = sourceBytes[0];
   destBytes[1] = sourceBytes[1];
   destBytes[2] = line_1_0 & 0xff;
   destBytes[3] = (line_1_0 & 0xff00) >> 8;
   destBytes[4] = (line_1_0 & 0xff0000) >> 16;
   FlipCopyDXT1BlockHalf(source + 2, dest + 2);
 }
 
-void Texture::loadDXT1ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                      int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadDXT1Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                         int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     ASSERT(xoffset % 4 == 0);
     ASSERT(yoffset % 4 == 0);
     ASSERT(width % 4 == 0 || width == 2 || width == 1);
     ASSERT(inputPitch % 8 == 0);
     ASSERT(outputPitch % 8 == 0);
 
     const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
@@ -951,18 +972,18 @@ void Texture::loadDXT1ImageData(GLint xo
                 {
                     FlipCopyDXT1BlockFull(source + x, dest + x);
                 }
             }
             break;
     }
 }
 
-void Texture::loadDXT3ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadDXT3Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                         int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     ASSERT(xoffset % 4 == 0);
     ASSERT(yoffset % 4 == 0);
     ASSERT(width % 4 == 0 || width == 2 || width == 1);
     ASSERT(inputPitch % 16 == 0);
     ASSERT(outputPitch % 16 == 0);
 
     const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
@@ -1001,18 +1022,18 @@ void Texture::loadDXT3ImageData(GLint xo
                 {
                   FlipCopyDXT3BlockFull(source + x, dest + x);
                 }
             }
             break;
     }
 }
 
-void Texture::loadDXT5ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                int inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadDXT5Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                         int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     ASSERT(xoffset % 4 == 0);
     ASSERT(yoffset % 4 == 0);
     ASSERT(width % 4 == 0 || width == 2 || width == 1);
     ASSERT(inputPitch % 16 == 0);
     ASSERT(outputPitch % 16 == 0);
 
     const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
@@ -1051,222 +1072,19 @@ void Texture::loadDXT5ImageData(GLint xo
                 {
                     FlipCopyDXT5BlockFull(source + x, dest + x);
                 }
             }
             break;
     }
 }
 
-void Texture::createSurface(Image *image)
-{
-    IDirect3DTexture9 *newTexture = NULL;
-    IDirect3DSurface9 *newSurface = NULL;
-
-    if (image->width != 0 && image->height != 0)
-    {
-        int levelToFetch = 0;
-        GLsizei requestWidth = image->width;
-        GLsizei requestHeight = image->height;
-        if (IsCompressed(image->format) && (image->width % 4 != 0 || image->height % 4 != 0))
-        {
-            bool isMult4 = false;
-            int upsampleCount = 0;
-            while (!isMult4)
-            {
-                requestWidth <<= 1;
-                requestHeight <<= 1;
-                upsampleCount++;
-                if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
-                {
-                    isMult4 = true;
-                }
-            }
-            levelToFetch = upsampleCount;
-        }
-
-        HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, image->getD3DFormat(),
-                                                    D3DPOOL_SYSTEMMEM, &newTexture, NULL);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            return error(GL_OUT_OF_MEMORY);
-        }
-
-        newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
-        newTexture->Release();
-    }
-
-    if (image->surface)
-    {
-        image->surface->Release();
-    }
-
-    image->surface = newSurface;
-}
-
-void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image)
-{
-    createSurface(image);
-
-    if (pixels != NULL && image->surface != NULL)
-    {
-        D3DSURFACE_DESC description;
-        image->surface->GetDesc(&description);
-
-        D3DLOCKED_RECT locked;
-        HRESULT result = image->surface->LockRect(&locked, NULL, 0);
-
-        ASSERT(SUCCEEDED(result));
-
-        if (SUCCEEDED(result))
-        {
-            loadImageData(0, 0, image->width, image->height, image->format, image->type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
-            image->surface->UnlockRect();
-        }
-
-        image->dirty = true;
-        mDirtyImage = true;
-    }
-}
-
-void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
-{
-    createSurface(image);
-
-    if (pixels != NULL && image->surface != NULL)
-    {
-        D3DLOCKED_RECT locked;
-        HRESULT result = image->surface->LockRect(&locked, NULL, 0);
-
-        ASSERT(SUCCEEDED(result));
-
-        if (SUCCEEDED(result))
-        {
-            int inputPitch = ComputeCompressedPitch(image->width, image->format);
-            int inputSize = ComputeCompressedSize(image->width, image->height, image->format);
-            loadCompressedImageData(0, 0, image->width, image->height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
-            image->surface->UnlockRect();
-        }
-
-        image->dirty = true;
-        mDirtyImage = true;
-    }
-}
-
-bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image)
+// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
+void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
 {
-    if (width + xoffset > image->width || height + yoffset > image->height)
-    {
-        error(GL_INVALID_VALUE);
-        return false;
-    }
-
-    if (IsCompressed(image->format))
-    {
-        error(GL_INVALID_OPERATION);
-        return false;
-    }
-
-    if (format != image->format)
-    {
-        error(GL_INVALID_OPERATION);
-        return false;
-    }
-
-    if (!image->surface)
-    {
-        createSurface(image);
-    }
-
-    if (pixels != NULL && image->surface != NULL)
-    {
-        D3DSURFACE_DESC description;
-        image->surface->GetDesc(&description);
-
-        D3DLOCKED_RECT locked;
-        HRESULT result = image->surface->LockRect(&locked, NULL, 0);
-
-        ASSERT(SUCCEEDED(result));
-
-        if (SUCCEEDED(result))
-        {
-            loadImageData(xoffset, transformPixelYOffset(yoffset, height, image->height), width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
-            image->surface->UnlockRect();
-        }
-
-        image->dirty = true;
-        mDirtyImage = true;
-    }
-
-    return true;
-}
-
-bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image)
-{
-    if (width + xoffset > image->width || height + yoffset > image->height)
-    {
-        error(GL_INVALID_VALUE);
-        return false;
-    }
-
-    if (format != getInternalFormat())
-    {
-        error(GL_INVALID_OPERATION);
-        return false;
-    }
-
-    if (!image->surface)
-    {
-        createSurface(image);
-    }
-
-    if (pixels != NULL && image->surface != NULL)
-    {
-        RECT updateRegion;
-        updateRegion.left = xoffset;
-        updateRegion.right = xoffset + width;
-        updateRegion.bottom = yoffset + height;
-        updateRegion.top = yoffset;
-
-        D3DLOCKED_RECT locked;
-        HRESULT result = image->surface->LockRect(&locked, &updateRegion, 0);
-
-        ASSERT(SUCCEEDED(result));
-
-        if (SUCCEEDED(result))
-        {
-            int inputPitch = ComputeCompressedPitch(width, format);
-            int inputSize = ComputeCompressedSize(width, height, format);
-            loadCompressedImageData(xoffset, transformPixelYOffset(yoffset, height, image->height), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
-            image->surface->UnlockRect();
-        }
-
-        image->dirty = true;
-        mDirtyImage = true;
-    }
-
-    return true;
-}
-
-// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
-void Texture::copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
-{
-    if (!image->surface)
-    {
-        createSurface(image);
-
-        if (!image->surface)
-        {
-            ERR("Failed to create an image surface.");
-            return error(GL_OUT_OF_MEMORY);
-        }
-    }
-
     IDirect3DDevice9 *device = getDevice();
     IDirect3DSurface9 *renderTargetData = NULL;
     D3DSURFACE_DESC description;
     renderTarget->GetDesc(&description);
     
     HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
 
     if (FAILED(result))
@@ -1280,22 +1098,22 @@ void Texture::copyToImage(Image *image, 
     if (FAILED(result))
     {
         ERR("GetRenderTargetData unexpectedly failed.");
         renderTargetData->Release();
         return error(GL_OUT_OF_MEMORY);
     }
 
     RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);
-    int destYOffset = transformPixelYOffset(yoffset, height, image->height);
+    int destYOffset = transformPixelYOffset(yoffset, height, mHeight);
     RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};
 
-    if (image->isRenderable())
+    if (isRenderable())
     {
-        result = D3DXLoadSurfaceFromSurface(image->surface, NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0);
+        result = D3DXLoadSurfaceFromSurface(getSurface(), NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0);
         
         if (FAILED(result))
         {
             ERR("Copying surfaces unexpectedly failed.");
             renderTargetData->Release();
             return error(GL_OUT_OF_MEMORY);
         }
     }
@@ -1307,17 +1125,17 @@ void Texture::copyToImage(Image *image, 
         if (FAILED(result))
         {
             ERR("Failed to lock the source surface (rectangle might be invalid).");
             renderTargetData->Release();
             return error(GL_OUT_OF_MEMORY);
         }
 
         D3DLOCKED_RECT destLock = {0};
-        result = image->surface->LockRect(&destLock, &destRect, 0);
+        result = lock(&destLock, &destRect);
         
         if (FAILED(result))
         {
             ERR("Failed to lock the destination surface (rectangle might be invalid).");
             renderTargetData->UnlockRect();
             renderTargetData->Release();
             return error(GL_OUT_OF_MEMORY);
         }
@@ -1326,17 +1144,17 @@ void Texture::copyToImage(Image *image, 
         {
             unsigned char *source = (unsigned char*)sourceLock.pBits;
             unsigned char *dest = (unsigned char*)destLock.pBits;
 
             switch (description.Format)
             {
               case D3DFMT_X8R8G8B8:
               case D3DFMT_A8R8G8B8:
-                switch(image->getD3DFormat())
+                switch(getD3DFormat())
                 {
                   case D3DFMT_L8:
                     for(int y = 0; y < height; y++)
                     {
                         for(int x = 0; x < width; x++)
                         {
                             dest[x] = source[x * 4 + 2];
                         }
@@ -1358,17 +1176,17 @@ void Texture::copyToImage(Image *image, 
                         dest += destLock.Pitch;
                     }
                     break;
                   default:
                     UNREACHABLE();
                 }
                 break;
               case D3DFMT_R5G6B5:
-                switch(image->getD3DFormat())
+                switch(getD3DFormat())
                 {
                   case D3DFMT_L8:
                     for(int y = 0; y < height; y++)
                     {
                         for(int x = 0; x < width; x++)
                         {
                             unsigned char red = source[x * 2 + 1] & 0xF8;
                             dest[x] = red | (red >> 5);
@@ -1378,17 +1196,17 @@ void Texture::copyToImage(Image *image, 
                         dest += destLock.Pitch;
                     }
                     break;
                   default:
                     UNREACHABLE();
                 }
                 break;
               case D3DFMT_A1R5G5B5:
-                switch(image->getD3DFormat())
+                switch(getD3DFormat())
                 {
                   case D3DFMT_L8:
                     for(int y = 0; y < height; y++)
                     {
                         for(int x = 0; x < width; x++)
                         {
                             unsigned char red = source[x * 2 + 1] & 0x7C;
                             dest[x] = (red << 1) | (red >> 4);
@@ -1416,270 +1234,612 @@ void Texture::copyToImage(Image *image, 
                     UNREACHABLE();
                 }
                 break;
               default:
                 UNREACHABLE();
             }
         }
 
-        image->surface->UnlockRect();
+        unlock();
         renderTargetData->UnlockRect();
     }
 
     renderTargetData->Release();
 
-    image->dirty = true;
-    mDirtyImage = true;
+    mDirty = true;
+}
+
+TextureStorage::TextureStorage(bool renderable)
+    : mRenderable(renderable), mManaged(getDisplay()->getBufferPool(renderable) == D3DPOOL_MANAGED), mTextureSerial(issueTextureSerial())
+{
+}
+
+TextureStorage::~TextureStorage()
+{
+}
+
+bool TextureStorage::isRenderable() const
+{
+    return mRenderable;
+}
+
+bool TextureStorage::isManaged() const
+{
+    return mManaged;
+}
+
+unsigned int TextureStorage::getTextureSerial() const
+{
+    return mTextureSerial;
+}
+
+unsigned int TextureStorage::issueTextureSerial()
+{
+    return mCurrentTextureSerial++;
+}
+
+Texture::Texture(GLuint id) : RefCountObject(id)
+{
+    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
+    mMagFilter = GL_LINEAR;
+    mWrapS = GL_REPEAT;
+    mWrapT = GL_REPEAT;
+    mDirtyParameters = true;
+    mUsage = GL_NONE;
+    
+    mDirtyImages = true;
+
+    mImmutable = false;
+}
+
+Texture::~Texture()
+{
+}
+
+// Returns true on successful filter state update (valid enum parameter)
+bool Texture::setMinFilter(GLenum filter)
+{
+    switch (filter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+      case GL_NEAREST_MIPMAP_NEAREST:
+      case GL_LINEAR_MIPMAP_NEAREST:
+      case GL_NEAREST_MIPMAP_LINEAR:
+      case GL_LINEAR_MIPMAP_LINEAR:
+        {
+            if (mMinFilter != filter)
+            {
+                mMinFilter = filter;
+                mDirtyParameters = true;
+            }
+            return true;
+        }
+      default:
+        return false;
+    }
+}
+
+// Returns true on successful filter state update (valid enum parameter)
+bool Texture::setMagFilter(GLenum filter)
+{
+    switch (filter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+        {
+            if (mMagFilter != filter)
+            {
+                mMagFilter = filter;
+                mDirtyParameters = true;
+            }
+            return true;
+        }
+      default:
+        return false;
+    }
+}
+
+// Returns true on successful wrap state update (valid enum parameter)
+bool Texture::setWrapS(GLenum wrap)
+{
+    switch (wrap)
+    {
+      case GL_REPEAT:
+      case GL_CLAMP_TO_EDGE:
+      case GL_MIRRORED_REPEAT:
+        {
+            if (mWrapS != wrap)
+            {
+                mWrapS = wrap;
+                mDirtyParameters = true;
+            }
+            return true;
+        }
+      default:
+        return false;
+    }
+}
+
+// Returns true on successful wrap state update (valid enum parameter)
+bool Texture::setWrapT(GLenum wrap)
+{
+    switch (wrap)
+    {
+      case GL_REPEAT:
+      case GL_CLAMP_TO_EDGE:
+      case GL_MIRRORED_REPEAT:
+        {
+            if (mWrapT != wrap)
+            {
+                mWrapT = wrap;
+                mDirtyParameters = true;
+            }
+            return true;
+        }
+      default:
+        return false;
+    }
+}
+
+// Returns true on successful usage state update (valid enum parameter)
+bool Texture::setUsage(GLenum usage)
+{
+    switch (usage)
+    {
+      case GL_NONE:
+      case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
+        mUsage = usage;
+        return true;
+      default:
+        return false;
+    }
+}
+
+GLenum Texture::getMinFilter() const
+{
+    return mMinFilter;
+}
+
+GLenum Texture::getMagFilter() const
+{
+    return mMagFilter;
+}
+
+GLenum Texture::getWrapS() const
+{
+    return mWrapS;
+}
+
+GLenum Texture::getWrapT() const
+{
+    return mWrapT;
+}
+
+GLenum Texture::getUsage() const
+{
+    return mUsage;
+}
+
+void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image)
+{
+    if (pixels != NULL)
+    {
+        D3DLOCKED_RECT locked;
+        HRESULT result = image->lock(&locked, NULL);
+
+        if (SUCCEEDED(result))
+        {
+            image->loadData(0, 0, image->getWidth(), image->getHeight(), image->getType(), unpackAlignment, pixels, locked.Pitch, locked.pBits);
+            image->unlock();
+        }
+
+        mDirtyImages = true;
+    }
+}
+
+void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
+{
+    if (pixels != NULL)
+    {
+        D3DLOCKED_RECT locked;
+        HRESULT result = image->lock(&locked, NULL);
+
+        if (SUCCEEDED(result))
+        {
+            int inputPitch = ComputeCompressedPitch(image->getWidth(), image->getFormat());
+            int inputSize = ComputeCompressedSize(image->getWidth(), image->getHeight(), image->getFormat());
+            image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
+            image->unlock();
+        }
+
+        mDirtyImages = true;
+    }
+}
+
+bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image)
+{
+    if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
+    {
+        error(GL_INVALID_VALUE);
+        return false;
+    }
+
+    if (IsCompressed(image->getFormat()))
+    {
+        error(GL_INVALID_OPERATION);
+        return false;
+    }
+
+    if (format != image->getFormat())
+    {
+        error(GL_INVALID_OPERATION);
+        return false;
+    }
+
+    if (pixels != NULL)
+    {
+        D3DLOCKED_RECT locked;
+        HRESULT result = image->lock(&locked, NULL);
+
+        if (SUCCEEDED(result))
+        {
+            image->loadData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
+            image->unlock();
+        }
+
+        mDirtyImages = true;
+    }
+
+    return true;
+}
+
+bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image)
+{
+    if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
+    {
+        error(GL_INVALID_VALUE);
+        return false;
+    }
+
+    if (format != getInternalFormat())
+    {
+        error(GL_INVALID_OPERATION);
+        return false;
+    }
+
+    if (pixels != NULL)
+    {
+        RECT updateRegion;
+        updateRegion.left = xoffset;
+        updateRegion.right = xoffset + width;
+        updateRegion.bottom = yoffset + height;
+        updateRegion.top = yoffset;
+
+        D3DLOCKED_RECT locked;
+        HRESULT result = image->lock(&locked, &updateRegion);
+
+        if (SUCCEEDED(result))
+        {
+            int inputPitch = ComputeCompressedPitch(width, format);
+            int inputSize = ComputeCompressedSize(width, height, format);
+            image->loadCompressedData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
+            image->unlock();
+        }
+
+        mDirtyImages = true;
+    }
+
+    return true;
 }
 
 IDirect3DBaseTexture9 *Texture::getTexture()
 {
-    if (!isComplete())
+    if (!isSamplerComplete())
     {
         return NULL;
     }
 
     if (!getBaseTexture())
     {
         createTexture();
     }
 
     updateTexture();
 
     return getBaseTexture();
 }
 
-bool Texture::isDirtyParameter() const
+bool Texture::hasDirtyParameters() const
 {
-    return mDirtyParameter;
+    return mDirtyParameters;
 }
 
-bool Texture::isDirtyImage() const
+bool Texture::hasDirtyImages() const
 {
-    return mDirtyImage;
+    return mDirtyImages;
 }
 
 void Texture::resetDirty()
 {
-    mDirtyParameter = false;
-    mDirtyImage = false;
+    mDirtyParameters = false;
+    mDirtyImages = false;
+}
+
+unsigned int Texture::getTextureSerial() const
+{
+    TextureStorage *texture = getStorage();
+    return texture ? texture->getTextureSerial() : 0;
 }
 
-unsigned int Texture::getSerial() const
+unsigned int Texture::getRenderTargetSerial(GLenum target) const
 {
-    return mSerial;
+    TextureStorage *texture = getStorage();
+    return texture ? texture->getRenderTargetSerial(target) : 0;
 }
 
-GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
+bool Texture::isImmutable() const
+{
+    return mImmutable;
+}
+
+GLint Texture::creationLevels(GLsizei width, GLsizei height) const
 {
     if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
     {
-        return maxlevel;
+        return 0;   // Maximum number of levels
     }
     else
     {
         // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
         return 1;
     }
 }
 
-GLint Texture::creationLevels(GLsizei size, GLint maxlevel) const
+GLint Texture::creationLevels(GLsizei size) const
 {
-    return creationLevels(size, size, maxlevel);
+    return creationLevels(size, size);
 }
 
 int Texture::levelCount() const
 {
     return getBaseTexture() ? getBaseTexture()->GetLevelCount() : 0;
 }
 
-unsigned int Texture::issueSerial()
+Blit *Texture::getBlitter()
+{
+    Context *context = getContext();
+    return context->getBlitter();
+}
+
+bool Texture::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
+{
+    if (source && dest)
+    {
+        HRESULT result;
+
+        if (fromManaged)
+        {
+            result = D3DXLoadSurfaceFromSurface(dest, NULL, NULL, source, NULL, NULL, D3DX_FILTER_BOX, 0);
+        }
+        else
+        {
+            egl::Display *display = getDisplay();
+            IDirect3DDevice9 *device = display->getDevice();
+
+            display->endScene();
+            result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+        }
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+TextureStorage2D::TextureStorage2D(IDirect3DTexture9 *surfaceTexture) : TextureStorage(true), mRenderTargetSerial(RenderbufferStorage::issueSerial())
 {
-    return mCurrentSerial++;
+    mTexture = surfaceTexture;
+}
+
+TextureStorage2D::TextureStorage2D(int levels, D3DFORMAT format, int width, int height, bool renderable) : TextureStorage(renderable), mRenderTargetSerial(RenderbufferStorage::issueSerial())
+{
+    egl::Display *display = getDisplay();
+    IDirect3DDevice9 *device = display->getDevice();
+
+    mTexture = NULL;
+    HRESULT result = device->CreateTexture(width, height, levels, renderable ? D3DUSAGE_RENDERTARGET : 0, format, display->getTexturePool(renderable), &mTexture, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        error(GL_OUT_OF_MEMORY);
+    }
+}
+
+TextureStorage2D::~TextureStorage2D()
+{
+    mTexture->Release();
+}
+
+IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level)
+{
+    IDirect3DSurface9 *surface = NULL;
+
+    if (mTexture)
+    {
+        HRESULT result = mTexture->GetSurfaceLevel(level, &surface);
+        ASSERT(SUCCEEDED(result));
+    }
+
+    return surface;
+}
+
+IDirect3DBaseTexture9 *TextureStorage2D::getBaseTexture() const
+{
+    return mTexture;
+}
+
+unsigned int TextureStorage2D::getRenderTargetSerial(GLenum target) const
+{
+    return mRenderTargetSerial;
 }
 
 Texture2D::Texture2D(GLuint id) : Texture(id)
 {
     mTexture = NULL;
     mSurface = NULL;
 }
 
 Texture2D::~Texture2D()
 {
     mColorbufferProxy.set(NULL);
 
-    if (mTexture)
-    {
-        mTexture->Release();
-        mTexture = NULL;
-    }
-
+    delete mTexture;
+    mTexture = NULL;
+    
     if (mSurface)
     {
         mSurface->setBoundTexture(NULL);
         mSurface = NULL;
     }
 }
 
 GLenum Texture2D::getTarget() const
 {
     return GL_TEXTURE_2D;
 }
 
 GLsizei Texture2D::getWidth() const
 {
-    return mImageArray[0].width;
+    return mImageArray[0].getWidth();
 }
 
 GLsizei Texture2D::getHeight() const
 {
-    return mImageArray[0].height;
+    return mImageArray[0].getHeight();
 }
 
 GLenum Texture2D::getInternalFormat() const
 {
-    return mImageArray[0].format;
+    return mImageArray[0].getFormat();
 }
 
 GLenum Texture2D::getType() const
 {
-    return mImageArray[0].type;
+    return mImageArray[0].getType();
 }
 
 D3DFORMAT Texture2D::getD3DFormat() const
 {
     return mImageArray[0].getD3DFormat();
 }
 
-void Texture2D::redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRedefine)
+void Texture2D::redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
 {
-    GLsizei textureWidth = mImageArray[0].width;
-    GLsizei textureHeight = mImageArray[0].height;
-    GLenum textureFormat = mImageArray[0].format;
-    GLenum textureType = mImageArray[0].type;
-
-    mImageArray[level].width = width;
-    mImageArray[level].height = height;
-    mImageArray[level].format = format;
-    mImageArray[level].type = type;
-
-    if (!mTexture)
-    {
-        return;
-    }
-
-    bool widthOkay = (textureWidth >> level == width) || (textureWidth >> level == 0 && width == 1);
-    bool heightOkay = (textureHeight >> level == height) || (textureHeight >> level == 0 && height == 1);
-    bool textureOkay = (widthOkay && heightOkay && textureFormat == format && textureType == type);
-
-    if (!textureOkay || forceRedefine || mSurface)   // Purge all the levels and the texture.
+    releaseTexImage();
+
+    bool redefined = mImageArray[level].redefine(format, width, height, type, false);
+
+    if (mTexture && redefined)
     {
         for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
         {
-            if (mImageArray[i].surface != NULL)
-            {
-                mImageArray[i].surface->Release();
-                mImageArray[i].surface = NULL;
-                mImageArray[i].dirty = true;
-            }
+            mImageArray[i].markDirty();
         }
 
-        if (mTexture != NULL)
-        {
-            mTexture->Release();
-            mTexture = NULL;
-            mDirtyImage = true;
-            mIsRenderable = false;
-        }
-
-        if (mSurface)
-        {
-            mSurface->setBoundTexture(NULL);
-            mSurface = NULL;
-        }
-
-        mColorbufferProxy.set(NULL);
+        delete mTexture;
+        mTexture = NULL;
+        mDirtyImages = true;
     }
 }
 
 void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
 {
-    redefineTexture(level, format, width, height, type, false);
+    redefineImage(level, format, width, height, type);
 
     Texture::setImage(unpackAlignment, pixels, &mImageArray[level]);
 }
 
 void Texture2D::bindTexImage(egl::Surface *surface)
 {
+    releaseTexImage();
+
     GLenum format;
 
     switch(surface->getFormat())
     {
       case D3DFMT_A8R8G8B8:
         format = GL_RGBA;
         break;
       case D3DFMT_X8R8G8B8:
         format = GL_RGB;
         break;
       default:
         UNIMPLEMENTED();
         return;
     }
 
-    redefineTexture(0, format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true);
-
-    IDirect3DTexture9 *texture = surface->getOffscreenTexture();
-
-    mTexture = texture;
-    mDirtyImage = true;
-    mIsRenderable = true;
+    mImageArray[0].redefine(format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true);
+
+    delete mTexture;
+    mTexture = new TextureStorage2D(surface->getOffscreenTexture());
+
+    mDirtyImages = true;
     mSurface = surface;
     mSurface->setBoundTexture(this);
 }
 
 void Texture2D::releaseTexImage()
 {
-    redefineTexture(0, GL_RGB, 0, 0, GL_UNSIGNED_BYTE, true);
+    if (mSurface)
+    {
+        mSurface->setBoundTexture(NULL);
+        mSurface = NULL;
+
+        if (mTexture)
+        {
+            delete mTexture;
+            mTexture = NULL;
+        }
+
+        for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+        {
+            mImageArray[i].redefine(GL_RGBA, 0, 0, GL_UNSIGNED_BYTE, true);
+        }
+    }
 }
 
 void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
 {
-    redefineTexture(level, format, width, height, GL_UNSIGNED_BYTE, false);
+    redefineImage(level, format, width, height, GL_UNSIGNED_BYTE);
 
     Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]);
 }
 
 void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
 {
-    ASSERT(mImageArray[level].surface != NULL);
+    ASSERT(mImageArray[level].getSurface() != NULL);
 
     if (level < levelCount())
     {
-        IDirect3DSurface9 *destLevel = NULL;
-        HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
-
-        ASSERT(SUCCEEDED(result));
-
-        if (SUCCEEDED(result))
+        IDirect3DSurface9 *destLevel = mTexture->getSurfaceLevel(level);
+
+        if (destLevel)
         {
             Image *image = &mImageArray[level];
-
-            RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->height);;
-
-            POINT destPoint;
-            destPoint.x = sourceRect.left;
-            destPoint.y = sourceRect.top;
-
-            result = getDevice()->UpdateSurface(image->surface, &sourceRect, destLevel, &destPoint);
-            ASSERT(SUCCEEDED(result));
+            image->updateSurface(destLevel, xoffset, yoffset, width, height);
 
             destLevel->Release();
-
-            image->dirty = false;
+            image->markClean();
         }
     }
 }
 
 void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
 {
     if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
     {
@@ -1700,104 +1860,134 @@ void Texture2D::copyImage(GLint level, G
     IDirect3DSurface9 *renderTarget = source->getRenderTarget();
 
     if (!renderTarget)
     {
         ERR("Failed to retrieve the render target.");
         return error(GL_OUT_OF_MEMORY);
     }
 
-    redefineTexture(level, format, width, height, GL_UNSIGNED_BYTE, false);
+    redefineImage(level, format, width, height, GL_UNSIGNED_BYTE);
    
     if (!mImageArray[level].isRenderable())
     {
-        copyToImage(&mImageArray[level], 0, 0, x, y, width, height, renderTarget);
+        mImageArray[level].copy(0, 0, x, y, width, height, renderTarget);
+        mDirtyImages = true;
     }
     else
     {
-        if (!mTexture || !mIsRenderable)
+        if (!mTexture || !mTexture->isRenderable())
         {
             convertToRenderTarget();
         }
         
-        updateTexture();
+        mImageArray[level].markClean();
 
         if (width != 0 && height != 0 && level < levelCount())
         {
             RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
             sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
             sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
             sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
             sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
 
-            GLint destYOffset = transformPixelYOffset(0, height, mImageArray[level].height);
+            GLint destYOffset = transformPixelYOffset(0, height, mImageArray[level].getHeight());
             
-            IDirect3DSurface9 *dest;
-            HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
-
-            getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest);
-            dest->Release();
+            IDirect3DSurface9 *dest = mTexture->getSurfaceLevel(level);
+
+            if (dest)
+            {
+                getBlitter()->copy(renderTarget, sourceRect, format, 0, destYOffset, dest);
+                dest->Release();
+            }
         }
     }
+
+    renderTarget->Release();
 }
 
 void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
 {
-    if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
+    if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight())
     {
         return error(GL_INVALID_VALUE);
     }
 
     IDirect3DSurface9 *renderTarget = source->getRenderTarget();
 
     if (!renderTarget)
     {
         ERR("Failed to retrieve the render target.");
         return error(GL_OUT_OF_MEMORY);
     }
 
-    redefineTexture(level, mImageArray[level].format, mImageArray[level].width, mImageArray[level].height, GL_UNSIGNED_BYTE, false);
-   
-    if (!mImageArray[level].isRenderable() || (!mTexture && !isComplete()))
+    if (!mImageArray[level].isRenderable() || (!mTexture && !isSamplerComplete()))
     {
-        copyToImage(&mImageArray[level], xoffset, yoffset, x, y, width, height, renderTarget);
+        mImageArray[level].copy(xoffset, yoffset, x, y, width, height, renderTarget);
+        mDirtyImages = true;
     }
     else
     {
-        if (!mTexture || !mIsRenderable)
+        if (!mTexture || !mTexture->isRenderable())
         {
             convertToRenderTarget();
         }
         
         updateTexture();
 
         if (level < levelCount())
         {
             RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
             sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
             sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
             sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
             sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
 
-            GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[level].height);
-
-            IDirect3DSurface9 *dest;
-            HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
-
-            getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, destYOffset, dest);
-            dest->Release();
+            GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[level].getHeight());
+
+            IDirect3DSurface9 *dest = mTexture->getSurfaceLevel(level);
+
+            if (dest)
+            {
+                getBlitter()->copy(renderTarget, sourceRect, mImageArray[0].getFormat(), xoffset, destYOffset, dest);
+                dest->Release();
+            }
         }
     }
+
+    renderTarget->Release();
 }
 
-// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool Texture2D::isComplete() const
+void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 {
-    GLsizei width = mImageArray[0].width;
-    GLsizei height = mImageArray[0].height;
+    GLenum format = gl::ExtractFormat(internalformat);
+    GLenum type = gl::ExtractType(internalformat);
+
+    delete mTexture;
+    mTexture = new TextureStorage2D(levels, mImageArray[0].getD3DFormat(), width, height, mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+    mImmutable = true;
+
+    for (int level = 0; level < levels; level++)
+    {
+        mImageArray[level].redefine(format, width, height, type, true);
+        width = std::max(1, width >> 1);
+        height = std::max(1, height >> 1);
+    }
+
+    for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        mImageArray[level].redefine(GL_NONE, 0, 0, GL_UNSIGNED_BYTE, true);
+    }
+}
+
+// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
+bool Texture2D::isSamplerComplete() const
+{
+    GLsizei width = mImageArray[0].getWidth();
+    GLsizei height = mImageArray[0].getHeight();
 
     if (width <= 0 || height <= 0)
     {
         return false;
     }
 
     bool mipmapping = false;
 
@@ -1808,374 +1998,372 @@ bool Texture2D::isComplete() const
         mipmapping = false;
         break;
       case GL_NEAREST_MIPMAP_NEAREST:
       case GL_LINEAR_MIPMAP_NEAREST:
       case GL_NEAREST_MIPMAP_LINEAR:
       case GL_LINEAR_MIPMAP_LINEAR:
         mipmapping = true;
         break;
-     default: UNREACHABLE();
+      default: UNREACHABLE();
     }
 
-    if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
-        (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
+    if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
+        (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsFloat16LinearFilter()))
     {
         if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
         {
             return false;
         }
     }
 
-    bool npot = getContext()->supportsNonPower2Texture();
-
-    if (!npot)
+    bool npotSupport = getContext()->supportsNonPower2Texture();
+
+    if (!npotSupport)
     {
         if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
             (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
         {
             return false;
         }
     }
 
     if (mipmapping)
     {
-        if (!npot)
+        if (!npotSupport)
         {
             if (!isPow2(width) || !isPow2(height))
             {
                 return false;
             }
         }
 
-        int q = log2(std::max(width, height));
-
-        for (int level = 1; level <= q; level++)
+        if (!isMipmapComplete())
         {
-            if (mImageArray[level].format != mImageArray[0].format)
-            {
-                return false;
-            }
-
-            if (mImageArray[level].type != mImageArray[0].type)
-            {
-                return false;
-            }
-
-            if (mImageArray[level].width != std::max(1, width >> level))
-            {
-                return false;
-            }
-
-            if (mImageArray[level].height != std::max(1, height >> level))
-            {
-                return false;
-            }
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture2D::isMipmapComplete() const
+{
+    if (isImmutable())
+    {
+        return true;
+    }
+
+    GLsizei width = mImageArray[0].getWidth();
+    GLsizei height = mImageArray[0].getHeight();
+
+    if (width <= 0 || height <= 0)
+    {
+        return false;
+    }
+
+    int q = log2(std::max(width, height));
+
+    for (int level = 1; level <= q; level++)
+    {
+        if (mImageArray[level].getFormat() != mImageArray[0].getFormat())
+        {
+            return false;
+        }
+
+        if (mImageArray[level].getType() != mImageArray[0].getType())
+        {
+            return false;
+        }
+
+        if (mImageArray[level].getWidth() != std::max(1, width >> level))
+        {
+            return false;
+        }
+
+        if (mImageArray[level].getHeight() != std::max(1, height >> level))
+        {
+            return false;
         }
     }
 
     return true;
 }
 
 bool Texture2D::isCompressed() const
 {
     return IsCompressed(getInternalFormat());
 }
 
 IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const
 {
-    return mTexture;
+    return mTexture ? mTexture->getBaseTexture() : NULL;
 }
 
 // Constructs a Direct3D 9 texture resource from the texture images
 void Texture2D::createTexture()
 {
-    IDirect3DDevice9 *device = getDevice();
+    GLsizei width = mImageArray[0].getWidth();
+    GLsizei height = mImageArray[0].getHeight();
+    GLint levels = creationLevels(width, height);
     D3DFORMAT format = mImageArray[0].getD3DFormat();
-    GLint levels = creationLevels(mImageArray[0].width, mImageArray[0].height, 0);
-
-    IDirect3DTexture9 *texture = NULL;
-    HRESULT result = device->CreateTexture(mImageArray[0].width, mImageArray[0].height, levels, 0, format, D3DPOOL_DEFAULT, &texture, NULL);
-
-    if (FAILED(result))
+    bool renderable = (mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+
+    delete mTexture;
+    mTexture = new TextureStorage2D(levels, format, width, height, renderable);
+    
+    if (mTexture->isManaged())
     {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return error(GL_OUT_OF_MEMORY);
+        int levels = levelCount();
+
+        for (int level = 0; level < levels; level++)
+        {
+            IDirect3DSurface9 *surface = mTexture->getSurfaceLevel(level);
+            mImageArray[level].setManagedSurface(surface);
+        }
     }
 
-    if (mTexture)
-    {
-        mTexture->Release();
-    }
-
-    mTexture = texture;
-    mDirtyImage = true;
-    mIsRenderable = false;
+    mDirtyImages = true;
 }
 
 void Texture2D::updateTexture()
 {
-    IDirect3DDevice9 *device = getDevice();
-
     int levels = levelCount();
 
     for (int level = 0; level < levels; level++)
     {
-        if (mImageArray[level].surface && mImageArray[level].dirty)
+        Image *image = &mImageArray[level];
+
+        if (image->isDirty())
         {
-            IDirect3DSurface9 *levelSurface = NULL;
-            HRESULT result = mTexture->GetSurfaceLevel(level, &levelSurface);
-
-            ASSERT(SUCCEEDED(result));
-
-            if (SUCCEEDED(result))
-            {
-                result = device->UpdateSurface(mImageArray[level].surface, NULL, levelSurface, NULL);
-                ASSERT(SUCCEEDED(result));
-
-                levelSurface->Release();
-
-                mImageArray[level].dirty = false;
-            }
+            commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight());
         }
     }
 }
 
 void Texture2D::convertToRenderTarget()
 {
-    IDirect3DTexture9 *texture = NULL;
-
-    if (mImageArray[0].width != 0 && mImageArray[0].height != 0)
+    TextureStorage2D *newTexture = NULL;
+
+    if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0)
     {
-        egl::Display *display = getDisplay();
-        IDirect3DDevice9 *device = getDevice();
+        GLsizei width = mImageArray[0].getWidth();
+        GLsizei height = mImageArray[0].getHeight();
+        GLint levels = creationLevels(width, height);
         D3DFORMAT format = mImageArray[0].getD3DFormat();
-        GLint levels = creationLevels(mImageArray[0].width, mImageArray[0].height, 0);
-
-        HRESULT result = device->CreateTexture(mImageArray[0].width, mImageArray[0].height, levels, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            return error(GL_OUT_OF_MEMORY);
-        }
+
+        newTexture = new TextureStorage2D(levels, format, width, height, true);
 
         if (mTexture != NULL)
         {
             int levels = levelCount();
             for (int i = 0; i < levels; i++)
             {
-                IDirect3DSurface9 *source;
-                result = mTexture->GetSurfaceLevel(i, &source);
-
-                if (FAILED(result))
-                {
-                    ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
-                    texture->Release();
-
-                    return error(GL_OUT_OF_MEMORY);
+                IDirect3DSurface9 *source = mTexture->getSurfaceLevel(i);
+                IDirect3DSurface9 *dest = newTexture->getSurfaceLevel(i);
+
+                if (!copyToRenderTarget(dest, source, mTexture->isManaged()))
+                {   
+                   delete newTexture;
+                   source->Release();
+                   dest->Release();
+                   return error(GL_OUT_OF_MEMORY);
                 }
 
-                IDirect3DSurface9 *dest;
-                result = texture->GetSurfaceLevel(i, &dest);
-
-                if (FAILED(result))
-                {
-                    ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
-                    texture->Release();
-                    source->Release();
-
-                    return error(GL_OUT_OF_MEMORY);
-                }
-
-                display->endScene();
-                result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
-
-                if (FAILED(result))
-                {
-                    ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
-                    texture->Release();
-                    source->Release();
-                    dest->Release();
-
-                    return error(GL_OUT_OF_MEMORY);
-                }
-
-                source->Release();
-                dest->Release();
+                if (source) source->Release();
+                if (dest) dest->Release();
             }
         }
     }
 
-    if (mTexture != NULL)
-    {
-        mTexture->Release();
-    }
-
-    mTexture = texture;
-    mDirtyImage = true;
-    mIsRenderable = true;
+    delete mTexture;
+    mTexture = newTexture;
+
+    mDirtyImages = true;
 }
 
 void Texture2D::generateMipmaps()
 {
     if (!getContext()->supportsNonPower2Texture())
     {
-        if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))
+        if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight()))
         {
             return error(GL_INVALID_OPERATION);
         }
     }
 
     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
-    unsigned int q = log2(std::max(mImageArray[0].width, mImageArray[0].height));
+    unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight()));
     for (unsigned int i = 1; i <= q; i++)
     {
-        if (mImageArray[i].surface != NULL)
-        {
-            mImageArray[i].surface->Release();
-            mImageArray[i].surface = NULL;
-        }
-
-        mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);
-        mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
-        mImageArray[i].format = mImageArray[0].format;
-        mImageArray[i].type = mImageArray[0].type;
+        redefineImage(i, mImageArray[0].getFormat(), 
+                         std::max(mImageArray[0].getWidth() >> i, 1),
+                         std::max(mImageArray[0].getHeight() >> i, 1),
+                         mImageArray[0].getType());
     }
 
-    if (mIsRenderable)
+    if (mTexture && mTexture->isRenderable())
     {
-        if (mTexture == NULL)
-        {
-            ERR(" failed because mTexture was null.");
-            return;
-        }
-
         for (unsigned int i = 1; i <= q; i++)
         {
-            IDirect3DSurface9 *upper = NULL;
-            IDirect3DSurface9 *lower = NULL;
-
-            mTexture->GetSurfaceLevel(i-1, &upper);
-            mTexture->GetSurfaceLevel(i, &lower);
+            IDirect3DSurface9 *upper = mTexture->getSurfaceLevel(i - 1);
+            IDirect3DSurface9 *lower = mTexture->getSurfaceLevel(i);
 
             if (upper != NULL && lower != NULL)
             {
                 getBlitter()->boxFilter(upper, lower);
             }
 
             if (upper != NULL) upper->Release();
             if (lower != NULL) lower->Release();
 
-            mImageArray[i].dirty = false;
+            mImageArray[i].markClean();
         }
     }
     else
     {
         for (unsigned int i = 1; i <= q; i++)
         {
-            createSurface(&mImageArray[i]);
-            
-            if (mImageArray[i].surface == NULL)
+            if (mImageArray[i].getSurface() == NULL)
             {
                 return error(GL_OUT_OF_MEMORY);
             }
 
-            if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[i].surface, NULL, NULL, mImageArray[i - 1].surface, NULL, NULL, D3DX_FILTER_BOX, 0)))
+            if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[i].getSurface(), NULL, NULL, mImageArray[i - 1].getSurface(), NULL, NULL, D3DX_FILTER_BOX, 0)))
             {
                 ERR(" failed to load filter %d to %d.", i - 1, i);
             }
 
-            mImageArray[i].dirty = true;
+            mImageArray[i].markDirty();
         }
     }
 }
 
 Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
 {
     if (target != GL_TEXTURE_2D)
     {
         return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
     }
 
     if (mColorbufferProxy.get() == NULL)
     {
-        mColorbufferProxy.set(new Renderbuffer(id(), new Colorbuffer(this, target)));
+        mColorbufferProxy.set(new Renderbuffer(id(), new RenderbufferTexture(this, target)));
     }
 
     return mColorbufferProxy.get();
 }
 
 IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
 {
     ASSERT(target == GL_TEXTURE_2D);
 
-    if (!mIsRenderable)
+    if (!mTexture || !mTexture->isRenderable())
     {
         convertToRenderTarget();
     }
 
     if (mTexture == NULL)
     {
         return NULL;
     }
 
     updateTexture();
     
-    IDirect3DSurface9 *renderTarget = NULL;
-    mTexture->GetSurfaceLevel(0, &renderTarget);
-
-    return renderTarget;
+    return mTexture->getSurfaceLevel(0);
+}
+
+TextureStorage *Texture2D::getStorage() const
+{
+    return mTexture;
+}
+
+TextureStorageCubeMap::TextureStorageCubeMap(int levels, D3DFORMAT format, int size, bool renderable) : TextureStorage(renderable), mFirstRenderTargetSerial(RenderbufferStorage::issueCubeSerials())
+{
+    egl::Display *display = getDisplay();
+    IDirect3DDevice9 *device = display->getDevice();
+
+    mTexture = NULL;
+    HRESULT result = device->CreateCubeTexture(size, levels, renderable ? D3DUSAGE_RENDERTARGET : 0, format, display->getTexturePool(renderable), &mTexture, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        error(GL_OUT_OF_MEMORY);
+    }
+}
+
+TextureStorageCubeMap::~TextureStorageCubeMap()
+{
+    mTexture->Release();
+}
+
+IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, int level)
+{
+    IDirect3DSurface9 *surface = NULL;
+
+    if (mTexture)
+    {
+        HRESULT result = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(faceTarget), level, &surface);
+        ASSERT(SUCCEEDED(result));
+    }
+
+    return surface;
+}
+
+IDirect3DBaseTexture9 *TextureStorageCubeMap::getBaseTexture() const
+{
+    return mTexture;
+}
+
+unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const
+{
+    return mFirstRenderTargetSerial + TextureCubeMap::faceIndex(target);
 }
 
 TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
 {
     mTexture = NULL;
 }
 
 TextureCubeMap::~TextureCubeMap()
 {
     for (int i = 0; i < 6; i++)
     {
         mFaceProxies[i].set(NULL);
     }
 
-    if (mTexture)
-    {
-        mTexture->Release();
-        mTexture = NULL;
-    }
+    delete mTexture;
+    mTexture = NULL;
 }
 
 GLenum TextureCubeMap::getTarget() const
 {
     return GL_TEXTURE_CUBE_MAP;
 }
 
 GLsizei TextureCubeMap::getWidth() const
 {
-    return mImageArray[0][0].width;
+    return mImageArray[0][0].getWidth();
 }
 
 GLsizei TextureCubeMap::getHeight() const
 {
-    return mImageArray[0][0].height;
+    return mImageArray[0][0].getHeight();
 }
 
 GLenum TextureCubeMap::getInternalFormat() const
 {
-    return mImageArray[0][0].format;
+    return mImageArray[0][0].getFormat();
 }
 
 GLenum TextureCubeMap::getType() const
 {
-    return mImageArray[0][0].type;
+    return mImageArray[0][0].getType();
 }
 
 D3DFORMAT TextureCubeMap::getD3DFormat() const
 {
     return mImageArray[0][0].getD3DFormat();
 }
 
 void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
@@ -2205,76 +2393,61 @@ void TextureCubeMap::setImagePosZ(GLint 
 
 void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
 {
     setImage(5, level, width, height, format, type, unpackAlignment, pixels);
 }
 
 void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
 {
-    redefineTexture(faceIndex(face), level, format, width, height, GL_UNSIGNED_BYTE);
+    redefineImage(faceIndex(face), level, format, width, height, GL_UNSIGNED_BYTE);
 
     Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]);
 }
 
-void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
 {
-    int face = faceIndex(faceTarget);
-    ASSERT(mImageArray[face][level].surface != NULL);
+    ASSERT(mImageArray[face][level].getSurface() != NULL);
 
     if (level < levelCount())
     {
-        IDirect3DSurface9 *destLevel = getCubeMapSurface(faceTarget, level);
+        IDirect3DSurface9 *destLevel = mTexture->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
         ASSERT(destLevel != NULL);
 
         if (destLevel != NULL)
         {
             Image *image = &mImageArray[face][level];
-
-            RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->height);;
-
-            POINT destPoint;
-            destPoint.x = sourceRect.left;
-            destPoint.y = sourceRect.top;
-
-            HRESULT result = getDevice()->UpdateSurface(image->surface, &sourceRect, destLevel, &destPoint);
-            ASSERT(SUCCEEDED(result));
+            image->updateSurface(destLevel, xoffset, yoffset, width, height);
 
             destLevel->Release();
-
-            image->dirty = false;
+            image->markClean();
         }
     }
 }
 
 void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
 {
     if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
     {
-        commitRect(target, level, xoffset, yoffset, width, height);
+        commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
     }
 }
 
 void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
 {
     if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
     {
-        commitRect(target, level, xoffset, yoffset, width, height);
+        commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
     }
 }
 
-// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool TextureCubeMap::isComplete() const
+// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
+bool TextureCubeMap::isSamplerComplete() const
 {
-    int size = mImageArray[0][0].width;
-
-    if (size <= 0)
-    {
-        return false;
-    }
+    int size = mImageArray[0][0].getWidth();
 
     bool mipmapping;
 
     switch (mMinFilter)
     {
       case GL_NEAREST:
       case GL_LINEAR:
         mipmapping = false;
@@ -2283,539 +2456,493 @@ bool TextureCubeMap::isComplete() const
       case GL_LINEAR_MIPMAP_NEAREST:
       case GL_NEAREST_MIPMAP_LINEAR:
       case GL_LINEAR_MIPMAP_LINEAR:
         mipmapping = true;
         break;
       default: UNREACHABLE();
     }
 
-    for (int face = 0; face < 6; face++)
-    {
-        if (mImageArray[face][0].width != size || mImageArray[face][0].height != size)
-        {
-            return false;
-        }
-    }
-
-    if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
-        (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
+    if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
+        (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsFloat16LinearFilter()))
     {
         if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
         {
             return false;
         }
     }
 
-    bool npot = getContext()->supportsNonPower2Texture();
-
-    if (!npot)
+    if (!isPow2(size) && !getContext()->supportsNonPower2Texture())
     {
-        if ((getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE) && !isPow2(size))
+        if (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE || mipmapping)
+        {
+            return false;
+        }
+    }
+
+    if (!mipmapping)
+    {
+        if (!isCubeComplete())
+        {
+            return false;
+        }
+    }
+    else
+    {
+        if (!isMipmapCubeComplete())   // Also tests for isCubeComplete()
         {
             return false;
         }
     }
 
-    if (mipmapping)
+    return true;
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureCubeMap::isCubeComplete() const
+{
+    if (mImageArray[0][0].getWidth() <= 0 || mImageArray[0][0].getHeight() != mImageArray[0][0].getWidth())
+    {
+        return false;
+    }
+
+    for (unsigned int face = 1; face < 6; face++)
     {
-        if (!npot)
+        if (mImageArray[face][0].getWidth() != mImageArray[0][0].getWidth() ||
+            mImageArray[face][0].getWidth() != mImageArray[0][0].getHeight() ||
+            mImageArray[face][0].getFormat() != mImageArray[0][0].getFormat() ||
+            mImageArray[face][0].getType() != mImageArray[0][0].getType())
         {
-            if (!isPow2(size))
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool TextureCubeMap::isMipmapCubeComplete() const
+{
+    if (isImmutable())
+    {
+        return true;
+    }
+
+    if (!isCubeComplete())
+    {
+        return false;
+    }
+
+    GLsizei size = mImageArray[0][0].getWidth();
+
+    int q = log2(size);
+
+    for (int face = 0; face < 6; face++)
+    {
+        for (int level = 1; level <= q; level++)
+        {
+            if (mImageArray[face][level].getFormat() != mImageArray[0][0].getFormat())
             {
                 return false;
             }
-        }
-
-        int q = log2(size);
-
-        for (int face = 0; face < 6; face++)
-        {
-            for (int level = 1; level <= q; level++)
+
+            if (mImageArray[face][level].getType() != mImageArray[0][0].getType())
             {
-                if (mImageArray[face][level].format != mImageArray[0][0].format)
-                {
-                    return false;
-                }
-
-                if (mImageArray[face][level].type != mImageArray[0][0].type)
-                {
-                    return false;
-                }
-
-                if (mImageArray[face][level].width != std::max(1, size >> level))
-                {
-                    return false;
-                }
-
-                ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);
+                return false;
+            }
+
+            if (mImageArray[face][level].getWidth() != std::max(1, size >> level))
+            {
+                return false;
             }
         }
     }
 
     return true;
 }
 
 bool TextureCubeMap::isCompressed() const
 {
     return IsCompressed(getInternalFormat());
 }
 
 IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const
 {
-    return mTexture;
+    return mTexture ? mTexture->getBaseTexture() : NULL;
 }
 
 // Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
 void TextureCubeMap::createTexture()
 {
-    IDirect3DDevice9 *device = getDevice();
+    GLsizei size = mImageArray[0][0].getWidth();
+    GLint levels = creationLevels(size, 0);
     D3DFORMAT format = mImageArray[0][0].getD3DFormat();
-    GLint levels = creationLevels(mImageArray[0][0].width, 0);
-
-    IDirect3DCubeTexture9 *texture = NULL;
-    HRESULT result = device->CreateCubeTexture(mImageArray[0][0].width, levels, 0, format, D3DPOOL_DEFAULT, &texture, NULL);
-
-    if (FAILED(result))
+    bool renderable = (mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+
+    delete mTexture;
+    mTexture = new TextureStorageCubeMap(levels, format, size, renderable);
+
+    if (mTexture->isManaged())
     {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return error(GL_OUT_OF_MEMORY);
+        int levels = levelCount();
+
+        for (int face = 0; face < 6; face++)
+        {
+            for (int level = 0; level < levels; level++)
+            {
+                IDirect3DSurface9 *surface = mTexture->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
+                mImageArray[face][level].setManagedSurface(surface);
+            }
+        }
     }
-
-    if (mTexture)
-    {
-        mTexture->Release();
-    }
-
-    mTexture = texture;
-    mDirtyImage = true;
-    mIsRenderable = false;
+    
+    mDirtyImages = true;
 }
 
 void TextureCubeMap::updateTexture()
 {
-    IDirect3DDevice9 *device = getDevice();
-
     for (int face = 0; face < 6; face++)
     {
         int levels = levelCount();
         for (int level = 0; level < levels; level++)
         {
             Image *image = &mImageArray[face][level];
 
-            if (image->surface && image->dirty)
+            if (image->isDirty())
             {
-                IDirect3DSurface9 *levelSurface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
-                ASSERT(levelSurface != NULL);
-
-                if (levelSurface != NULL)
-                {
-                    HRESULT result = device->UpdateSurface(image->surface, NULL, levelSurface, NULL);
-                    ASSERT(SUCCEEDED(result));
-
-                    levelSurface->Release();
-
-                    image->dirty = false;
-                }
+                commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
             }
         }
     }
 }
 
 void TextureCubeMap::convertToRenderTarget()
 {
-    IDirect3DCubeTexture9 *texture = NULL;
-
-    if (mImageArray[0][0].width != 0)
+    TextureStorageCubeMap *newTexture = NULL;
+
+    if (mImageArray[0][0].getWidth() != 0)
     {
-        egl::Display *display = getDisplay();
-        IDirect3DDevice9 *device = getDevice();
+        GLsizei size = mImageArray[0][0].getWidth();
+        GLint levels = creationLevels(size, 0);
         D3DFORMAT format = mImageArray[0][0].getD3DFormat();
-        GLint levels = creationLevels(mImageArray[0][0].width, 0);
-
-        HRESULT result = device->CreateCubeTexture(mImageArray[0][0].width, levels, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            return error(GL_OUT_OF_MEMORY);
-        }
+
+        newTexture = new TextureStorageCubeMap(levels, format, size, true);
 
         if (mTexture != NULL)
         {
+            egl::Display *display = getDisplay();
+            IDirect3DDevice9 *device = display->getDevice();
+
             int levels = levelCount();
             for (int f = 0; f < 6; f++)
             {
                 for (int i = 0; i < levels; i++)
                 {
-                    IDirect3DSurface9 *source;
-                    result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
-
-                    if (FAILED(result))
-                    {
-                        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
-                        texture->Release();
-
-                        return error(GL_OUT_OF_MEMORY);
-                    }
-
-                    IDirect3DSurface9 *dest;
-                    result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
-
-                    if (FAILED(result))
+                    IDirect3DSurface9 *source = mTexture->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
+                    IDirect3DSurface9 *dest = newTexture->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
+
+                    if (!copyToRenderTarget(dest, source, mTexture->isManaged()))
                     {
-                        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
-                        texture->Release();
-                        source->Release();
-
-                        return error(GL_OUT_OF_MEMORY);
+                       delete newTexture;
+                       source->Release();
+                       dest->Release();
+                       return error(GL_OUT_OF_MEMORY);
                     }
 
-                    display->endScene();
-                    result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
-
-                    if (FAILED(result))
-                    {
-                        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
-                        texture->Release();
-                        source->Release();
-                        dest->Release();
-
-                        return error(GL_OUT_OF_MEMORY);
-                    }
-
-                    source->Release();
-                    dest->Release();
+                    if (source) source->Release();
+                    if (dest) dest->Release();
                 }
             }
         }
     }
 
-    if (mTexture != NULL)
-    {
-        mTexture->Release();
-    }
-
-    mTexture = texture;
-    mDirtyImage = true;
-    mIsRenderable = true;
+    delete mTexture;
+    mTexture = newTexture;
+
+    mDirtyImages = true;
 }
 
 void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
 {
-    redefineTexture(faceIndex, level, format, width, height, type);
+    redefineImage(faceIndex, level, format, width, height, type);
 
     Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]);
 }
 
 unsigned int TextureCubeMap::faceIndex(GLenum face)
 {
     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
 
     return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
 }
 
-void TextureCubeMap::redefineTexture(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
+void TextureCubeMap::redefineImage(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
 {
-    GLsizei textureWidth = mImageArray[0][0].width;
-    GLsizei textureHeight = mImageArray[0][0].height;
-    GLenum textureFormat = mImageArray[0][0].format;
-    GLenum textureType = mImageArray[0][0].type;
-
-    mImageArray[face][level].width = width;
-    mImageArray[face][level].height = height;
-    mImageArray[face][level].format = format;
-    mImageArray[face][level].type = type;
-
-    if (!mTexture)
-    {
-        return;
-    }
-
-    bool sizeOkay = (textureWidth >> level == width);
-    bool textureOkay = (sizeOkay && textureFormat == format && textureType == type);
-
-    if (!textureOkay)   // Purge all the levels and the texture.
+    bool redefined = mImageArray[face][level].redefine(format, width, height, type, false);
+
+    if (mTexture && redefined)
     {
         for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
         {
             for (int f = 0; f < 6; f++)
             {
-                if (mImageArray[f][i].surface != NULL)
-                {
-                    mImageArray[f][i].surface->Release();
-                    mImageArray[f][i].surface = NULL;
-                    mImageArray[f][i].dirty = true;
-                }
+                mImageArray[f][i].markDirty();
             }
         }
 
-        if (mTexture != NULL)
-        {
-            mTexture->Release();
-            mTexture = NULL;
-            mDirtyImage = true;
-            mIsRenderable = false;
-        }
+        delete mTexture;
+        mTexture = NULL;
+
+        mDirtyImages = true;
     }
 }
 
 void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
 {
     IDirect3DSurface9 *renderTarget = source->getRenderTarget();
 
     if (!renderTarget)
     {
         ERR("Failed to retrieve the render target.");
         return error(GL_OUT_OF_MEMORY);
     }
 
     unsigned int faceindex = faceIndex(target);
-    redefineTexture(faceindex, level, format, width, height, GL_UNSIGNED_BYTE);
+    redefineImage(faceindex, level, format, width, height, GL_UNSIGNED_BYTE);
 
     if (!mImageArray[faceindex][level].isRenderable())
     {
-        copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget);
+        mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
+        mDirtyImages = true;
     }
     else
     {
-        if (!mTexture || !mIsRenderable)
+        if (!mTexture || !mTexture->isRenderable())
         {
             convertToRenderTarget();
         }
         
-        updateTexture();
+        mImageArray[faceindex][level].markClean();
 
         ASSERT(width == height);
 
         if (width > 0 && level < levelCount())
         {
             RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
             sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
             sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
             sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
             sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
 
-            GLint destYOffset = transformPixelYOffset(0, height, mImageArray[faceindex][level].width);
-
-            IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
-
-            getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest);
-            dest->Release();
+            GLint destYOffset = transformPixelYOffset(0, height, mImageArray[faceindex][level].getWidth());
+
+            IDirect3DSurface9 *dest = mTexture->getCubeMapSurface(target, level);
+
+            if (dest)
+            {
+                getBlitter()->copy(renderTarget, sourceRect, format, 0, destYOffset, dest);
+                dest->Release();
+            }
         }
     }
-}
-
-IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(GLenum face, unsigned int level)
-{
-    if (mTexture == NULL)
-    {
-        UNREACHABLE();
-        return NULL;
-    }
-
-    IDirect3DSurface9 *surface = NULL;
-
-    HRESULT hr = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(face), level, &surface);
-
-    return (SUCCEEDED(hr)) ? surface : NULL;
+
+    renderTarget->Release();
 }
 
 void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
 {
-    GLsizei size = mImageArray[faceIndex(target)][level].width;
+    GLsizei size = mImageArray[faceIndex(target)][level].getWidth();
 
     if (xoffset + width > size || yoffset + height > size)
     {
         return error(GL_INVALID_VALUE);
     }
 
     IDirect3DSurface9 *renderTarget = source->getRenderTarget();
 
     if (!renderTarget)
     {
         ERR("Failed to retrieve the render target.");
         return error(GL_OUT_OF_MEMORY);
     }
 
     unsigned int faceindex = faceIndex(target);
-    redefineTexture(faceindex, level, mImageArray[faceindex][level].format, mImageArray[faceindex][level].width, mImageArray[faceindex][level].height, GL_UNSIGNED_BYTE);
-   
-    if (!mImageArray[faceindex][level].isRenderable() || (!mTexture && !isComplete()))
+
+    if (!mImageArray[faceindex][level].isRenderable() || (!mTexture && !isSamplerComplete()))
     {
-        copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget);
+        mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
+        mDirtyImages = true;
     }
     else
     {
-        if (!mTexture || !mIsRenderable)
+        if (!mTexture || !mTexture->isRenderable())
         {
             convertToRenderTarget();
         }
         
         updateTexture();
 
         if (level < levelCount())
         {
             RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
             sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
             sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
             sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
             sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
 
-            GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[faceindex][level].width);
-
-            IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
-
-            getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, destYOffset, dest);
-            dest->Release();
+            GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[faceindex][level].getWidth());
+
+            IDirect3DSurface9 *dest = mTexture->getCubeMapSurface(target, level);
+
+            if (dest)
+            {
+                getBlitter()->copy(renderTarget, sourceRect, mImageArray[0][0].getFormat(), xoffset, destYOffset, dest);
+                dest->Release();
+            }
         }
     }
+
+    renderTarget->Release();
 }
 
-bool TextureCubeMap::isCubeComplete() const
+void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
 {
-    if (mImageArray[0][0].width == 0)
+    GLenum format = gl::ExtractFormat(internalformat);
+    GLenum type = gl::ExtractType(internalformat);
+
+    delete mTexture;
+    mTexture = new TextureStorageCubeMap(levels, mImageArray[0][0].getD3DFormat(), size, mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+    mImmutable = true;
+
+    for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
     {
-        return false;
-    }
-
-    for (unsigned int f = 1; f < 6; f++)
-    {
-        if (mImageArray[f][0].width != mImageArray[0][0].width
-            || mImageArray[f][0].format != mImageArray[0][0].format)
+        for (int face = 0; face < 6; face++)
         {
-            return false;
+            mImageArray[face][level].redefine(format, size, size, type, true);
+            size = std::max(1, size >> 1);
         }
     }
 
-    return true;
+    for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        for (int face = 0; face < 6; face++)
+        {
+            mImageArray[face][level].redefine(GL_NONE, 0, 0, GL_UNSIGNED_BYTE, true);
+        }
+    }
 }
 
 void TextureCubeMap::generateMipmaps()
 {
     if (!isCubeComplete())
     {
         return error(GL_INVALID_OPERATION);
     }
 
     if (!getContext()->supportsNonPower2Texture())
     {
-        if (!isPow2(mImageArray[0][0].width))
+        if (!isPow2(mImageArray[0][0].getWidth()))
         {
             return error(GL_INVALID_OPERATION);
         }
     }
 
     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
-    unsigned int q = log2(mImageArray[0][0].width);
+    unsigned int q = log2(mImageArray[0][0].getWidth());
     for (unsigned int f = 0; f < 6; f++)
     {
         for (unsigned int i = 1; i <= q; i++)
         {
-            if (mImageArray[f][i].surface != NULL)
-            {
-                mImageArray[f][i].surface->Release();
-                mImageArray[f][i].surface = NULL;
-            }
-
-            mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);
-            mImageArray[f][i].height = mImageArray[f][i].width;
-            mImageArray[f][i].format = mImageArray[f][0].format;
-            mImageArray[f][i].type = mImageArray[f][0].type;
+            redefineImage(f, i, mImageArray[f][0].getFormat(),
+                                std::max(mImageArray[f][0].getWidth() >> i, 1),
+                                std::max(mImageArray[f][0].getWidth() >> i, 1),
+                                mImageArray[f][0].getType());
         }
     }
 
-    if (mIsRenderable)
+    if (mTexture && mTexture->isRenderable())
     {
-        if (mTexture == NULL)
-        {
-            return;
-        }
-
         for (unsigned int f = 0; f < 6; f++)
         {
             for (unsigned int i = 1; i <= q; i++)
             {
-                IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i-1);
-                IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
+                IDirect3DSurface9 *upper = mTexture->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i-1);
+                IDirect3DSurface9 *lower = mTexture->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
 
                 if (upper != NULL && lower != NULL)
                 {
                     getBlitter()->boxFilter(upper, lower);
                 }
 
                 if (upper != NULL) upper->Release();
                 if (lower != NULL) lower->Release();
 
-                mImageArray[f][i].dirty = false;
+                mImageArray[f][i].markClean();
             }
         }
     }
     else
     {
         for (unsigned int f = 0; f < 6; f++)
         {
             for (unsigned int i = 1; i <= q; i++)
             {
-                createSurface(&mImageArray[f][i]);
-                if (mImageArray[f][i].surface == NULL)
+                if (mImageArray[f][i].getSurface() == NULL)
                 {
                     return error(GL_OUT_OF_MEMORY);
                 }
 
-                if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[f][i].surface, NULL, NULL, mImageArray[f][i - 1].surface, NULL, NULL, D3DX_FILTER_BOX, 0)))
+                if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[f][i].getSurface(), NULL, NULL, mImageArray[f][i - 1].getSurface(), NULL, NULL, D3DX_FILTER_BOX, 0)))
                 {
                     ERR(" failed to load filter %d to %d.", i - 1, i);
                 }
 
-                mImageArray[f][i].dirty = true;
+                mImageArray[f][i].markDirty();
             }
         }
     }
 }
 
 Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
 {
     if (!IsCubemapTextureTarget(target))
     {
         return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
     }
 
     unsigned int face = faceIndex(target);
 
     if (mFaceProxies[face].get() == NULL)
     {
-        mFaceProxies[face].set(new Renderbuffer(id(), new Colorbuffer(this, target)));
+        mFaceProxies[face].set(new Renderbuffer(id(), new RenderbufferTexture(this, target)));
     }
 
     return mFaceProxies[face].get();
 }
 
 IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
 {
     ASSERT(IsCubemapTextureTarget(target));
 
-    if (!mIsRenderable)
+    if (!mTexture || !mTexture->isRenderable())
     {
         convertToRenderTarget();
     }
 
     if (mTexture == NULL)
     {
         return NULL;
     }
 
     updateTexture();
     
-    IDirect3DSurface9 *renderTarget = NULL;
-    mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(target), 0, &renderTarget);
-
-    return renderTarget;
+    return mTexture->getCubeMapSurface(target, 0);
 }
 
+TextureStorage *TextureCubeMap::getStorage() const
+{
+    return mTexture;
 }
+
+}
\ No newline at end of file
--- a/gfx/angle/src/libGLESv2/Texture.h
+++ b/gfx/angle/src/libGLESv2/Texture.h
@@ -38,170 +38,239 @@ enum
     // The actual GL caps are limited by the device caps
     // and should be queried from the Context
     IMPLEMENTATION_MAX_TEXTURE_SIZE = 16384,
     IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
 
     IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15   // 1+log2 of MAX_TEXTURE_SIZE
 };
 
+class Image
+{
+  public:
+    Image();
+    ~Image();
+
+    bool redefine(GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRelease);
+    void markDirty() {mDirty = true;}
+    void markClean() {mDirty = false;}
+
+    HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
+    void unlock();
+
+    bool isRenderable() const;
+    D3DFORMAT getD3DFormat() const;
+
+    GLsizei getWidth() const {return mWidth;}
+    GLsizei getHeight() const {return mHeight;}
+    GLenum getFormat() const {return mFormat;}
+    GLenum getType() const {return mType;}
+    bool isDirty() const {return mSurface && mDirty;}
+    IDirect3DSurface9 *getSurface();
+
+    void setManagedSurface(IDirect3DSurface9 *surface);
+    void updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+    void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum type,
+                  GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output) const;
+
+    void loadAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                       int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                            int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadLuminanceData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
+    void loadLuminanceFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadLuminanceHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                    int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadLuminanceAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
+    void loadLuminanceAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                     int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadLuminanceAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                         int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGB565Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                        int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBAUByteDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                               int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBAUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBA4444Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBA5551Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBAFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBAHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                               int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadBGRAData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                      int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                            int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadDXT1Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                      int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadDXT3Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                      int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadDXT5Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                      int inputPitch, const void *input, size_t outputPitch, void *output) const;
+
+    void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Image);
+
+    void createSurface();
+
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLenum mFormat;
+    GLenum mType;
+
+    bool mDirty;
+    bool mManaged;
+
+    IDirect3DSurface9 *mSurface;
+};
+
+class TextureStorage
+{
+  public:
+    explicit TextureStorage(bool renderable);
+
+    virtual ~TextureStorage();
+
+    bool isRenderable() const;
+    bool isManaged() const;
+    unsigned int getTextureSerial() const;
+    virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureStorage);
+
+    const bool mRenderable;
+    const bool mManaged;
+
+    const unsigned int mTextureSerial;
+    static unsigned int issueTextureSerial();
+
+    static unsigned int mCurrentTextureSerial;
+};
+
 class Texture : public RefCountObject
 {
   public:
     explicit Texture(GLuint id);
 
     virtual ~Texture();
 
     virtual GLenum getTarget() const = 0;
 
     bool setMinFilter(GLenum filter);
     bool setMagFilter(GLenum filter);
     bool setWrapS(GLenum wrap);
     bool setWrapT(GLenum wrap);
+    bool setUsage(GLenum usage);
 
     GLenum getMinFilter() const;
     GLenum getMagFilter() const;
     GLenum getWrapS() const;
     GLenum getWrapT() const;
+    GLenum getUsage() const;
 
     virtual GLsizei getWidth() const = 0;
     virtual GLsizei getHeight() const = 0;
     virtual GLenum getInternalFormat() const = 0;
     virtual GLenum getType() const = 0;
     virtual D3DFORMAT getD3DFormat() const = 0;
 
-    virtual bool isComplete() const = 0;
+    virtual bool isSamplerComplete() const = 0;
     virtual bool isCompressed() const = 0;
 
     IDirect3DBaseTexture9 *getTexture();
     virtual Renderbuffer *getRenderbuffer(GLenum target) = 0;
 
     virtual void generateMipmaps() = 0;
     virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;
 
-    bool isDirtyParameter() const;
-    bool isDirtyImage() const;
+    bool hasDirtyParameters() const;
+    bool hasDirtyImages() const;
     void resetDirty();
-    unsigned int getSerial() const;
+    unsigned int getTextureSerial() const;
+    unsigned int getRenderTargetSerial(GLenum target) const;
+
+    bool isImmutable() const;
 
     static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1);   // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
 
   protected:
-    friend class Colorbuffer;
-
-    // Helper structure representing a single image layer
-    struct Image
-    {
-        Image();
-        ~Image();
-
-        bool isRenderable() const;
-        D3DFORMAT getD3DFormat() const;
-
-        GLsizei width;
-        GLsizei height;
-        GLenum format;
-        GLenum type;
-
-        bool dirty;
-
-        IDirect3DSurface9 *surface;
-    };
+    friend class RenderbufferTexture;
 
     void setImage(GLint unpackAlignment, const void *pixels, Image *image);
     bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image);
     void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
     bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image);
-    void copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
 
-    GLint creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const;
-    GLint creationLevels(GLsizei size, GLint maxlevel) const;
+    GLint creationLevels(GLsizei width, GLsizei height) const;
+    GLint creationLevels(GLsizei size) const;
 
     virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
     virtual void createTexture() = 0;
     virtual void updateTexture() = 0;
     virtual void convertToRenderTarget() = 0;
     virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0;
 
-    void createSurface(Image *image);
+    int levelCount() const;
 
-    Blit *getBlitter();
-
-    int levelCount() const;
+    static Blit *getBlitter();
+    static bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
 
     GLenum mMinFilter;
     GLenum mMagFilter;
     GLenum mWrapS;
     GLenum mWrapT;
-    bool mDirtyParameter;
+    bool mDirtyParameters;
+    GLenum mUsage;
 
-    bool mDirtyImage;
+    bool mDirtyImages;
 
-    bool mIsRenderable;
+    bool mImmutable;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture);
 
-    void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
-                       GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output, D3DSURFACE_DESC *description) const;
+    virtual TextureStorage *getStorage() const = 0;
+};
+
+class TextureStorage2D : public TextureStorage
+{
+  public:
+    explicit TextureStorage2D(IDirect3DTexture9 *surfaceTexture);
+    TextureStorage2D(int levels, D3DFORMAT format, int width, int height, bool renderable);
+
+    virtual ~TextureStorage2D();
 
-    void loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                            int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                 int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
-    void loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
-    void loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                              int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                               int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                             int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                               int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBAUByteImageDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                               int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                               int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                 int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadDXT1ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadDXT3ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
-    void loadDXT5ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    IDirect3DSurface9 *getSurfaceLevel(int level);
+    IDirect3DBaseTexture9 *getBaseTexture() const;
+
+    virtual unsigned int getRenderTargetSerial(GLenum target) const;
 
-    static unsigned int issueSerial();
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureStorage2D);
 
-    const unsigned int mSerial;
-
-    static unsigned int mCurrentSerial;
+    IDirect3DTexture9 *mTexture;
+    const unsigned int mRenderTargetSerial;
 };
 
 class Texture2D : public Texture
 {
   public:
     explicit Texture2D(GLuint id);
 
     ~Texture2D();
@@ -214,47 +283,70 @@ class Texture2D : public Texture
     virtual GLenum getType() const;
     virtual D3DFORMAT getD3DFormat() const;
 
     void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
     void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
     void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
     void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
     void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
-    void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
 
-    virtual bool isComplete() const;
+    virtual bool isSamplerComplete() const;
     virtual bool isCompressed() const;
     virtual void bindTexImage(egl::Surface *surface);
     virtual void releaseTexImage();
 
     virtual void generateMipmaps();
 
     virtual Renderbuffer *getRenderbuffer(GLenum target);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture2D);
 
     virtual IDirect3DBaseTexture9 *getBaseTexture() const;
     virtual void createTexture();
     virtual void updateTexture();
     virtual void convertToRenderTarget();
     virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
+    virtual TextureStorage *getStorage() const;
 
-    void redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool force);
+    bool isMipmapComplete() const;
+
+    void redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
     void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
 
     Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 
-    IDirect3DTexture9 *mTexture;
+    TextureStorage2D *mTexture;
     egl::Surface *mSurface;
 
     BindingPointer<Renderbuffer> mColorbufferProxy;
 };
 
+class TextureStorageCubeMap : public TextureStorage
+{
+  public:
+    TextureStorageCubeMap(int levels, D3DFORMAT format, int size, bool renderable);
+
+    virtual ~TextureStorageCubeMap();
+
+    IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level);
+    IDirect3DBaseTexture9 *getBaseTexture() const;
+
+    virtual unsigned int getRenderTargetSerial(GLenum target) const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureStorageCubeMap);
+
+    IDirect3DCubeTexture9 *mTexture;
+    const unsigned int mFirstRenderTargetSerial;
+};
+
 class TextureCubeMap : public Texture
 {
   public:
     explicit TextureCubeMap(GLuint id);
 
     ~TextureCubeMap();
 
     virtual GLenum getTarget() const;
@@ -273,46 +365,45 @@ class TextureCubeMap : public Texture
     void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
 
     void setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
 
     void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
     void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
     void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
     virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    void storage(GLsizei levels, GLenum internalformat, GLsizei size);
 
-    virtual bool isComplete() const;
+    virtual bool isSamplerComplete() const;
     virtual bool isCompressed() const;
 
     virtual void generateMipmaps();
 
     virtual Renderbuffer *getRenderbuffer(GLenum target);
 
+    static unsigned int faceIndex(GLenum face);
+
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
 
     virtual IDirect3DBaseTexture9 *getBaseTexture() const;
     virtual void createTexture();
     virtual void updateTexture();
     virtual void convertToRenderTarget();
     virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
-
-    // face is one of the GL_TEXTURE_CUBE_MAP_* enumerants.
-    // Returns NULL if the call underlying Direct3D call fails.
-    IDirect3DSurface9 *getCubeMapSurface(GLenum face, unsigned int level);
-
-    static unsigned int faceIndex(GLenum face);
+    virtual TextureStorage *getStorage() const;
 
     bool isCubeComplete() const;
+    bool isMipmapCubeComplete() const;
 
     void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
-    void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    void redefineTexture(int faceIndex, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
+    void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+    void redefineImage(int faceIndex, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
 
     Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 
-    IDirect3DCubeTexture9 *mTexture;
+    TextureStorageCubeMap *mTexture;
 
     BindingPointer<Renderbuffer> mFaceProxies[6];
 };
 }
 
-#endif   // LIBGLESV2_TEXTURE_H_
+#endif   // LIBGLESV2_TEXTURE_H_
\ No newline at end of file
--- a/gfx/angle/src/libGLESv2/VertexDataManager.cpp
+++ b/gfx/angle/src/libGLESv2/VertexDataManager.cpp
@@ -24,16 +24,22 @@ namespace
     // This has to be at least 4k or else it fails on ATI cards.
     enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
 }
 
 namespace gl
 {
 unsigned int VertexBuffer::mCurrentSerial = 1;
 
+int elementsInBuffer(const VertexAttribute &attribute, int size)
+{
+    int stride = attribute.stride();
+    return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
+}
+
 VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device)
 {
     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
     {
         mDirtyCurrentValue[i] = true;
         mCurrentValueBuffer[i] = NULL;
         mCurrentValueOffsets[i] = 0;
     }
@@ -132,17 +138,17 @@ GLenum VertexDataManager::prepareVertexD
         {
             Buffer *buffer = attribs[i].mBoundBuffer.get();
             StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
 
             if (staticBuffer)
             {
                 if (staticBuffer->size() == 0)
                 {
-                    int totalCount = buffer->size() / attribs[i].stride();
+                    int totalCount = elementsInBuffer(attribs[i], buffer->size());
                     staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount));
                 }
                 else if (staticBuffer->lookupAttribute(attribs[i]) == -1)
                 {
                     // This static buffer doesn't have matching attributes, so fall back to using the streaming buffer
                     // Add the space of all previous attributes belonging to the invalidated static buffer to the streaming buffer
                     for (int previous = 0; previous < i; previous++)
                     {
@@ -211,17 +217,17 @@ GLenum VertexDataManager::prepareVertexD
 
                 if (staticBuffer)
                 {
                     streamOffset = staticBuffer->lookupAttribute(attribs[i]);
 
                     if (streamOffset == -1)
                     {
                         // Convert the entire buffer
-                        int totalCount = buffer->size() / attribs[i].stride();
+                        int totalCount = elementsInBuffer(attribs[i], buffer->size());
                         int startIndex = attribs[i].mOffset / attribs[i].stride();
 
                         streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i]);
                     }
 
                     if (streamOffset != -1)
                     {
                         streamOffset += (start + attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize;
--- a/gfx/angle/src/libGLESv2/libGLESv2.cpp
+++ b/gfx/angle/src/libGLESv2/libGLESv2.cpp
@@ -48,26 +48,66 @@ bool validImageSize(GLint level, GLsizei
     if (gl::isPow2(width) && gl::isPow2(height))
     {
         return true;
     }
 
     return false;
 }
 
+// check for combinations of format and type that are valid for ReadPixels
+bool validReadFormatType(GLenum format, GLenum type)
+{
+    switch (format)
+    {
+      case GL_RGBA:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:
+            break;
+          default:
+            return false;
+        }
+        break;
+      case GL_BGRA_EXT:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:
+          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+            break;
+          default:
+            return false;
+        }
+        break;
+      case gl::IMPLEMENTATION_COLOR_READ_FORMAT:
+        switch (type)
+        {
+          case gl::IMPLEMENTATION_COLOR_READ_TYPE:
+            break;
+          default:
+            return false;
+        }
+        break;
+      default:
+        return false;
+    }
+    return true;
+}
+
 extern "C"
 {
 
 void __stdcall glActiveTexture(GLenum texture)
 {
     EVENT("(GLenum texture = 0x%X)", texture);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1)
             {
                 return error(GL_INVALID_ENUM);
             }
 
@@ -81,17 +121,17 @@ void __stdcall glActiveTexture(GLenum te
 }
 
 void __stdcall glAttachShader(GLuint program, GLuint shader)
 {
     EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Program *programObject = context->getProgram(program);
             gl::Shader *shaderObject = context->getShader(shader);
 
             if (!programObject)
             {
@@ -135,17 +175,17 @@ void __stdcall glBindAttribLocation(GLui
 
     try
     {
         if (index >= gl::MAX_VERTEX_ATTRIBS)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Program *programObject = context->getProgram(program);
 
             if (!programObject)
             {
                 if (context->getShader(program))
@@ -173,17 +213,17 @@ void __stdcall glBindAttribLocation(GLui
 }
 
 void __stdcall glBindBuffer(GLenum target, GLuint buffer)
 {
     EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             switch (target)
             {
               case GL_ARRAY_BUFFER:
                 context->bindArrayBuffer(buffer);
                 return;
@@ -207,17 +247,17 @@ void __stdcall glBindFramebuffer(GLenum 
 
     try
     {
         if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
         {
             return error(GL_INVALID_ENUM);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
             {
                 context->bindReadFramebuffer(framebuffer);
             }
             
@@ -239,17 +279,17 @@ void __stdcall glBindRenderbuffer(GLenum
 
     try
     {
         if (target != GL_RENDERBUFFER)
         {
             return error(GL_INVALID_ENUM);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->bindRenderbuffer(renderbuffer);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -258,17 +298,17 @@ void __stdcall glBindRenderbuffer(GLenum
 }
 
 void __stdcall glBindTexture(GLenum target, GLuint texture)
 {
     EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Texture *textureObject = context->getTexture(texture);
 
             if (textureObject && textureObject->getTarget() != target && texture != 0)
             {
                 return error(GL_INVALID_OPERATION);
@@ -295,17 +335,17 @@ void __stdcall glBindTexture(GLenum targ
 
 void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 {
     EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
           red, green, blue, alpha);
 
     try
     {
-        gl::Context* context = gl::getContext();
+        gl::Context* context = gl::getNonLostContext();
 
         if (context)
         {
             context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
         }
     }
     catch(std::bad_alloc&)
     {
@@ -339,17 +379,17 @@ void __stdcall glBlendEquationSeparate(G
           case GL_FUNC_ADD:
           case GL_FUNC_SUBTRACT:
           case GL_FUNC_REVERSE_SUBTRACT:
             break;
           default:
             return error(GL_INVALID_ENUM);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setBlendEquation(modeRGB, modeAlpha);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -462,17 +502,17 @@ void __stdcall glBlendFuncSeparate(GLenu
                                   dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
 
         if (constantColorUsed && constantAlphaUsed)
         {
             ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL");
             return error(GL_INVALID_OPERATION);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -497,17 +537,17 @@ void __stdcall glBufferData(GLenum targe
           case GL_STREAM_DRAW:
           case GL_STATIC_DRAW:
           case GL_DYNAMIC_DRAW:
             break;
           default:
             return error(GL_INVALID_ENUM);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Buffer *buffer;
 
             switch (target)
             {
               case GL_ARRAY_BUFFER:
@@ -546,17 +586,17 @@ void __stdcall glBufferSubData(GLenum ta
             return error(GL_INVALID_VALUE);
         }
 
         if (data == NULL)
         {
             return;
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Buffer *buffer;
 
             switch (target)
             {
               case GL_ARRAY_BUFFER:
@@ -594,17 +634,17 @@ GLenum __stdcall glCheckFramebufferStatu
 
     try
     {
         if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
         {
             return error(GL_INVALID_ENUM, 0);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Framebuffer *framebuffer = NULL;
             if (target == GL_READ_FRAMEBUFFER_ANGLE)
             {
                 framebuffer = context->getReadFramebuffer();
             }
@@ -625,17 +665,17 @@ GLenum __stdcall glCheckFramebufferStatu
 }
 
 void __stdcall glClear(GLbitfield mask)
 {
     EVENT("(GLbitfield mask = %X)", mask);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->clear(mask);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -645,17 +685,17 @@ void __stdcall glClear(GLbitfield mask)
 
 void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 {
     EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
           red, green, blue, alpha);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setClearColor(red, green, blue, alpha);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -664,17 +704,17 @@ void __stdcall glClearColor(GLclampf red
 }
 
 void __stdcall glClearDepthf(GLclampf depth)
 {
     EVENT("(GLclampf depth = %f)", depth);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setClearDepth(depth);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -683,17 +723,17 @@ void __stdcall glClearDepthf(GLclampf de
 }
 
 void __stdcall glClearStencil(GLint s)
 {
     EVENT("(GLint s = %d)", s);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setClearStencil(s);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -703,17 +743,17 @@ void __stdcall glClearStencil(GLint s)
 
 void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
 {
     EVENT("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
           red, green, blue, alpha);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -722,17 +762,17 @@ void __stdcall glColorMask(GLboolean red
 }
 
 void __stdcall glCompileShader(GLuint shader)
 {
     EVENT("(GLuint shader = %d)", shader);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Shader *shaderObject = context->getShader(shader);
 
             if (!shaderObject)
             {
                 if (context->getProgram(shader))
@@ -779,17 +819,17 @@ void __stdcall glCompressedTexImage2D(GL
             return error(GL_INVALID_ENUM);
         }
 
         if (border != 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (level > context->getMaximumTextureLevel())
             {
                 return error(GL_INVALID_VALUE);
             }
 
@@ -855,27 +895,37 @@ void __stdcall glCompressedTexImage2D(GL
             {
                 gl::Texture2D *texture = context->getTexture2D();
 
                 if (!texture)
                 {
                     return error(GL_INVALID_OPERATION);
                 }
 
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
                 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
             }
             else
             {
                 gl::TextureCubeMap *texture = context->getTextureCubeMap();
 
                 if (!texture)
                 {
                     return error(GL_INVALID_OPERATION);
                 }
 
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
                 switch (target)
                 {
                   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
                   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
                   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
                   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
                   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
                   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
@@ -924,17 +974,17 @@ void __stdcall glCompressedTexSubImage2D
             return error(GL_INVALID_ENUM);
         }
 
         if (width == 0 || height == 0 || data == NULL)
         {
             return;
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (level > context->getMaximumTextureLevel())
             {
                 return error(GL_INVALID_VALUE);
             }
 
@@ -1041,20 +1091,25 @@ void __stdcall glCopyTexImage2D(GLenum t
             return error(GL_INVALID_VALUE);
         }
 
         if (border != 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
             switch (target)
             {
               case GL_TEXTURE_2D:
                 if (width > (context->getMaximumTextureDimension() >> level) ||
                     height > (context->getMaximumTextureDimension() >> level))
                 {
                     return error(GL_INVALID_VALUE);
                 }
@@ -1087,17 +1142,17 @@ void __stdcall glCopyTexImage2D(GLenum t
                 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
             }
 
             if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0)
             {
                 return error(GL_INVALID_OPERATION);
             }
 
-            gl::Colorbuffer *source = framebuffer->getColorbuffer();
+            gl::Renderbuffer *source = framebuffer->getColorbuffer();
             GLenum colorbufferFormat = source->getInternalFormat();
 
             // [OpenGL ES 2.0.24] table 3.9
             switch (internalformat)
             {
               case GL_ALPHA:
                 if (colorbufferFormat != GL_ALPHA &&
                     colorbufferFormat != GL_RGBA &&
@@ -1170,27 +1225,37 @@ void __stdcall glCopyTexImage2D(GLenum t
             {
                 gl::Texture2D *texture = context->getTexture2D();
 
                 if (!texture)
                 {
                     return error(GL_INVALID_OPERATION);
                 }
 
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
                 texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
             }
             else if (gl::IsCubemapTextureTarget(target))
             {
                 gl::TextureCubeMap *texture = context->getTextureCubeMap();
 
                 if (!texture)
                 {
                     return error(GL_INVALID_OPERATION);
                 }
 
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
                 texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
             }
             else UNREACHABLE();
         }
     }
     catch(std::bad_alloc&)
     {
         return error(GL_OUT_OF_MEMORY);
@@ -1220,17 +1285,17 @@ void __stdcall glCopyTexSubImage2D(GLenu
             return error(GL_INVALID_VALUE);
         }
 
         if (width == 0 || height == 0)
         {
             return;
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (level > context->getMaximumTextureLevel())
             {
                 return error(GL_INVALID_VALUE);
             }
 
@@ -1241,17 +1306,17 @@ void __stdcall glCopyTexSubImage2D(GLenu
                 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
             }
 
             if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0)
             {
                 return error(GL_INVALID_OPERATION);
             }
 
-            gl::Colorbuffer *source = framebuffer->getColorbuffer();
+            gl::Renderbuffer *source = framebuffer->getColorbuffer();
             GLenum colorbufferFormat = source->getInternalFormat();
             gl::Texture *texture = NULL;
 
             if (target == GL_TEXTURE_2D)
             {
                 texture = context->getTexture2D();
             }
             else if (gl::IsCubemapTextureTarget(target))
@@ -1323,17 +1388,17 @@ void __stdcall glCopyTexSubImage2D(GLenu
 }
 
 GLuint __stdcall glCreateProgram(void)
 {
     EVENT("()");
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             return context->createProgram();
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1344,17 +1409,17 @@ GLuint __stdcall glCreateProgram(void)
 }
 
 GLuint __stdcall glCreateShader(GLenum type)
 {
     EVENT("(GLenum type = 0x%X)", type);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             switch (type)
             {
               case GL_FRAGMENT_SHADER:
               case GL_VERTEX_SHADER:
                 return context->createShader(type);
@@ -1378,17 +1443,17 @@ void __stdcall glCullFace(GLenum mode)
     try
     {
         switch (mode)
         {
           case GL_FRONT:
           case GL_BACK:
           case GL_FRONT_AND_BACK:
             {
-                gl::Context *context = gl::getContext();
+                gl::Context *context = gl::getNonLostContext();
 
                 if (context)
                 {
                     context->setCullMode(mode);
                 }
             }
             break;
           default:
@@ -1407,17 +1472,17 @@ void __stdcall glDeleteBuffers(GLsizei n
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 context->deleteBuffer(buffers[i]);
             }
         }
@@ -1434,17 +1499,17 @@ void __stdcall glDeleteFencesNV(GLsizei 
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 context->deleteFence(fences[i]);
             }
         }
@@ -1461,17 +1526,17 @@ void __stdcall glDeleteFramebuffers(GLsi
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 if (framebuffers[i] != 0)
                 {
                     context->deleteFramebuffer(framebuffers[i]);
@@ -1491,17 +1556,17 @@ void __stdcall glDeleteProgram(GLuint pr
 
     try
     {
         if (program == 0)
         {
             return;
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (!context->getProgram(program))
             {
                 if(context->getShader(program))
                 {
                     return error(GL_INVALID_OPERATION);
@@ -1527,17 +1592,17 @@ void __stdcall glDeleteRenderbuffers(GLs
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 context->deleteRenderbuffer(renderbuffers[i]);
             }
         }
@@ -1554,17 +1619,17 @@ void __stdcall glDeleteShader(GLuint sha
 
     try
     {
         if (shader == 0)
         {
             return;
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (!context->getShader(shader))
             {
                 if(context->getProgram(shader))
                 {
                     return error(GL_INVALID_OPERATION);
@@ -1590,17 +1655,17 @@ void __stdcall glDeleteTextures(GLsizei 
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 if (textures[i] != 0)
                 {
                     context->deleteTexture(textures[i]);
@@ -1630,17 +1695,17 @@ void __stdcall glDepthFunc(GLenum func)
           case GL_GREATER:
           case GL_GEQUAL:
           case GL_NOTEQUAL:
             break;
           default:
             return error(GL_INVALID_ENUM);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setDepthFunc(func);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1649,17 +1714,17 @@ void __stdcall glDepthFunc(GLenum func)
 }
 
 void __stdcall glDepthMask(GLboolean flag)
 {
     EVENT("(GLboolean flag = %d)", flag);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setDepthMask(flag != GL_FALSE);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1668,17 +1733,17 @@ void __stdcall glDepthMask(GLboolean fla
 }
 
 void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
 {
     EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setDepthRange(zNear, zFar);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1687,17 +1752,17 @@ void __stdcall glDepthRangef(GLclampf zN
 }
 
 void __stdcall glDetachShader(GLuint program, GLuint shader)
 {
     EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
 
             gl::Program *programObject = context->getProgram(program);
             gl::Shader *shaderObject = context->getShader(shader);
             
             if (!programObject)
@@ -1740,17 +1805,17 @@ void __stdcall glDetachShader(GLuint pro
 }
 
 void __stdcall glDisable(GLenum cap)
 {
     EVENT("(GLenum cap = 0x%X)", cap);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             switch (cap)
             {
               case GL_CULL_FACE:                context->setCullFace(false);              break;
               case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(false);     break;
               case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
@@ -1777,17 +1842,17 @@ void __stdcall glDisableVertexAttribArra
 
     try
     {
         if (index >= gl::MAX_VERTEX_ATTRIBS)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setEnableVertexAttribArray(index, false);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1801,17 +1866,17 @@ void __stdcall glDrawArrays(GLenum mode,
 
     try
     {
         if (count < 0 || first < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->drawArrays(mode, first, count);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1826,17 +1891,17 @@ void __stdcall glDrawElements(GLenum mod
 
     try
     {
         if (count < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             switch (type)
             {
               case GL_UNSIGNED_BYTE:
               case GL_UNSIGNED_SHORT:
                 break;
@@ -1860,17 +1925,17 @@ void __stdcall glDrawElements(GLenum mod
 }
 
 void __stdcall glEnable(GLenum cap)
 {
     EVENT("(GLenum cap = 0x%X)", cap);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             switch (cap)
             {
               case GL_CULL_FACE:                context->setCullFace(true);              break;
               case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(true);     break;
               case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
@@ -1897,17 +1962,17 @@ void __stdcall glEnableVertexAttribArray
 
     try
     {
         if (index >= gl::MAX_VERTEX_ATTRIBS)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->setEnableVertexAttribArray(index, true);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1916,17 +1981,17 @@ void __stdcall glEnableVertexAttribArray
 }
 
 void __stdcall glFinishFenceNV(GLuint fence)
 {
     EVENT("(GLuint fence = %d)", fence);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Fence* fenceObject = context->getFence(fence);
 
             if (fenceObject == NULL)
             {
                 return error(GL_INVALID_OPERATION);
@@ -1942,17 +2007,17 @@ void __stdcall glFinishFenceNV(GLuint fe
 }
 
 void __stdcall glFinish(void)
 {
     EVENT("()");
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->sync(true);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1961,17 +2026,17 @@ void __stdcall glFinish(void)
 }
 
 void __stdcall glFlush(void)
 {
     EVENT("()");
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             context->sync(false);
         }
     }
     catch(std::bad_alloc&)
     {
@@ -1987,17 +2052,17 @@ void __stdcall glFramebufferRenderbuffer
     try
     {
         if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
             || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
         {
             return error(GL_INVALID_ENUM);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Framebuffer *framebuffer = NULL;
             GLuint framebufferHandle = 0;
             if (target == GL_READ_FRAMEBUFFER_ANGLE)
             {
                 framebuffer = context->getReadFramebuffer();
@@ -2053,17 +2118,17 @@ void __stdcall glFramebufferTexture2D(GL
           case GL_COLOR_ATTACHMENT0:
           case GL_DEPTH_ATTACHMENT:
           case GL_STENCIL_ATTACHMENT:
             break;
           default:
             return error(GL_INVALID_ENUM);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (texture == 0)
             {
                 textarget = GL_NONE;
             }
             else
@@ -2149,17 +2214,17 @@ void __stdcall glFrontFace(GLenum mode)
 
     try
     {
         switch (mode)
         {
           case GL_CW:
           case GL_CCW:
             {
-                gl::Context *context = gl::getContext();
+                gl::Context *context = gl::getNonLostContext();
 
                 if (context)
                 {
                     context->setFrontFace(mode);
                 }
             }
             break;
           default:
@@ -2178,17 +2243,17 @@ void __stdcall glGenBuffers(GLsizei n, G
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 buffers[i] = context->createBuffer();
             }
         }
@@ -2200,17 +2265,17 @@ void __stdcall glGenBuffers(GLsizei n, G
 }
 
 void __stdcall glGenerateMipmap(GLenum target)
 {
     EVENT("(GLenum target = 0x%X)", target);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Texture *texture;
 
             switch (target)
             {
               case GL_TEXTURE_2D:
@@ -2245,17 +2310,17 @@ void __stdcall glGenFencesNV(GLsizei n, 
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 fences[i] = context->createFence();
             }
         }
@@ -2272,17 +2337,17 @@ void __stdcall glGenFramebuffers(GLsizei
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 framebuffers[i] = context->createFramebuffer();
             }
         }
@@ -2299,17 +2364,17 @@ void __stdcall glGenRenderbuffers(GLsize
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 renderbuffers[i] = context->createRenderbuffer();
             }
         }
@@ -2326,17 +2391,17 @@ void __stdcall glGenTextures(GLsizei n, 
 
     try
     {
         if (n < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             for (int i = 0; i < n; i++)
             {
                 textures[i] = context->createTexture();
             }
         }
@@ -2355,17 +2420,17 @@ void __stdcall glGetActiveAttrib(GLuint 
 
     try
     {
         if (bufsize < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Program *programObject = context->getProgram(program);
 
             if (!programObject)
             {
                 if (context->getShader(program))
@@ -2400,17 +2465,17 @@ void __stdcall glGetActiveUniform(GLuint
 
     try
     {
         if (bufsize < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Program *programObject = context->getProgram(program);
 
             if (!programObject)
             {
                 if (context->getShader(program))
@@ -2444,17 +2509,17 @@ void __stdcall glGetAttachedShaders(GLui
 
     try
     {
         if (maxcount < 0)
         {
             return error(GL_INVALID_VALUE);
         }
 
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Program *programObject = context->getProgram(program);
 
             if (!programObject)
             {
                 if (context->getShader(program))
@@ -2477,17 +2542,17 @@ void __stdcall glGetAttachedShaders(GLui
 }
 
 int __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
 {
     EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
 
             gl::Program *programObject = context->getProgram(program);
 
             if (!programObject)
             {
@@ -2518,17 +2583,17 @@ int __stdcall glGetAttribLocation(GLuint
 }
 
 void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
 {
     EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)",  pname, params);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             if (!(context->getBooleanv(pname, params)))
             {
                 GLenum nativeType;
                 unsigned int numParams = 0;
                 if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
@@ -2581,17 +2646,17 @@ void __stdcall glGetBooleanv(GLenum pnam
 }
 
 void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Buffer *buffer;
 
             switch (target)
             {
               case GL_ARRAY_BUFFER:
@@ -2630,30 +2695,33 @@ void __stdcall glGetBufferParameteriv(GL
 GLenum __stdcall glGetError(void)
 {
     EVENT("()");
 
     gl::Context *context = gl::getContext();
 
     if (context)
     {
-        return context->getError();
+        if (context->isContextLost())
+            return GL_OUT_OF_MEMORY;
+        else
+            return context->getError();
     }
 
     return GL_NO_ERROR;
 }
 
 void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
 {
     EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
 
     try
     {
     
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();
 
         if (context)
         {
             gl::Fence *fenceObject = context->getFence(fence);
 
             if (fenceObject == NULL)
             {
                 return error(GL_INVALID_OPERATION);
@@ -2669,17 +2737,17 @@ void __stdcall glGetFenceivNV(GLuint fen
 }
 
 void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
 {
     EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
 
     try
     {
-        gl::Context *context = gl::getContext();
+        gl::Context *context = gl::getNonLostContext();