Fix FBO/Texture/renderbuffer class hierarchy issues
TRAC #14744
Issue=51/52
Delegated format queries to RenderbufferStorage.
Eliminated TextureColorbufferProxy by merging it into Colorbuffer.
Abstracted texture colorbuffer queries.
Moved some conversion functions to the right namespace.
Fixed line-endings in Texture.cpp
Signed-off-by: Daniel Koch

Author:    Nicolas Capens <nicolas@transgaming.com>

git-svn-id: https://angleproject.googlecode.com/svn/trunk@553 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index bfa4d2a..d3c4ff7 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -2378,7 +2378,7 @@
             D3DSURFACE_DESC desc;
             depthStencil->GetDesc(&desc);
 
-            unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
+            unsigned int stencilSize = dx2es::GetStencilSize(desc.Format);
             stencilUnmasked = (0x1 << stencilSize) - 1;
 
             if (stencilUnmasked != 0x0)
@@ -2415,7 +2415,7 @@
     D3DSURFACE_DESC desc;
     renderTarget->GetDesc(&desc);
 
-    bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
+    bool alphaUnmasked = (dx2es::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
 
     const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
                                         (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
diff --git a/src/libGLESv2/Framebuffer.cpp b/src/libGLESv2/Framebuffer.cpp
index 5fe01e0..dd34725 100644
--- a/src/libGLESv2/Framebuffer.cpp
+++ b/src/libGLESv2/Framebuffer.cpp
@@ -46,7 +46,7 @@
     }
     else if (IsTextureTarget(type))
     {
-        buffer = context->getTexture(handle)->getColorbuffer(type);
+        buffer = context->getTexture(handle)->getRenderbuffer(type);
     }
     else
     {
@@ -307,14 +307,14 @@
 
         if (mColorbufferType == GL_RENDERBUFFER)
         {
-            if (!gl::IsColorRenderable(colorbuffer->getFormat()))
+            if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
             {
                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
             }
         }
         else if (IsTextureTarget(mColorbufferType))
         {
-            if (IsCompressed(colorbuffer->getFormat()))
+            if (IsCompressed(colorbuffer->getInternalFormat()))
             {
                 return GL_FRAMEBUFFER_UNSUPPORTED;
             }
@@ -325,7 +325,7 @@
                 return GL_FRAMEBUFFER_UNSUPPORTED;
             }
 
-            if (colorbuffer->getFormat() == GL_LUMINANCE || colorbuffer->getFormat() == GL_LUMINANCE_ALPHA)
+            if (colorbuffer->getInternalFormat() == GL_LUMINANCE || colorbuffer->getInternalFormat() == GL_LUMINANCE_ALPHA)
             {
                 return GL_FRAMEBUFFER_UNSUPPORTED;
             }
@@ -424,8 +424,8 @@
 
     if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER)
     {
-        if (depthbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
-            stencilbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
+        if (depthbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
+            stencilbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
             depthbuffer->getSerial() != stencilbuffer->getSerial())
         {
             return GL_FRAMEBUFFER_UNSUPPORTED;
diff --git a/src/libGLESv2/Renderbuffer.cpp b/src/libGLESv2/Renderbuffer.cpp
index 6e4494b..7597504 100644
--- a/src/libGLESv2/Renderbuffer.cpp
+++ b/src/libGLESv2/Renderbuffer.cpp
@@ -54,24 +54,54 @@
     return mStorage->getDepthStencil();
 }
 
-int Renderbuffer::getWidth() const
+GLsizei Renderbuffer::getWidth() const
 {
     return mStorage->getWidth();
 }
 
-int Renderbuffer::getHeight() const
+GLsizei Renderbuffer::getHeight() const
 {
     return mStorage->getHeight();
 }
 
-GLenum Renderbuffer::getFormat() const
+GLenum Renderbuffer::getInternalFormat() const
 {
-    return mStorage->getFormat();
+    return mStorage->getInternalFormat();
 }
 
-D3DFORMAT Renderbuffer::getD3DFormat() const
+GLuint Renderbuffer::getRedSize() const
 {
-    return mStorage->getD3DFormat();
+    return mStorage->getRedSize();
+}
+
+GLuint Renderbuffer::getGreenSize() const
+{
+    return mStorage->getGreenSize();
+}
+
+GLuint Renderbuffer::getBlueSize() const
+{
+    return mStorage->getBlueSize();
+}
+
+GLuint Renderbuffer::getAlphaSize() const
+{
+    return mStorage->getAlphaSize();
+}
+
+GLuint Renderbuffer::getDepthSize() const
+{
+    return mStorage->getDepthSize();
+}
+
+GLuint Renderbuffer::getStencilSize() const
+{
+    return mStorage->getStencilSize();
+}
+
+GLsizei Renderbuffer::getSamples() const
+{
+    return mStorage->getSamples();
 }
 
 unsigned int Renderbuffer::getSerial() const
@@ -91,7 +121,7 @@
 {
     mWidth = 0;
     mHeight = 0;
-    mFormat = GL_RGBA4;
+    mInternalFormat = GL_RGBA4;
     mD3DFormat = D3DFMT_A8R8G8B8;
     mSamples = 0;
 }
@@ -125,35 +155,49 @@
     return NULL;
 }
 
-int RenderbufferStorage::getWidth() const
+GLsizei RenderbufferStorage::getWidth() const
 {
     return mWidth;
 }
 
-int RenderbufferStorage::getHeight() const
+GLsizei RenderbufferStorage::getHeight() const
 {
     return mHeight;
 }
 
-void RenderbufferStorage::setSize(int width, int height)
+GLenum RenderbufferStorage::getInternalFormat() const
 {
-    mWidth = width;
-    mHeight = height;
+    return mInternalFormat;
 }
 
-GLenum RenderbufferStorage::getFormat() const
+GLuint RenderbufferStorage::getRedSize() const
 {
-    return mFormat;
+    return dx2es::GetRedSize(getD3DFormat());
 }
 
-bool RenderbufferStorage::isFloatingPoint() const
+GLuint RenderbufferStorage::getGreenSize() const
 {
-    return false; // no floating point renderbuffers 
+    return dx2es::GetGreenSize(getD3DFormat());
 }
 
-D3DFORMAT RenderbufferStorage::getD3DFormat() const
+GLuint RenderbufferStorage::getBlueSize() const
 {
-    return mD3DFormat;
+    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());
 }
 
 GLsizei RenderbufferStorage::getSamples() const
@@ -161,6 +205,11 @@
     return mSamples;
 }
 
+D3DFORMAT RenderbufferStorage::getD3DFormat() const
+{
+    return mD3DFormat;
+}
+
 unsigned int RenderbufferStorage::getSerial() const
 {
     return mSerial;
@@ -171,7 +220,7 @@
     return mCurrentSerial++;
 }
 
-Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
+Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget), mTexture(NULL)
 {
     if (renderTarget)
     {
@@ -180,25 +229,32 @@
         D3DSURFACE_DESC description;
         renderTarget->GetDesc(&description);
 
-        setSize(description.Width, description.Height);
-        mFormat = dx2es::ConvertBackBufferFormat(description.Format);
+        mWidth = description.Width;
+        mHeight = description.Height;
+        mInternalFormat = dx2es::ConvertBackBufferFormat(description.Format);
         mD3DFormat = description.Format;
-        mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
+        mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType);
     }
 }
 
-Colorbuffer::Colorbuffer(const Texture* texture) : mRenderTarget(NULL)
+Colorbuffer::Colorbuffer(Texture *texture, GLenum target) : mRenderTarget(NULL), mTexture(texture), mTarget(target)
 {
-    setSize(texture->getWidth(), texture->getHeight());
-    mD3DFormat = texture->getD3DFormat();
-    mSamples = 0;
+    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)
+Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL), mTexture(NULL)
 {
     IDirect3DDevice9 *device = getDevice();
 
-    mRenderTarget = NULL;
     D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
     int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
 
@@ -226,8 +282,9 @@
 
     if (mRenderTarget)
     {
-        setSize(width, height);
-        mFormat = format;
+        mWidth = width;
+        mHeight = height;
+        mInternalFormat = format;
         mD3DFormat = requestedFormat;
         mSamples = supportedSamples;
     }
@@ -241,65 +298,73 @@
     }
 }
 
+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;
+}
+
+D3DFORMAT Colorbuffer::getD3DFormat() const
+{
+    if (mTexture)
+    {
+        return mTexture->getD3DFormat();
+    }
+
+    return mD3DFormat;
+}
+
+bool Colorbuffer::isFloatingPoint() const
+{
+    if (mTexture)
+    {
+        return mTexture->isFloatingPoint();
+    }
+
+    return false;
+}
+
 bool Colorbuffer::isColorbuffer() const
 {
     return true;
 }
 
-GLuint Colorbuffer::getRedSize() const
-{
-    if (mRenderTarget)
-    {
-        D3DSURFACE_DESC description;
-        mRenderTarget->GetDesc(&description);
-
-        return es2dx::GetRedSize(description.Format);
-    }
-
-    return 0;
-}
-
-GLuint Colorbuffer::getGreenSize() const
-{
-    if (mRenderTarget)
-    {
-        D3DSURFACE_DESC description;
-        mRenderTarget->GetDesc(&description);
-
-        return es2dx::GetGreenSize(description.Format);
-    }
-
-    return 0;
-}
-
-GLuint Colorbuffer::getBlueSize() const
-{
-    if (mRenderTarget)
-    {
-        D3DSURFACE_DESC description;
-        mRenderTarget->GetDesc(&description);
-
-        return es2dx::GetBlueSize(description.Format);
-    }
-
-    return 0;
-}
-
-GLuint Colorbuffer::getAlphaSize() const
-{
-    if (mRenderTarget)
-    {
-        D3DSURFACE_DESC description;
-        mRenderTarget->GetDesc(&description);
-
-        return es2dx::GetAlphaSize(description.Format);
-    }
-
-    return 0;
-}
-
 IDirect3DSurface9 *Colorbuffer::getRenderTarget()
 {
+    if (mTexture)
+    {
+        if (mRenderTarget)
+        {
+            mRenderTarget->Release();
+        }
+
+        mRenderTarget = mTexture->getRenderTarget(mTarget);
+    }
+
     return mRenderTarget;
 }
 
@@ -312,9 +377,10 @@
         D3DSURFACE_DESC description;
         depthStencil->GetDesc(&description);
 
-        setSize(description.Width, description.Height);
-        mFormat = dx2es::ConvertDepthStencilFormat(description.Format);
-        mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType); 
+        mWidth = description.Width;
+        mHeight = description.Height;
+        mInternalFormat = dx2es::ConvertDepthStencilFormat(description.Format);
+        mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType); 
         mD3DFormat = description.Format;
     }
 }
@@ -348,8 +414,9 @@
 
     if (mDepthStencil)
     {
-        setSize(width, height);
-        mFormat = GL_DEPTH24_STENCIL8_OES;
+        mWidth = width;
+        mHeight = height;
+        mInternalFormat = GL_DEPTH24_STENCIL8_OES;
         mD3DFormat = D3DFMT_D24S8;
         mSamples = supportedSamples;
     }
@@ -373,32 +440,6 @@
     return true;
 }
 
-GLuint DepthStencilbuffer::getDepthSize() const
-{
-    if (mDepthStencil)
-    {
-        D3DSURFACE_DESC description;
-        mDepthStencil->GetDesc(&description);
-
-        return es2dx::GetDepthSize(description.Format);
-    }
-
-    return 0;
-}
-
-GLuint DepthStencilbuffer::getStencilSize() const
-{
-    if (mDepthStencil)
-    {
-        D3DSURFACE_DESC description;
-        mDepthStencil->GetDesc(&description);
-
-        return es2dx::GetStencilSize(description.Format);
-    }
-
-    return 0;
-}
-
 IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
 {
     return mDepthStencil;
@@ -408,9 +449,9 @@
 {
     if (depthStencil)
     {
-        mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
-                                        // will expect one of the valid renderbuffer formats for use in 
-                                        // glRenderbufferStorage
+        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
     }
 }
 
@@ -418,9 +459,9 @@
 {
     if (getDepthStencil())
     {
-        mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
-                                        // will expect one of the valid renderbuffer formats for use in 
-                                        // glRenderbufferStorage
+        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
     }
 }
 
@@ -442,13 +483,9 @@
 {
     if (depthStencil)
     {
-        mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
-                                     // will expect one of the valid renderbuffer formats for use in 
-                                     // glRenderbufferStorage
-    }
-    else
-    {
-        mFormat = GL_RGBA4; //default format
+        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
     }
 }
 
@@ -456,9 +493,9 @@
 {
     if (getDepthStencil())
     {
-        mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
-                                     // will expect one of the valid renderbuffer formats for use in 
-                                     // glRenderbufferStorage
+        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
     }
 }
 
diff --git a/src/libGLESv2/Renderbuffer.h b/src/libGLESv2/Renderbuffer.h
index 98510c2..d6415bb 100644
--- a/src/libGLESv2/Renderbuffer.h
+++ b/src/libGLESv2/Renderbuffer.h
@@ -21,7 +21,7 @@
 
 namespace gl
 {
-    class Texture;
+class Texture;
 
 // A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
 // is called. The specific concrete type depends on whether the internal format is
@@ -40,34 +40,40 @@
     virtual IDirect3DSurface9 *getRenderTarget();
     virtual IDirect3DSurface9 *getDepthStencil();
 
-    virtual int getWidth() const;
-    virtual int getHeight() const;
-    virtual GLenum getFormat() const;
-    virtual bool isFloatingPoint() const;
-    D3DFORMAT getD3DFormat() const;
-    GLsizei getSamples() const;
+    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 GLsizei getSamples() const;
+
+    virtual D3DFORMAT getD3DFormat() const;
+
     unsigned int getSerial() const;
 
-    static unsigned int issueSerial();
-
   protected:
-    void setSize(int width, int height);
-    GLenum mFormat;
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLenum mInternalFormat;
     D3DFORMAT mD3DFormat;
     GLsizei mSamples;
-    const unsigned int mSerial;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
 
-    static unsigned int mCurrentSerial;
+    static unsigned int issueSerial();
 
-    int mWidth;
-    int mHeight;
+    const unsigned int mSerial;
+
+    static unsigned int mCurrentSerial;
 };
 
 // Renderbuffer implements the GL renderbuffer object.
-// It's only a wrapper for a RenderbufferStorage, but the internal object
+// It's only a proxy for a RenderbufferStorage instance; the internal object
 // can change whenever glRenderbufferStorage is called.
 class Renderbuffer : public RefCountObject
 {
@@ -83,10 +89,18 @@
     IDirect3DSurface9 *getRenderTarget();
     IDirect3DSurface9 *getDepthStencil();
 
-    int getWidth() const;
-    int getHeight() const;
-    GLenum getFormat() const;
+    GLsizei getWidth() const;
+    GLsizei getHeight() const;
+    GLenum getInternalFormat() const;
     D3DFORMAT getD3DFormat() const;
+    GLuint getRedSize() const;
+    GLuint getGreenSize() const;
+    GLuint getBlueSize() const;
+    GLuint getAlphaSize() const;
+    GLuint getDepthSize() const;
+    GLuint getStencilSize() const;
+    GLsizei getSamples() const;
+
     unsigned int getSerial() const;
 
     void setStorage(RenderbufferStorage *newStorage);
@@ -102,42 +116,43 @@
 {
   public:
     explicit Colorbuffer(IDirect3DSurface9 *renderTarget);
-    explicit Colorbuffer(const Texture* texture);
-    Colorbuffer(int width, int height, GLenum format, GLsizei samples);
+    Colorbuffer(Texture *texture, GLenum target);
+    Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples);
 
-    ~Colorbuffer();
+    virtual ~Colorbuffer();
 
-    bool isColorbuffer() const;
+    virtual bool isColorbuffer() const;
 
-    GLuint getRedSize() const;
-    GLuint getGreenSize() const;
-    GLuint getBlueSize() const;
-    GLuint getAlphaSize() const;
+    virtual IDirect3DSurface9 *getRenderTarget();
 
-    IDirect3DSurface9 *getRenderTarget();
+    virtual GLsizei getWidth() const;
+    virtual GLsizei getHeight() const;
+    virtual GLenum getInternalFormat() const;
 
-  protected:
-    IDirect3DSurface9 *mRenderTarget;
+    virtual D3DFORMAT getD3DFormat() const;
+
+    bool isFloatingPoint() const;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
+
+    IDirect3DSurface9 *mRenderTarget;
+    Texture *mTexture;
+    GLenum mTarget;
 };
 
 class DepthStencilbuffer : public RenderbufferStorage
 {
   public:
     explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil);
-    DepthStencilbuffer(int width, int height, GLsizei samples);
+    DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
 
     ~DepthStencilbuffer();
 
     virtual bool isDepthbuffer() const;
     virtual bool isStencilbuffer() const;
 
-    GLuint getDepthSize() const;
-    GLuint getStencilSize() const;
-
-    IDirect3DSurface9 *getDepthStencil();
+    virtual IDirect3DSurface9 *getDepthStencil();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
@@ -148,12 +163,12 @@
 {
   public:
     explicit Depthbuffer(IDirect3DSurface9 *depthStencil);
-    Depthbuffer(int width, int height, GLsizei samples);
+    Depthbuffer(GLsizei width, GLsizei height, GLsizei samples);
 
-    ~Depthbuffer();
+    virtual ~Depthbuffer();
 
-    bool isDepthbuffer() const;
-    bool isStencilbuffer() const;
+    virtual bool isDepthbuffer() const;
+    virtual bool isStencilbuffer() const;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
@@ -163,12 +178,12 @@
 {
   public:
     explicit Stencilbuffer(IDirect3DSurface9 *depthStencil);
-    Stencilbuffer(int width, int height, GLsizei samples);
+    Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
 
-    ~Stencilbuffer();
+    virtual ~Stencilbuffer();
 
-    bool isDepthbuffer() const;
-    bool isStencilbuffer() const;
+    virtual bool isDepthbuffer() const;
+    virtual bool isStencilbuffer() const;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 7a6ae8a..a0f446e 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -1,2509 +1,2464 @@
-//

-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-//

-

-// Texture.cpp: Implements the gl::Texture class and its derived classes

-// Texture2D and TextureCubeMap. Implements GL texture objects and related

-// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.

-

-#include "libGLESv2/Texture.h"

-

-#include <d3dx9tex.h>

-

-#include <algorithm>

-

-#include "common/debug.h"

-

-#include "libGLESv2/main.h"

-#include "libGLESv2/mathutil.h"

-#include "libGLESv2/utilities.h"

-#include "libGLESv2/Blit.h"

-#include "libGLESv2/Framebuffer.h"

-

-namespace gl

-{

-

-Texture::Image::Image()

-  : width(0), height(0), dirty(false), surface(NULL), format(GL_NONE)

-{

-}

-

-Texture::Image::~Image()

-{

-  if (surface) surface->Release();

-}

-

-Texture::Texture(GLuint id) : RefCountObject(id)

-{

-    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;

-    mMagFilter = GL_LINEAR;

-    mWrapS = GL_REPEAT;

-    mWrapT = GL_REPEAT;

-

-    mWidth = 0;

-    mHeight = 0;

-

-    mDirtyMetaData = true;

-    mDirty = true;

-    mIsRenderable = false;

-    mType = GL_UNSIGNED_BYTE;

-    mBaseTexture = NULL;

-}

-

-Texture::~Texture()

-{

-}

-

-Blit *Texture::getBlitter()

-{

-    Context *context = getContext();

-    return context->getBlitter();

-}

-

-// 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;

-                mDirty = 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;

-                mDirty = 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;

-                mDirty = 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;

-                mDirty = 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;

-}

-

-GLuint Texture::getWidth() const

-{

-    return mWidth;

-}

-

-GLuint Texture::getHeight() const

-{

-    return mHeight;

-}

-

-bool Texture::isFloatingPoint() const

-{

-    return (mType == GL_FLOAT || mType == GL_HALF_FLOAT_OES);

-}

-

-bool Texture::isRenderableFormat() const

-{

-    D3DFORMAT format = getD3DFormat();

-    

-    switch(format)

-    {

-      case D3DFMT_L8:

-      case D3DFMT_A8L8:

-      case D3DFMT_DXT1:

-        return false;

-      case D3DFMT_A8R8G8B8:

-      case D3DFMT_X8R8G8B8:

-      case D3DFMT_A16B16G16R16F:

-      case D3DFMT_A32B32G32R32F:

-        return true;

-      default:

-        UNREACHABLE();

-    }

-

-    return false;

-}

-

-// Selects an internal Direct3D 9 format for storing an Image

-D3DFORMAT Texture::selectFormat(GLenum format, GLenum type)

-{

-    if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||

-        format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)

-    {

-        return D3DFMT_DXT1;

-    }

-    else if (type == GL_FLOAT)

-    {

-        return D3DFMT_A32B32G32R32F;

-    }

-    else if (type == GL_HALF_FLOAT_OES)

-    {

-        return D3DFMT_A16B16G16R16F;

-    }

-    else if (type == GL_UNSIGNED_BYTE)

-    {

-        if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures())

-        {

-            return D3DFMT_L8;

-        }

-        else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())

-        {

-            return D3DFMT_A8L8;

-        }

-        else if (format == GL_RGB)

-        {

-            return D3DFMT_X8R8G8B8;

-        }

-

-        return D3DFMT_A8R8G8B8;

-    }

-

-    return D3DFMT_A8R8G8B8;

-}

-

-// 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

-{

-    GLsizei inputPitch = -ComputePitch(width, format, type, unpackAlignment);

-    input = ((char*)input) - inputPitch * (height - 1);

-

-    switch (type)

-    {

-      case GL_UNSIGNED_BYTE:

-        switch (format)

-        {

-          case GL_ALPHA:

-            loadAlphaImageData(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);

-            break;

-          case GL_LUMINANCE_ALPHA:

-            loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_A8L8);

-            break;

-          case GL_RGB:

-            loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          case GL_RGBA:

-            loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          case GL_BGRA_EXT:

-            loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          default: UNREACHABLE();

-        }

-        break;

-      case GL_UNSIGNED_SHORT_5_6_5:

-        switch (format)

-        {

-          case GL_RGB:

-            loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          default: UNREACHABLE();

-        }

-        break;

-      case GL_UNSIGNED_SHORT_4_4_4_4:

-        switch (format)

-        {

-          case GL_RGBA:

-            loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          default: UNREACHABLE();

-        }

-        break;

-      case GL_UNSIGNED_SHORT_5_5_5_1:

-        switch (format)

-        {

-          case GL_RGBA:

-            loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          default: UNREACHABLE();

-        }

-        break;

-      case GL_FLOAT:

-        switch (format)

-        {

-          // 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);

-            break;

-          case GL_LUMINANCE:

-            loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          case GL_LUMINANCE_ALPHA:

-            loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          case GL_RGB:

-            loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          case GL_RGBA:

-            loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          default: UNREACHABLE();

-        }

-        break;

-      case GL_HALF_FLOAT_OES:

-        switch (format)

-        {

-          // 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);

-            break;

-          case GL_LUMINANCE:

-            loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          case GL_LUMINANCE_ALPHA:

-            loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          case GL_RGB:

-            loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);

-            break;

-          case GL_RGBA:

-            loadRGBAHalfFloatImageData(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

-{

-    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;

-        for (int x = 0; x < width; 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

-{

-    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);

-        for (int x = 0; x < width; x++)

-        {

-            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

-{

-    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);

-        for (int x = 0; x < width; x++)

-        {

-            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

-{

-    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;

-        dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;

-

-        if (!native)   // BGRA8 destination format

-        {

-            for (int x = 0; x < width; x++)

-            {

-                dest[4 * x + 0] = source[x];

-                dest[4 * x + 1] = source[x];

-                dest[4 * x + 2] = source[x];

-                dest[4 * x + 3] = 0xFF;

-            }

-        }

-        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

-{

-    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);

-        for (int x = 0; x < width; x++)

-        {

-            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

-{

-    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);

-        for (int x = 0; x < width; x++)

-        {

-            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

-{

-    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;

-        dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;

-        

-        if (!native)   // BGRA8 destination format

-        {

-            for (int x = 0; x < width; x++)

-            {

-                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];

-            }

-        }

-        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

-{

-    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);

-        for (int x = 0; x < width; x++)

-        {

-            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

-{

-    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);

-        for (int x = 0; x < width; x++)

-        {

-            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

-{

-    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;

-        for (int x = 0; x < width; x++)

-        {

-            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

-{

-    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;

-        for (int x = 0; x < width; x++)

-        {

-            unsigned short rgba = source[x];

-            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

-{

-    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);

-        for (int x = 0; x < width; x++)

-        {

-            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

-{

-    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);

-        for (int x = 0; x < width; x++)

-        {

-            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::loadRGBAUByteImageData(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;

-        for (int x = 0; x < width; x++)

-        {

-            dest[4 * x + 0] = source[x * 4 + 2];

-            dest[4 * x + 1] = source[x * 4 + 1];

-            dest[4 * x + 2] = source[x * 4 + 0];

-            dest[4 * x + 3] = source[x * 4 + 3];

-        }

-    }

-}

-

-void Texture::loadRGBA4444ImageData(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;

-        for (int x = 0; x < width; x++)

-        {

-            unsigned short rgba = source[x];

-            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

-{

-    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;

-        for (int x = 0; x < width; x++)

-        {

-            unsigned short rgba = source[x];

-            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

-{

-    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

-{

-    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

-{

-    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

-{

-    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);

-    unsigned int *dest = reinterpret_cast<unsigned int*>(output);

-

-    switch (height)

-    {

-        case 1:

-            // Round width up in case it is 1.

-            for (int x = 0; x < (width + 1) / 2; x += 2)

-            {

-                // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.

-                dest[x] = source[x];

-

-                // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors, the last 3 rows being unused. No flipping should occur.

-                dest[x + 1] = source[x + 1];

-            }

-            break;

-        case 2:

-            // Round width up in case it is 1.

-            for (int x = 0; x < (width + 1) / 2; x += 2)

-            {

-                // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.

-                dest[x] = source[x];

-

-                // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors, the last 2 rows being unused. Only the top 2 rows should be flipped.

-                dest[x + 1] = ((source[x + 1] << 8) & 0x0000FF00) |

-                              ((source[x + 1] >> 8) & 0x000000FF);       

-            }

-            break;

-        default:

-            ASSERT(height % 4 == 0);

-            for (int y = 0; y < height / 4; ++y)

-            {

-                const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);

-                unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);

-

-                // Round width up in case it is 1.

-                for (int x = 0; x < (width + 1) / 2; x += 2)

-                {

-                    // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.

-                    dest[x] = source[x];

-

-                    // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.

-                    dest[x + 1] = (source[x + 1] >> 24) | 

-                                  ((source[x + 1] << 8) & 0x00FF0000) |

-                                  ((source[x + 1] >> 8) & 0x0000FF00) |

-                                  (source[x + 1] << 24);                    

-                }

-            }

-            break;

-    }

-}

-

-void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img)

-{

-    IDirect3DTexture9 *newTexture = NULL;

-    IDirect3DSurface9 *newSurface = NULL;

-

-    if (width != 0 && height != 0)

-    {

-        int levelToFetch = 0;

-        GLsizei requestWidth = width;

-        GLsizei requestHeight = height;

-        if (IsCompressed(format) && (width % 4 != 0 || 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, selectFormat(format, type),

-                                                    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 (img->surface) img->surface->Release();

-    img->surface = newSurface;

-

-    img->width = width;

-    img->height = height;

-    img->format = format;

-}

-

-void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)

-{

-    createSurface(width, height, format, type, img);

-

-    if (pixels != NULL && img->surface != NULL)

-    {

-        D3DSURFACE_DESC description;

-        img->surface->GetDesc(&description);

-

-        D3DLOCKED_RECT locked;

-        HRESULT result = img->surface->LockRect(&locked, NULL, 0);

-

-        ASSERT(SUCCEEDED(result));

-

-        if (SUCCEEDED(result))

-        {

-            loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);

-            img->surface->UnlockRect();

-        }

-

-        img->dirty = true;

-    }

-

-    mDirtyMetaData = true;

-}

-

-void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)

-{

-    createSurface(width, height, format, GL_UNSIGNED_BYTE, img);

-

-    if (pixels != NULL && img->surface != NULL)

-    {

-        D3DLOCKED_RECT locked;

-        HRESULT result = img->surface->LockRect(&locked, NULL, 0);

-

-        ASSERT(SUCCEEDED(result));

-

-        if (SUCCEEDED(result))

-        {

-            int inputPitch = ComputeCompressedPitch(width, format);

-            int inputSize = ComputeCompressedSize(width, height, format);

-            loadCompressedImageData(0, 0, width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);

-            img->surface->UnlockRect();

-        }

-

-        img->dirty = true;

-    }

-

-    mDirtyMetaData = true;

-}

-

-bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)

-{

-    if (width + xoffset > img->width || height + yoffset > img->height)

-    {

-        error(GL_INVALID_VALUE);

-        return false;

-    }

-

-    if (!img->surface)

-    {

-        createSurface(img->width, img->height, format, type, img);

-    }

-

-    if (pixels != NULL && img->surface != NULL)

-    {

-        D3DSURFACE_DESC description;

-        img->surface->GetDesc(&description);

-

-        D3DLOCKED_RECT locked;

-        HRESULT result = img->surface->LockRect(&locked, NULL, 0);

-

-        ASSERT(SUCCEEDED(result));

-

-        if (SUCCEEDED(result))

-        {

-            loadImageData(xoffset, transformPixelYOffset(yoffset, height, img->height), width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);

-            img->surface->UnlockRect();

-        }

-

-        img->dirty = true;

-    }

-

-    return true;

-}

-

-bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)

-{

-    if (width + xoffset > img->width || height + yoffset > img->height)

-    {

-        error(GL_INVALID_VALUE);

-        return false;

-    }

-

-    if (format != getFormat())

-    {

-        error(GL_INVALID_OPERATION);

-        return false;

-    }

-

-    if (!img->surface)

-    {

-        createSurface(img->width, img->height, format, GL_UNSIGNED_BYTE, img);

-    }

-

-    if (pixels != NULL && img->surface != NULL)

-    {

-        RECT updateRegion;

-        updateRegion.left = xoffset;

-        updateRegion.right = xoffset + width;

-        updateRegion.bottom = yoffset + height;

-        updateRegion.top = yoffset;

-

-        D3DLOCKED_RECT locked;

-        HRESULT result = img->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, img->height), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);

-            img->surface->UnlockRect();

-        }

-

-        img->dirty = true;

-    }

-

-    return true;

-}

-

-// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats

-void Texture::copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)

-{

-    IDirect3DDevice9 *device = getDevice();

-    IDirect3DSurface9 *surface = NULL;

-    D3DSURFACE_DESC description;

-    renderTarget->GetDesc(&description);

-    

-    HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);

-

-    if (!SUCCEEDED(result))

-    {

-        ERR("Could not create matching destination surface.");

-        return error(GL_OUT_OF_MEMORY);

-    }

-

-    result = device->GetRenderTargetData(renderTarget, surface);

-

-    if (!SUCCEEDED(result))

-    {

-        ERR("GetRenderTargetData unexpectedly failed.");

-        surface->Release();

-        return error(GL_OUT_OF_MEMORY);

-    }

-

-    D3DLOCKED_RECT sourceLock = {0};

-    RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);

-    result = surface->LockRect(&sourceLock, &sourceRect, 0);

-

-    if (FAILED(result))

-    {

-        ERR("Failed to lock the source surface (rectangle might be invalid).");

-        surface->UnlockRect();

-        surface->Release();

-        return error(GL_OUT_OF_MEMORY);

-    }

-

-    if (!image->surface)

-    {

-        createSurface(width, height, internalFormat, mType, image);

-    }

-

-    if (image->surface == NULL)

-    {

-        ERR("Failed to create an image surface.");

-        surface->UnlockRect();

-        surface->Release();

-        return error(GL_OUT_OF_MEMORY); 

-    }

-

-    D3DLOCKED_RECT destLock = {0};

-    int destYOffset = transformPixelYOffset(yoffset, height, image->height);

-    RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};

-    result = image->surface->LockRect(&destLock, &destRect, 0);

-    

-    if (FAILED(result))

-    {

-        ERR("Failed to lock the destination surface (rectangle might be invalid).");

-        surface->UnlockRect();

-        surface->Release();

-        return error(GL_OUT_OF_MEMORY);

-    }

-

-    if (destLock.pBits && sourceLock.pBits)

-    {

-        unsigned char *source = (unsigned char*)sourceLock.pBits;

-        unsigned char *dest = (unsigned char*)destLock.pBits;

-

-        switch (description.Format)

-        {

-          case D3DFMT_X8R8G8B8:

-          case D3DFMT_A8R8G8B8:

-            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];

-                    }

-

-                    source += sourceLock.Pitch;

-                    dest += destLock.Pitch;

-                }

-                break;

-              case D3DFMT_A8L8:

-                for(int y = 0; y < height; y++)

-                {

-                    for(int x = 0; x < width; x++)

-                    {

-                        dest[x * 2 + 0] = source[x * 4 + 2];

-                        dest[x * 2 + 1] = source[x * 4 + 3];

-                    }

-

-                    source += sourceLock.Pitch;

-                    dest += destLock.Pitch;

-                }

-                break;

-              default:

-                UNREACHABLE();

-            }

-            break;

-          case D3DFMT_R5G6B5:

-            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);

-                    }

-

-                    source += sourceLock.Pitch;

-                    dest += destLock.Pitch;

-                }

-                break;

-              default:

-                UNREACHABLE();

-            }

-            break;

-          case D3DFMT_A1R5G5B5:

-            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);

-                    }

-

-                    source += sourceLock.Pitch;

-                    dest += destLock.Pitch;

-                }

-                break;

-              case D3DFMT_A8L8:

-                for(int y = 0; y < height; y++)

-                {

-                    for(int x = 0; x < width; x++)

-                    {

-                        unsigned char red = source[x * 2 + 1] & 0x7C;

-                        dest[x * 2 + 0] = (red << 1) | (red >> 4);

-                        dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;

-                    }

-

-                    source += sourceLock.Pitch;

-                    dest += destLock.Pitch;

-                }

-                break;

-              default:

-                UNREACHABLE();

-            }

-            break;

-          default:

-            UNREACHABLE();

-        }

-

-        image->dirty = true;

-        mDirtyMetaData = true;    

-    }

-

-    image->surface->UnlockRect();

-    surface->UnlockRect();

-    surface->Release();

-}

-

-D3DFORMAT Texture::getD3DFormat() const

-{

-    return selectFormat(getFormat(), mType);

-}

-

-IDirect3DBaseTexture9 *Texture::getTexture()

-{

-    if (!isComplete())

-    {

-        return NULL;

-    }

-

-    if (mDirtyMetaData)

-    {

-        mBaseTexture = createTexture();

-        mIsRenderable = false;

-    }

-

-    if (mDirtyMetaData || dirtyImageData())

-    {

-        updateTexture();

-    }

-

-    mDirtyMetaData = false;

-    ASSERT(!dirtyImageData());

-

-    return mBaseTexture;

-}

-

-bool Texture::isDirty() const

-{

-    return (mDirty || mDirtyMetaData || dirtyImageData());

-}

-

-// Returns the top-level texture surface as a render target

-void Texture::needRenderTarget()

-{

-    if (!mIsRenderable)

-    {

-        mBaseTexture = convertToRenderTarget();

-        mIsRenderable = true;

-    }

-

-    if (dirtyImageData())

-    {

-        updateTexture();

-    }

-

-    mDirtyMetaData = false;

-}

-

-void Texture::dropTexture()

-{

-    if (mBaseTexture)

-    {

-        mBaseTexture = NULL;

-    }

-

-    mIsRenderable = false;

-}

-

-void Texture::pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable)

-{

-    mBaseTexture = newTexture;

-    mDirtyMetaData = false;

-    mIsRenderable = renderable;

-    mDirty = true;

-}

-

-

-GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const

-{

-    if (isPow2(width) && isPow2(height))

-    {

-        return maxlevel;

-    }

-    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

-{

-    return creationLevels(size, size, maxlevel);

-}

-

-int Texture::levelCount() const

-{

-    return mBaseTexture ? mBaseTexture->GetLevelCount() : 0;

-}

-

-bool Texture::isRenderable() const

-{

-    return mIsRenderable;

-}

-

-Texture2D::Texture2D(GLuint id) : Texture(id)

-{

-    mTexture = NULL;

-}

-

-Texture2D::~Texture2D()

-{

-    mColorbufferProxy.set(NULL);

-

-    if (mTexture)

-    {

-        mTexture->Release();

-        mTexture = NULL;

-    }

-}

-

-GLenum Texture2D::getTarget() const

-{

-    return GL_TEXTURE_2D;

-}

-

-GLenum Texture2D::getFormat() const

-{

-    return mImageArray[0].format;

-}

-

-// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture

-// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels.

-// Call this when a particular level of the texture must be defined with a specific format, width and height.

-//

-// Returns true if the existing texture was unsuitable and had to be destroyed. If so, it will also set

-// a new height and width for the texture by working backwards from the given width and height.

-bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type)

-{

-    bool widthOkay = (mWidth >> level == width);

-    bool heightOkay = (mHeight >> level == height);

-

-    bool sizeOkay = ((widthOkay && heightOkay)

-                     || (widthOkay && mHeight >> level == 0 && height == 1)

-                     || (heightOkay && mWidth >> level == 0 && width == 1));

-

-    bool typeOkay = (type == mType);

-

-    bool textureOkay = (sizeOkay && typeOkay && internalFormat == mImageArray[0].format);

-

-    if (!textureOkay)

-    {

-        TRACE("Redefining 2D texture (%d, 0x%04X, %d, %d => 0x%04X, %d, %d).", level,

-              mImageArray[0].format, mWidth, mHeight,

-              internalFormat, width, height);

-

-        // Purge all the levels and the texture.

-

-        for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)

-        {

-            if (mImageArray[i].surface != NULL)

-            {

-                mImageArray[i].dirty = false;

-

-                mImageArray[i].surface->Release();

-                mImageArray[i].surface = NULL;

-            }

-        }

-

-        if (mTexture != NULL)

-        {

-            mTexture->Release();

-            mTexture = NULL;

-            dropTexture();

-        }

-

-        mWidth = width << level;

-        mHeight = height << level;

-        mImageArray[0].format = internalFormat;

-        mType = type;

-    }

-

-    return !textureOkay;

-}

-

-void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

-{

-    redefineTexture(level, internalFormat, width, height, type);

-

-    Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]);

-}

-

-void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)

-{

-    redefineTexture(level, internalFormat, width, height, GL_UNSIGNED_BYTE);

-

-    Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);

-}

-

-void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)

-{

-    ASSERT(mImageArray[level].surface != NULL);

-

-    if (level < levelCount())

-    {

-        IDirect3DSurface9 *destLevel = NULL;

-        HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);

-

-        ASSERT(SUCCEEDED(result));

-

-        if (SUCCEEDED(result))

-        {

-            Image *img = &mImageArray[level];

-

-            RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, img->height);;

-

-            POINT destPoint;

-            destPoint.x = sourceRect.left;

-            destPoint.y = sourceRect.top;

-

-            result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);

-            ASSERT(SUCCEEDED(result));

-

-            destLevel->Release();

-

-            img->dirty = false;

-        }

-    }

-}

-

-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]))

-    {

-        commitRect(level, xoffset, yoffset, width, height);

-    }

-}

-

-void Texture2D::subImageCompressed(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[level]))

-    {

-        commitRect(level, xoffset, yoffset, width, height);

-    }

-}

-

-void Texture2D::copyImage(GLint level, GLenum internalFormat, 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);

-    }

-

-    bool redefined = redefineTexture(level, internalFormat, width, height, mType);

-   

-    if (!isRenderableFormat())

-    {

-        copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget);

-    }

-    else

-    {

-        if (redefined)

-        {

-            convertToRenderTarget();

-            pushTexture(mTexture, true);

-        }

-        else

-        {

-            needRenderTarget();

-        }

-

-        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());

-            

-            IDirect3DSurface9 *dest;

-            HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);

-

-            getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);

-            dest->Release();

-        }

-    }

-

-    mImageArray[level].width = width;

-    mImageArray[level].height = height;

-    mImageArray[level].format = internalFormat;

-}

-

-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)

-    {

-        return error(GL_INVALID_VALUE);

-    }

-

-    IDirect3DSurface9 *renderTarget = source->getRenderTarget();

-

-    if (!renderTarget)

-    {

-        ERR("Failed to retrieve the render target.");

-        return error(GL_OUT_OF_MEMORY);

-    }

-

-    bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType);

-   

-    if (!isRenderableFormat())

-    {

-        copyNonRenderable(&mImageArray[level], getFormat(), xoffset, yoffset, x, y, width, height, renderTarget);

-    }

-    else

-    {

-        if (redefined)

-        {

-            convertToRenderTarget();

-            pushTexture(mTexture, true);

-        }

-        else

-        {

-            needRenderTarget();

-        }

-

-        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()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, destYOffset, dest);

-            dest->Release();

-        }

-    }

-}

-

-// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.

-bool Texture2D::isComplete() const

-{

-    GLsizei width = mImageArray[0].width;

-    GLsizei height = mImageArray[0].height;

-

-    if (width <= 0 || height <= 0)

-    {

-        return false;

-    }

-

-    bool mipmapping = false;

-

-    switch (mMinFilter)

-    {

-      case GL_NEAREST:

-      case GL_LINEAR:

-        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();

-    }

-

-    if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||

-        (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))

-    {

-        if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))

-        {

-            return false;

-        }

-    }

-

-

-    if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width))

-        || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))

-    {

-        return false;

-    }

-

-    if (mipmapping)

-    {

-        if (!isPow2(width) || !isPow2(height))

-        {

-            return false;

-        }

-

-        int q = log2(std::max(width, height));

-

-        for (int level = 1; level <= q; level++)

-        {

-            if (mImageArray[level].format != mImageArray[0].format)

-            {

-                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 true;

-}

-

-bool Texture2D::isCompressed() const

-{

-    return IsCompressed(getFormat());

-}

-

-// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one

-IDirect3DBaseTexture9 *Texture2D::createTexture()

-{

-    IDirect3DTexture9 *texture;

-

-    IDirect3DDevice9 *device = getDevice();

-    D3DFORMAT format = selectFormat(mImageArray[0].format, mType);

-

-    HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);

-

-    if (FAILED(result))

-    {

-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

-        return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);

-    }

-

-    if (mTexture) mTexture->Release();

-    mTexture = texture;

-    return texture;

-}

-

-void Texture2D::updateTexture()

-{

-    IDirect3DDevice9 *device = getDevice();

-

-    int levels = levelCount();

-

-    for (int level = 0; level < levels; level++)

-    {

-        if (mImageArray[level].dirty)

-        {

-            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;

-            }

-        }

-    }

-}

-

-IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()

-{

-    IDirect3DTexture9 *texture = NULL;

-

-    if (mWidth != 0 && mHeight != 0)

-    {

-        egl::Display *display = getDisplay();

-        IDirect3DDevice9 *device = getDevice();

-        D3DFORMAT format = selectFormat(mImageArray[0].format, mType);

-

-        HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);

-

-        if (FAILED(result))

-        {

-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

-            return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);

-        }

-

-        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, (IDirect3DBaseTexture9*)NULL);

-                }

-

-                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, (IDirect3DBaseTexture9*)NULL);

-                }

-

-                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, (IDirect3DBaseTexture9*)NULL);

-                }

-

-                source->Release();

-                dest->Release();

-            }

-        }

-    }

-

-    if (mTexture != NULL)

-    {

-        mTexture->Release();

-    }

-

-    mTexture = texture;

-    return mTexture;

-}

-

-bool Texture2D::dirtyImageData() const

-{

-    int q = log2(std::max(mWidth, mHeight));

-

-    for (int i = 0; i <= q; i++)

-    {

-        if (mImageArray[i].dirty) return true;

-    }

-

-    return false;

-}

-

-void Texture2D::generateMipmaps()

-{

-    if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))

-    {

-        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(mWidth, mHeight));

-    for (unsigned int i = 1; i <= q; i++)

-    {

-        if (mImageArray[i].surface != NULL)

-        {

-            mImageArray[i].surface->Release();

-            mImageArray[i].surface = NULL;

-        }

-

-        mImageArray[i].dirty = false;

-

-        mImageArray[i].format = mImageArray[0].format;

-        mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);

-        mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);

-    }

-

-    if (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);

-

-            if (upper != NULL && lower != NULL)

-            {

-                getBlitter()->boxFilter(upper, lower);

-            }

-

-            if (upper != NULL) upper->Release();

-            if (lower != NULL) lower->Release();

-        }

-    }

-    else

-    {

-        for (unsigned int i = 1; i <= q; i++)

-        {

-            createSurface(mImageArray[i].width, mImageArray[i].height, mImageArray[i].format, mType, &mImageArray[i]);

-            if (mImageArray[i].surface == 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)))

-            {

-                ERR(" failed to load filter %d to %d.", i - 1, i);

-            }

-

-            mImageArray[i].dirty = true;

-        }

-

-        mDirtyMetaData = true;

-    }

-}

-

-Renderbuffer *Texture2D::getColorbuffer(GLenum target)

-{

-    if (target != GL_TEXTURE_2D)

-    {

-        return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);

-    }

-

-    if (mColorbufferProxy.get() == NULL)

-    {

-        mColorbufferProxy.set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));

-    }

-

-    return mColorbufferProxy.get();

-}

-

-IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)

-{

-    ASSERT(target == GL_TEXTURE_2D);

-

-    needRenderTarget();

-

-    if (mTexture == NULL)

-    {

-        return NULL;

-    }

-    

-    IDirect3DSurface9 *renderTarget = NULL;

-    mTexture->GetSurfaceLevel(0, &renderTarget);

-

-    return renderTarget;

-}

-

-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;

-    }

-}

-

-GLenum TextureCubeMap::getTarget() const

-{

-    return GL_TEXTURE_CUBE_MAP;

-}

-

-GLenum TextureCubeMap::getFormat() const

-{

-    return mImageArray[0][0].format;

-}

-

-void TextureCubeMap::setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

-{

-    setImage(0, level, internalFormat, width, height, format, type, unpackAlignment, pixels);

-}

-

-void TextureCubeMap::setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

-{

-    setImage(1, level, internalFormat, width, height, format, type, unpackAlignment, pixels);

-}

-

-void TextureCubeMap::setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

-{

-    setImage(2, level, internalFormat, width, height, format, type, unpackAlignment, pixels);

-}

-

-void TextureCubeMap::setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

-{

-    setImage(3, level, internalFormat, width, height, format, type, unpackAlignment, pixels);

-}

-

-void TextureCubeMap::setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

-{

-    setImage(4, level, internalFormat, width, height, format, type, unpackAlignment, pixels);

-}

-

-void TextureCubeMap::setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

-{

-    setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);

-}

-

-void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)

-{

-    redefineTexture(level, internalFormat, width);

-

-    Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);

-}

-

-void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)

-{

-    int face = faceIndex(faceTarget);

-    ASSERT(mImageArray[face][level].surface != NULL);

-

-    if (level < levelCount())

-    {

-        IDirect3DSurface9 *destLevel = getCubeMapSurface(faceTarget, level);

-        ASSERT(destLevel != NULL);

-

-        if (destLevel != NULL)

-        {

-            Image *img = &mImageArray[face][level];

-

-            RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, img->height);;

-

-            POINT destPoint;

-            destPoint.x = sourceRect.left;

-            destPoint.y = sourceRect.top;

-

-            HRESULT result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);

-            ASSERT(SUCCEEDED(result));

-

-            destLevel->Release();

-

-            img->dirty = false;

-        }

-    }

-}

-

-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);

-    }

-}

-

-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);

-    }

-}

-

-// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.

-bool TextureCubeMap::isComplete() const

-{

-    int size = mImageArray[0][0].width;

-

-    if (size <= 0)

-    {

-        return false;

-    }

-

-    bool mipmapping;

-

-    switch (mMinFilter)

-    {

-      case GL_NEAREST:

-      case GL_LINEAR:

-        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();

-    }

-

-    for (int face = 0; face < 6; face++)

-    {

-        if (mImageArray[face][0].width != size || mImageArray[face][0].height != size)

-        {

-            return false;

-        }

-    }

-

-    if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||

-        (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))

-    {

-        if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))

-        {

-            return false;

-        }

-    }

-

-    if (mipmapping)

-    {

-        if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE))

-        {

-            return false;

-        }

-

-        int q = log2(size);

-

-        for (int face = 0; face < 6; face++)

-        {

-            for (int level = 1; level <= q; level++)

-            {

-                if (mImageArray[face][level].format != mImageArray[0][0].format)

-                {

-                    return false;

-                }

-

-                if (mImageArray[face][level].width != std::max(1, size >> level))

-                {

-                    return false;

-                }

-

-                ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);

-            }

-        }

-    }

-

-    return true;

-}

-

-bool TextureCubeMap::isCompressed() const

-{

-    return IsCompressed(getFormat());

-}

-

-// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one

-IDirect3DBaseTexture9 *TextureCubeMap::createTexture()

-{

-    IDirect3DDevice9 *device = getDevice();

-    D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);

-

-    IDirect3DCubeTexture9 *texture;

-

-    HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);

-

-    if (FAILED(result))

-    {

-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

-        return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);

-    }

-

-    if (mTexture) mTexture->Release();

-

-    mTexture = texture;

-    return mTexture;

-}

-

-void TextureCubeMap::updateTexture()

-{

-    IDirect3DDevice9 *device = getDevice();

-

-    for (int face = 0; face < 6; face++)

-    {

-        int levels = levelCount();

-        for (int level = 0; level < levels; level++)

-        {

-            Image *img = &mImageArray[face][level];

-

-            if (img->dirty)

-            {

-                IDirect3DSurface9 *levelSurface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);

-                ASSERT(levelSurface != NULL);

-

-                if (levelSurface != NULL)

-                {

-                    HRESULT result = device->UpdateSurface(img->surface, NULL, levelSurface, NULL);

-                    ASSERT(SUCCEEDED(result));

-

-                    levelSurface->Release();

-

-                    img->dirty = false;

-                }

-            }

-        }

-    }

-}

-

-IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()

-{

-    IDirect3DCubeTexture9 *texture = NULL;

-

-    if (mWidth != 0)

-    {

-        egl::Display *display = getDisplay();

-        IDirect3DDevice9 *device = getDevice();

-        D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);

-

-        HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);

-

-        if (FAILED(result))

-        {

-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

-            return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);

-        }

-

-        if (mTexture != NULL)

-        {

-            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, (IDirect3DBaseTexture9*)NULL);

-                    }

-

-                    IDirect3DSurface9 *dest;

-                    result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);

-

-                    if (FAILED(result))

-                    {

-                        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

-

-                        texture->Release();

-                        source->Release();

-

-                        return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);

-                    }

-

-                    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, (IDirect3DBaseTexture9*)NULL);

-                    }

-                }

-            }

-        }

-    }

-

-    if (mTexture != NULL)

-    {

-        mTexture->Release();

-    }

-

-    mTexture = texture;

-    return mTexture;

-}

-

-void TextureCubeMap::setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

-{

-    redefineTexture(level, internalFormat, width);

-

-    Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[face][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;

-}

-

-bool TextureCubeMap::dirtyImageData() const

-{

-    int q = log2(mWidth);

-

-    for (int f = 0; f < 6; f++)

-    {

-        for (int i = 0; i <= q; i++)

-        {

-            if (mImageArray[f][i].dirty) return true;

-        }

-    }

-

-    return false;

-}

-

-// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture

-// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels & faces.

-// Call this when a particular level of the texture must be defined with a specific format, width and height.

-//

-// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set

-// a new size for the texture by working backwards from the given size.

-bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei width)

-{

-    // Are these settings compatible with level 0?

-    bool sizeOkay = (mImageArray[0][0].width >> level == width);

-

-    bool textureOkay = (sizeOkay && internalFormat == mImageArray[0][0].format);

-

-    if (!textureOkay)

-    {

-        TRACE("Redefining cube texture (%d, 0x%04X, %d => 0x%04X, %d).", level,

-              mImageArray[0][0].format, mImageArray[0][0].width,

-              internalFormat, width);

-

-        // Purge all the levels and the texture.

-        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].dirty = false;

-

-                    mImageArray[f][i].surface->Release();

-                    mImageArray[f][i].surface = NULL;

-                }

-            }

-        }

-

-        if (mTexture != NULL)

-        {

-            mTexture->Release();

-            mTexture = NULL;

-            dropTexture();

-        }

-

-        mWidth = width << level;

-        mImageArray[0][0].width = width << level;

-        mHeight = width << level;

-        mImageArray[0][0].height = width << level;

-

-        mImageArray[0][0].format = internalFormat;

-    }

-

-    return !textureOkay;

-}

-

-void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat, 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);

-    bool redefined = redefineTexture(level, internalFormat, width);

-

-    if (!isRenderableFormat())

-    {

-        copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget);

-    }

-    else

-    {

-        if (redefined)

-        {

-            convertToRenderTarget();

-            pushTexture(mTexture, true);

-        }

-        else

-        {

-            needRenderTarget();

-        }

-

-        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());

-

-            IDirect3DSurface9 *dest = getCubeMapSurface(target, level);

-

-            getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);

-            dest->Release();

-        }

-    }

-

-    mImageArray[faceindex][level].width = width;

-    mImageArray[faceindex][level].height = height;

-    mImageArray[faceindex][level].format = internalFormat;

-}

-

-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;

-}

-

-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;

-

-    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);

-    bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width);

-   

-    if (!isRenderableFormat())

-    {

-        copyNonRenderable(&mImageArray[faceindex][level], getFormat(), 0, 0, x, y, width, height, renderTarget);

-    }

-    else

-    {

-        if (redefined)

-        {

-            convertToRenderTarget();

-            pushTexture(mTexture, true);

-        }

-        else

-        {

-            needRenderTarget();

-        }

-

-        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()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, destYOffset, dest);

-            dest->Release();

-        }

-    }

-}

-

-bool TextureCubeMap::isCubeComplete() const

-{

-    if (mImageArray[0][0].width == 0)

-    {

-        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)

-        {

-            return false;

-        }

-    }

-

-    return true;

-}

-

-void TextureCubeMap::generateMipmaps()

-{

-    if (!isPow2(mImageArray[0][0].width) || !isCubeComplete())

-    {

-        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);

-    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].dirty = false;

-

-            mImageArray[f][i].format = mImageArray[f][0].format;

-            mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);

-            mImageArray[f][i].height = mImageArray[f][i].width;

-        }

-    }

-

-    if (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);

-

-                if (upper != NULL && lower != NULL)

-                {

-                    getBlitter()->boxFilter(upper, lower);

-                }

-

-                if (upper != NULL) upper->Release();

-                if (lower != NULL) lower->Release();

-            }

-        }

-    }

-    else

-    {

-        for (unsigned int f = 0; f < 6; f++)

-        {

-            for (unsigned int i = 1; i <= q; i++)

-            {

-                createSurface(mImageArray[f][i].width, mImageArray[f][i].height, mImageArray[f][i].format, mType, &mImageArray[f][i]);

-                if (mImageArray[f][i].surface == 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)))

-                {

-                    ERR(" failed to load filter %d to %d.", i - 1, i);

-                }

-

-                mImageArray[f][i].dirty = true;

-            }

-        }

-

-        mDirtyMetaData = true;

-    }

-}

-

-Renderbuffer *TextureCubeMap::getColorbuffer(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 TextureColorbufferProxy(this, target)));

-    }

-

-    return mFaceProxies[face].get();

-}

-

-IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)

-{

-    ASSERT(IsCubemapTextureTarget(target));

-

-    needRenderTarget();

-    

-    if (mTexture == NULL)

-    {

-        return NULL;

-    }

-    

-    IDirect3DSurface9 *renderTarget = NULL;

-    mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(target), 0, &renderTarget);

-

-    return renderTarget;

-}

-

-Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target)

-  : Colorbuffer(texture), mTexture(texture), mTarget(target)

-{

-    ASSERT(IsTextureTarget(target));

-}

-

-void Texture::TextureColorbufferProxy::addRef() const

-{

-    mTexture->addRef();

-}

-

-void Texture::TextureColorbufferProxy::release() const

-{

-    mTexture->release();

-}

-

-IDirect3DSurface9 *Texture::TextureColorbufferProxy::getRenderTarget()

-{

-    if (mRenderTarget) mRenderTarget->Release();

-

-    mRenderTarget = mTexture->getRenderTarget(mTarget);

-

-    return mRenderTarget;

-}

-

-int Texture::TextureColorbufferProxy::getWidth() const

-{

-    return mTexture->getWidth();

-}

-

-int Texture::TextureColorbufferProxy::getHeight() const

-{

-    return mTexture->getHeight();

-}

-

-GLenum Texture::TextureColorbufferProxy::getFormat() const

-{

-    return mTexture->getFormat();

-}

-

-bool Texture::TextureColorbufferProxy::isFloatingPoint() const

-{

-    return mTexture->isFloatingPoint();

-}

-

-}

+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Texture.cpp: Implements the gl::Texture class and its derived classes
+// Texture2D and TextureCubeMap. Implements GL texture objects and related
+// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#include "libGLESv2/Texture.h"
+
+#include <d3dx9tex.h>
+
+#include <algorithm>
+
+#include "common/debug.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/Blit.h"
+#include "libGLESv2/Framebuffer.h"
+
+namespace gl
+{
+
+Texture::Image::Image()
+  : width(0), height(0), dirty(false), surface(NULL), format(GL_NONE)
+{
+}
+
+Texture::Image::~Image()
+{
+  if (surface) surface->Release();
+}
+
+Texture::Texture(GLuint id) : RefCountObject(id)
+{
+    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
+    mMagFilter = GL_LINEAR;
+    mWrapS = GL_REPEAT;
+    mWrapT = GL_REPEAT;
+
+    mWidth = 0;
+    mHeight = 0;
+
+    mDirtyMetaData = true;
+    mDirty = true;
+    mIsRenderable = false;
+    mType = GL_UNSIGNED_BYTE;
+    mBaseTexture = NULL;
+}
+
+Texture::~Texture()
+{
+}
+
+Blit *Texture::getBlitter()
+{
+    Context *context = getContext();
+    return context->getBlitter();
+}
+
+// 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;
+                mDirty = 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;
+                mDirty = 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;
+                mDirty = 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;
+                mDirty = 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;
+}
+
+GLsizei Texture::getWidth() const
+{
+    return mWidth;
+}
+
+GLsizei Texture::getHeight() const
+{
+    return mHeight;
+}
+
+bool Texture::isFloatingPoint() const
+{
+    return (mType == GL_FLOAT || mType == GL_HALF_FLOAT_OES);
+}
+
+bool Texture::isRenderableFormat() const
+{
+    D3DFORMAT format = getD3DFormat();
+    
+    switch(format)
+    {
+      case D3DFMT_L8:
+      case D3DFMT_A8L8:
+      case D3DFMT_DXT1:
+        return false;
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_X8R8G8B8:
+      case D3DFMT_A16B16G16R16F:
+      case D3DFMT_A32B32G32R32F:
+        return true;
+      default:
+        UNREACHABLE();
+    }
+
+    return false;
+}
+
+// Selects an internal Direct3D 9 format for storing an Image
+D3DFORMAT Texture::selectFormat(GLenum format, GLenum type)
+{
+    if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+        format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+    {
+        return D3DFMT_DXT1;
+    }
+    else if (type == GL_FLOAT)
+    {
+        return D3DFMT_A32B32G32R32F;
+    }
+    else if (type == GL_HALF_FLOAT_OES)
+    {
+        return D3DFMT_A16B16G16R16F;
+    }
+    else if (type == GL_UNSIGNED_BYTE)
+    {
+        if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
+        {
+            return D3DFMT_L8;
+        }
+        else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
+        {
+            return D3DFMT_A8L8;
+        }
+        else if (format == GL_RGB)
+        {
+            return D3DFMT_X8R8G8B8;
+        }
+
+        return D3DFMT_A8R8G8B8;
+    }
+
+    return D3DFMT_A8R8G8B8;
+}
+
+// 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
+{
+    GLsizei inputPitch = -ComputePitch(width, format, type, unpackAlignment);
+    input = ((char*)input) - inputPitch * (height - 1);
+
+    switch (type)
+    {
+      case GL_UNSIGNED_BYTE:
+        switch (format)
+        {
+          case GL_ALPHA:
+            loadAlphaImageData(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);
+            break;
+          case GL_LUMINANCE_ALPHA:
+            loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_A8L8);
+            break;
+          case GL_RGB:
+            loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          case GL_RGBA:
+            loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          case GL_BGRA_EXT:
+            loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_UNSIGNED_SHORT_5_6_5:
+        switch (format)
+        {
+          case GL_RGB:
+            loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_UNSIGNED_SHORT_4_4_4_4:
+        switch (format)
+        {
+          case GL_RGBA:
+            loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_UNSIGNED_SHORT_5_5_5_1:
+        switch (format)
+        {
+          case GL_RGBA:
+            loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT:
+        switch (format)
+        {
+          // 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);
+            break;
+          case GL_LUMINANCE:
+            loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          case GL_LUMINANCE_ALPHA:
+            loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          case GL_RGB:
+            loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          case GL_RGBA:
+            loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_HALF_FLOAT_OES:
+        switch (format)
+        {
+          // 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);
+            break;
+          case GL_LUMINANCE:
+            loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          case GL_LUMINANCE_ALPHA:
+            loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          case GL_RGB:
+            loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            break;
+          case GL_RGBA:
+            loadRGBAHalfFloatImageData(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
+{
+    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;
+        for (int x = 0; x < width; 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
+{
+    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);
+        for (int x = 0; x < width; x++)
+        {
+            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
+{
+    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);
+        for (int x = 0; x < width; x++)
+        {
+            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
+{
+    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;
+        dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;
+
+        if (!native)   // BGRA8 destination format
+        {
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x];
+                dest[4 * x + 1] = source[x];
+                dest[4 * x + 2] = source[x];
+                dest[4 * x + 3] = 0xFF;
+            }
+        }
+        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
+{
+    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);
+        for (int x = 0; x < width; x++)
+        {
+            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
+{
+    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);
+        for (int x = 0; x < width; x++)
+        {
+            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
+{
+    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;
+        dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;
+        
+        if (!native)   // BGRA8 destination format
+        {
+            for (int x = 0; x < width; x++)
+            {
+                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];
+            }
+        }
+        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
+{
+    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);
+        for (int x = 0; x < width; x++)
+        {
+            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
+{
+    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);
+        for (int x = 0; x < width; x++)
+        {
+            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
+{
+    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;
+        for (int x = 0; x < width; x++)
+        {
+            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
+{
+    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;
+        for (int x = 0; x < width; x++)
+        {
+            unsigned short rgba = source[x];
+            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
+{
+    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);
+        for (int x = 0; x < width; x++)
+        {
+            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
+{
+    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);
+        for (int x = 0; x < width; x++)
+        {
+            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::loadRGBAUByteImageData(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;
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = source[x * 4 + 2];
+            dest[4 * x + 1] = source[x * 4 + 1];
+            dest[4 * x + 2] = source[x * 4 + 0];
+            dest[4 * x + 3] = source[x * 4 + 3];
+        }
+    }
+}
+
+void Texture::loadRGBA4444ImageData(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;
+        for (int x = 0; x < width; x++)
+        {
+            unsigned short rgba = source[x];
+            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
+{
+    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;
+        for (int x = 0; x < width; x++)
+        {
+            unsigned short rgba = source[x];
+            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
+{
+    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
+{
+    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
+{
+    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
+{
+    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);
+    unsigned int *dest = reinterpret_cast<unsigned int*>(output);
+
+    switch (height)
+    {
+        case 1:
+            // Round width up in case it is 1.
+            for (int x = 0; x < (width + 1) / 2; x += 2)
+            {
+                // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
+                dest[x] = source[x];
+
+                // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors, the last 3 rows being unused. No flipping should occur.
+                dest[x + 1] = source[x + 1];
+            }
+            break;
+        case 2:
+            // Round width up in case it is 1.
+            for (int x = 0; x < (width + 1) / 2; x += 2)
+            {
+                // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
+                dest[x] = source[x];
+
+                // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors, the last 2 rows being unused. Only the top 2 rows should be flipped.
+                dest[x + 1] = ((source[x + 1] << 8) & 0x0000FF00) |
+                              ((source[x + 1] >> 8) & 0x000000FF);       
+            }
+            break;
+        default:
+            ASSERT(height % 4 == 0);
+            for (int y = 0; y < height / 4; ++y)
+            {
+                const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+                unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
+
+                // Round width up in case it is 1.
+                for (int x = 0; x < (width + 1) / 2; x += 2)
+                {
+                    // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
+                    dest[x] = source[x];
+
+                    // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.
+                    dest[x + 1] = (source[x + 1] >> 24) | 
+                                  ((source[x + 1] << 8) & 0x00FF0000) |
+                                  ((source[x + 1] >> 8) & 0x0000FF00) |
+                                  (source[x + 1] << 24);                    
+                }
+            }
+            break;
+    }
+}
+
+void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img)
+{
+    IDirect3DTexture9 *newTexture = NULL;
+    IDirect3DSurface9 *newSurface = NULL;
+
+    if (width != 0 && height != 0)
+    {
+        int levelToFetch = 0;
+        GLsizei requestWidth = width;
+        GLsizei requestHeight = height;
+        if (IsCompressed(format) && (width % 4 != 0 || 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, selectFormat(format, type),
+                                                    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 (img->surface) img->surface->Release();
+    img->surface = newSurface;
+
+    img->width = width;
+    img->height = height;
+    img->format = format;
+}
+
+void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
+{
+    createSurface(width, height, format, type, img);
+
+    if (pixels != NULL && img->surface != NULL)
+    {
+        D3DSURFACE_DESC description;
+        img->surface->GetDesc(&description);
+
+        D3DLOCKED_RECT locked;
+        HRESULT result = img->surface->LockRect(&locked, NULL, 0);
+
+        ASSERT(SUCCEEDED(result));
+
+        if (SUCCEEDED(result))
+        {
+            loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
+            img->surface->UnlockRect();
+        }
+
+        img->dirty = true;
+    }
+
+    mDirtyMetaData = true;
+}
+
+void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
+{
+    createSurface(width, height, format, GL_UNSIGNED_BYTE, img);
+
+    if (pixels != NULL && img->surface != NULL)
+    {
+        D3DLOCKED_RECT locked;
+        HRESULT result = img->surface->LockRect(&locked, NULL, 0);
+
+        ASSERT(SUCCEEDED(result));
+
+        if (SUCCEEDED(result))
+        {
+            int inputPitch = ComputeCompressedPitch(width, format);
+            int inputSize = ComputeCompressedSize(width, height, format);
+            loadCompressedImageData(0, 0, width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
+            img->surface->UnlockRect();
+        }
+
+        img->dirty = true;
+    }
+
+    mDirtyMetaData = true;
+}
+
+bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
+{
+    if (width + xoffset > img->width || height + yoffset > img->height)
+    {
+        error(GL_INVALID_VALUE);
+        return false;
+    }
+
+    if (!img->surface)
+    {
+        createSurface(img->width, img->height, format, type, img);
+    }
+
+    if (pixels != NULL && img->surface != NULL)
+    {
+        D3DSURFACE_DESC description;
+        img->surface->GetDesc(&description);
+
+        D3DLOCKED_RECT locked;
+        HRESULT result = img->surface->LockRect(&locked, NULL, 0);
+
+        ASSERT(SUCCEEDED(result));
+
+        if (SUCCEEDED(result))
+        {
+            loadImageData(xoffset, transformPixelYOffset(yoffset, height, img->height), width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
+            img->surface->UnlockRect();
+        }
+
+        img->dirty = true;
+    }
+
+    return true;
+}
+
+bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
+{
+    if (width + xoffset > img->width || height + yoffset > img->height)
+    {
+        error(GL_INVALID_VALUE);
+        return false;
+    }
+
+    if (format != getInternalFormat())
+    {
+        error(GL_INVALID_OPERATION);
+        return false;
+    }
+
+    if (!img->surface)
+    {
+        createSurface(img->width, img->height, format, GL_UNSIGNED_BYTE, img);
+    }
+
+    if (pixels != NULL && img->surface != NULL)
+    {
+        RECT updateRegion;
+        updateRegion.left = xoffset;
+        updateRegion.right = xoffset + width;
+        updateRegion.bottom = yoffset + height;
+        updateRegion.top = yoffset;
+
+        D3DLOCKED_RECT locked;
+        HRESULT result = img->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, img->height), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
+            img->surface->UnlockRect();
+        }
+
+        img->dirty = true;
+    }
+
+    return true;
+}
+
+// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats
+void Texture::copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
+{
+    IDirect3DDevice9 *device = getDevice();
+    IDirect3DSurface9 *surface = NULL;
+    D3DSURFACE_DESC description;
+    renderTarget->GetDesc(&description);
+    
+    HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
+
+    if (!SUCCEEDED(result))
+    {
+        ERR("Could not create matching destination surface.");
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    result = device->GetRenderTargetData(renderTarget, surface);
+
+    if (!SUCCEEDED(result))
+    {
+        ERR("GetRenderTargetData unexpectedly failed.");
+        surface->Release();
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    D3DLOCKED_RECT sourceLock = {0};
+    RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);
+    result = surface->LockRect(&sourceLock, &sourceRect, 0);
+
+    if (FAILED(result))
+    {
+        ERR("Failed to lock the source surface (rectangle might be invalid).");
+        surface->UnlockRect();
+        surface->Release();
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    if (!image->surface)
+    {
+        createSurface(width, height, internalFormat, mType, image);
+    }
+
+    if (image->surface == NULL)
+    {
+        ERR("Failed to create an image surface.");
+        surface->UnlockRect();
+        surface->Release();
+        return error(GL_OUT_OF_MEMORY); 
+    }
+
+    D3DLOCKED_RECT destLock = {0};
+    int destYOffset = transformPixelYOffset(yoffset, height, image->height);
+    RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};
+    result = image->surface->LockRect(&destLock, &destRect, 0);
+    
+    if (FAILED(result))
+    {
+        ERR("Failed to lock the destination surface (rectangle might be invalid).");
+        surface->UnlockRect();
+        surface->Release();
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    if (destLock.pBits && sourceLock.pBits)
+    {
+        unsigned char *source = (unsigned char*)sourceLock.pBits;
+        unsigned char *dest = (unsigned char*)destLock.pBits;
+
+        switch (description.Format)
+        {
+          case D3DFMT_X8R8G8B8:
+          case D3DFMT_A8R8G8B8:
+            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];
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              case D3DFMT_A8L8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        dest[x * 2 + 0] = source[x * 4 + 2];
+                        dest[x * 2 + 1] = source[x * 4 + 3];
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              default:
+                UNREACHABLE();
+            }
+            break;
+          case D3DFMT_R5G6B5:
+            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);
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              default:
+                UNREACHABLE();
+            }
+            break;
+          case D3DFMT_A1R5G5B5:
+            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);
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              case D3DFMT_A8L8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        unsigned char red = source[x * 2 + 1] & 0x7C;
+                        dest[x * 2 + 0] = (red << 1) | (red >> 4);
+                        dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              default:
+                UNREACHABLE();
+            }
+            break;
+          default:
+            UNREACHABLE();
+        }
+
+        image->dirty = true;
+        mDirtyMetaData = true;    
+    }
+
+    image->surface->UnlockRect();
+    surface->UnlockRect();
+    surface->Release();
+}
+
+D3DFORMAT Texture::getD3DFormat() const
+{
+    return selectFormat(getInternalFormat(), mType);
+}
+
+IDirect3DBaseTexture9 *Texture::getTexture()
+{
+    if (!isComplete())
+    {
+        return NULL;
+    }
+
+    if (mDirtyMetaData)
+    {
+        mBaseTexture = createTexture();
+        mIsRenderable = false;
+    }
+
+    if (mDirtyMetaData || dirtyImageData())
+    {
+        updateTexture();
+    }
+
+    mDirtyMetaData = false;
+    ASSERT(!dirtyImageData());
+
+    return mBaseTexture;
+}
+
+bool Texture::isDirty() const
+{
+    return (mDirty || mDirtyMetaData || dirtyImageData());
+}
+
+// Returns the top-level texture surface as a render target
+void Texture::needRenderTarget()
+{
+    if (!mIsRenderable)
+    {
+        mBaseTexture = convertToRenderTarget();
+        mIsRenderable = true;
+    }
+
+    if (dirtyImageData())
+    {
+        updateTexture();
+    }
+
+    mDirtyMetaData = false;
+}
+
+void Texture::dropTexture()
+{
+    if (mBaseTexture)
+    {
+        mBaseTexture = NULL;
+    }
+
+    mIsRenderable = false;
+}
+
+void Texture::pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable)
+{
+    mBaseTexture = newTexture;
+    mDirtyMetaData = false;
+    mIsRenderable = renderable;
+    mDirty = true;
+}
+
+
+GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
+{
+    if (isPow2(width) && isPow2(height))
+    {
+        return maxlevel;
+    }
+    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
+{
+    return creationLevels(size, size, maxlevel);
+}
+
+int Texture::levelCount() const
+{
+    return mBaseTexture ? mBaseTexture->GetLevelCount() : 0;
+}
+
+bool Texture::isRenderable() const
+{
+    return mIsRenderable;
+}
+
+Texture2D::Texture2D(GLuint id) : Texture(id)
+{
+    mTexture = NULL;
+}
+
+Texture2D::~Texture2D()
+{
+    mColorbufferProxy.set(NULL);
+
+    if (mTexture)
+    {
+        mTexture->Release();
+        mTexture = NULL;
+    }
+}
+
+GLenum Texture2D::getTarget() const
+{
+    return GL_TEXTURE_2D;
+}
+
+GLenum Texture2D::getInternalFormat() const
+{
+    return mImageArray[0].format;
+}
+
+// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
+// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels.
+// Call this when a particular level of the texture must be defined with a specific format, width and height.
+//
+// Returns true if the existing texture was unsuitable and had to be destroyed. If so, it will also set
+// a new height and width for the texture by working backwards from the given width and height.
+bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type)
+{
+    bool widthOkay = (mWidth >> level == width);
+    bool heightOkay = (mHeight >> level == height);
+
+    bool sizeOkay = ((widthOkay && heightOkay)
+                     || (widthOkay && mHeight >> level == 0 && height == 1)
+                     || (heightOkay && mWidth >> level == 0 && width == 1));
+
+    bool typeOkay = (type == mType);
+
+    bool textureOkay = (sizeOkay && typeOkay && internalFormat == mImageArray[0].format);
+
+    if (!textureOkay)
+    {
+        TRACE("Redefining 2D texture (%d, 0x%04X, %d, %d => 0x%04X, %d, %d).", level,
+              mImageArray[0].format, mWidth, mHeight,
+              internalFormat, width, height);
+
+        // Purge all the levels and the texture.
+
+        for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+        {
+            if (mImageArray[i].surface != NULL)
+            {
+                mImageArray[i].dirty = false;
+
+                mImageArray[i].surface->Release();
+                mImageArray[i].surface = NULL;
+            }
+        }
+
+        if (mTexture != NULL)
+        {
+            mTexture->Release();
+            mTexture = NULL;
+            dropTexture();
+        }
+
+        mWidth = width << level;
+        mHeight = height << level;
+        mImageArray[0].format = internalFormat;
+        mType = type;
+    }
+
+    return !textureOkay;
+}
+
+void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    redefineTexture(level, internalFormat, width, height, type);
+
+    Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]);
+}
+
+void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+{
+    redefineTexture(level, internalFormat, width, height, GL_UNSIGNED_BYTE);
+
+    Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);
+}
+
+void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+    ASSERT(mImageArray[level].surface != NULL);
+
+    if (level < levelCount())
+    {
+        IDirect3DSurface9 *destLevel = NULL;
+        HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
+
+        ASSERT(SUCCEEDED(result));
+
+        if (SUCCEEDED(result))
+        {
+            Image *img = &mImageArray[level];
+
+            RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, img->height);;
+
+            POINT destPoint;
+            destPoint.x = sourceRect.left;
+            destPoint.y = sourceRect.top;
+
+            result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
+            ASSERT(SUCCEEDED(result));
+
+            destLevel->Release();
+
+            img->dirty = false;
+        }
+    }
+}
+
+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]))
+    {
+        commitRect(level, xoffset, yoffset, width, height);
+    }
+}
+
+void Texture2D::subImageCompressed(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[level]))
+    {
+        commitRect(level, xoffset, yoffset, width, height);
+    }
+}
+
+void Texture2D::copyImage(GLint level, GLenum internalFormat, 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);
+    }
+
+    bool redefined = redefineTexture(level, internalFormat, width, height, mType);
+   
+    if (!isRenderableFormat())
+    {
+        copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget);
+    }
+    else
+    {
+        if (redefined)
+        {
+            convertToRenderTarget();
+            pushTexture(mTexture, true);
+        }
+        else
+        {
+            needRenderTarget();
+        }
+
+        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());
+            
+            IDirect3DSurface9 *dest;
+            HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
+
+            getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
+            dest->Release();
+        }
+    }
+
+    mImageArray[level].width = width;
+    mImageArray[level].height = height;
+    mImageArray[level].format = internalFormat;
+}
+
+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)
+    {
+        return error(GL_INVALID_VALUE);
+    }
+
+    IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+
+    if (!renderTarget)
+    {
+        ERR("Failed to retrieve the render target.");
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType);
+   
+    if (!isRenderableFormat())
+    {
+        copyNonRenderable(&mImageArray[level], getInternalFormat(), xoffset, yoffset, x, y, width, height, renderTarget);
+    }
+    else
+    {
+        if (redefined)
+        {
+            convertToRenderTarget();
+            pushTexture(mTexture, true);
+        }
+        else
+        {
+            needRenderTarget();
+        }
+
+        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()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, destYOffset, dest);
+            dest->Release();
+        }
+    }
+}
+
+// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture2D::isComplete() const
+{
+    GLsizei width = mImageArray[0].width;
+    GLsizei height = mImageArray[0].height;
+
+    if (width <= 0 || height <= 0)
+    {
+        return false;
+    }
+
+    bool mipmapping = false;
+
+    switch (mMinFilter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+        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();
+    }
+
+    if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
+        (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
+    {
+        if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
+        {
+            return false;
+        }
+    }
+
+
+    if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width))
+        || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
+    {
+        return false;
+    }
+
+    if (mipmapping)
+    {
+        if (!isPow2(width) || !isPow2(height))
+        {
+            return false;
+        }
+
+        int q = log2(std::max(width, height));
+
+        for (int level = 1; level <= q; level++)
+        {
+            if (mImageArray[level].format != mImageArray[0].format)
+            {
+                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 true;
+}
+
+bool Texture2D::isCompressed() const
+{
+    return IsCompressed(getInternalFormat());
+}
+
+// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
+IDirect3DBaseTexture9 *Texture2D::createTexture()
+{
+    IDirect3DTexture9 *texture;
+
+    IDirect3DDevice9 *device = getDevice();
+    D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
+
+    HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+    }
+
+    if (mTexture) mTexture->Release();
+    mTexture = texture;
+    return texture;
+}
+
+void Texture2D::updateTexture()
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    int levels = levelCount();
+
+    for (int level = 0; level < levels; level++)
+    {
+        if (mImageArray[level].dirty)
+        {
+            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;
+            }
+        }
+    }
+}
+
+IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()
+{
+    IDirect3DTexture9 *texture = NULL;
+
+    if (mWidth != 0 && mHeight != 0)
+    {
+        egl::Display *display = getDisplay();
+        IDirect3DDevice9 *device = getDevice();
+        D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
+
+        HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+        }
+
+        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, (IDirect3DBaseTexture9*)NULL);
+                }
+
+                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, (IDirect3DBaseTexture9*)NULL);
+                }
+
+                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, (IDirect3DBaseTexture9*)NULL);
+                }
+
+                source->Release();
+                dest->Release();
+            }
+        }
+    }
+
+    if (mTexture != NULL)
+    {
+        mTexture->Release();
+    }
+
+    mTexture = texture;
+    return mTexture;
+}
+
+bool Texture2D::dirtyImageData() const
+{
+    int q = log2(std::max(mWidth, mHeight));
+
+    for (int i = 0; i <= q; i++)
+    {
+        if (mImageArray[i].dirty) return true;
+    }
+
+    return false;
+}
+
+void Texture2D::generateMipmaps()
+{
+    if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))
+    {
+        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(mWidth, mHeight));
+    for (unsigned int i = 1; i <= q; i++)
+    {
+        if (mImageArray[i].surface != NULL)
+        {
+            mImageArray[i].surface->Release();
+            mImageArray[i].surface = NULL;
+        }
+
+        mImageArray[i].dirty = false;
+
+        mImageArray[i].format = mImageArray[0].format;
+        mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);
+        mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
+    }
+
+    if (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);
+
+            if (upper != NULL && lower != NULL)
+            {
+                getBlitter()->boxFilter(upper, lower);
+            }
+
+            if (upper != NULL) upper->Release();
+            if (lower != NULL) lower->Release();
+        }
+    }
+    else
+    {
+        for (unsigned int i = 1; i <= q; i++)
+        {
+            createSurface(mImageArray[i].width, mImageArray[i].height, mImageArray[i].format, mType, &mImageArray[i]);
+            if (mImageArray[i].surface == 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)))
+            {
+                ERR(" failed to load filter %d to %d.", i - 1, i);
+            }
+
+            mImageArray[i].dirty = true;
+        }
+
+        mDirtyMetaData = true;
+    }
+}
+
+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)));
+    }
+
+    return mColorbufferProxy.get();
+}
+
+IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+
+    needRenderTarget();
+
+    if (mTexture == NULL)
+    {
+        return NULL;
+    }
+    
+    IDirect3DSurface9 *renderTarget = NULL;
+    mTexture->GetSurfaceLevel(0, &renderTarget);
+
+    return renderTarget;
+}
+
+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;
+    }
+}
+
+GLenum TextureCubeMap::getTarget() const
+{
+    return GL_TEXTURE_CUBE_MAP;
+}
+
+GLenum TextureCubeMap::getInternalFormat() const
+{
+    return mImageArray[0][0].format;
+}
+
+void TextureCubeMap::setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(0, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(1, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(2, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(3, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(4, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+{
+    redefineTexture(level, internalFormat, width);
+
+    Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);
+}
+
+void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+    int face = faceIndex(faceTarget);
+    ASSERT(mImageArray[face][level].surface != NULL);
+
+    if (level < levelCount())
+    {
+        IDirect3DSurface9 *destLevel = getCubeMapSurface(faceTarget, level);
+        ASSERT(destLevel != NULL);
+
+        if (destLevel != NULL)
+        {
+            Image *img = &mImageArray[face][level];
+
+            RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, img->height);;
+
+            POINT destPoint;
+            destPoint.x = sourceRect.left;
+            destPoint.y = sourceRect.top;
+
+            HRESULT result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
+            ASSERT(SUCCEEDED(result));
+
+            destLevel->Release();
+
+            img->dirty = false;
+        }
+    }
+}
+
+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);
+    }
+}
+
+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);
+    }
+}
+
+// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureCubeMap::isComplete() const
+{
+    int size = mImageArray[0][0].width;
+
+    if (size <= 0)
+    {
+        return false;
+    }
+
+    bool mipmapping;
+
+    switch (mMinFilter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+        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();
+    }
+
+    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 (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
+        {
+            return false;
+        }
+    }
+
+    if (mipmapping)
+    {
+        if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE))
+        {
+            return false;
+        }
+
+        int q = log2(size);
+
+        for (int face = 0; face < 6; face++)
+        {
+            for (int level = 1; level <= q; level++)
+            {
+                if (mImageArray[face][level].format != mImageArray[0][0].format)
+                {
+                    return false;
+                }
+
+                if (mImageArray[face][level].width != std::max(1, size >> level))
+                {
+                    return false;
+                }
+
+                ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);
+            }
+        }
+    }
+
+    return true;
+}
+
+bool TextureCubeMap::isCompressed() const
+{
+    return IsCompressed(getInternalFormat());
+}
+
+// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
+IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
+{
+    IDirect3DDevice9 *device = getDevice();
+    D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
+
+    IDirect3DCubeTexture9 *texture;
+
+    HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+    }
+
+    if (mTexture) mTexture->Release();
+
+    mTexture = texture;
+    return mTexture;
+}
+
+void TextureCubeMap::updateTexture()
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    for (int face = 0; face < 6; face++)
+    {
+        int levels = levelCount();
+        for (int level = 0; level < levels; level++)
+        {
+            Image *img = &mImageArray[face][level];
+
+            if (img->dirty)
+            {
+                IDirect3DSurface9 *levelSurface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
+                ASSERT(levelSurface != NULL);
+
+                if (levelSurface != NULL)
+                {
+                    HRESULT result = device->UpdateSurface(img->surface, NULL, levelSurface, NULL);
+                    ASSERT(SUCCEEDED(result));
+
+                    levelSurface->Release();
+
+                    img->dirty = false;
+                }
+            }
+        }
+    }
+}
+
+IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()
+{
+    IDirect3DCubeTexture9 *texture = NULL;
+
+    if (mWidth != 0)
+    {
+        egl::Display *display = getDisplay();
+        IDirect3DDevice9 *device = getDevice();
+        D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
+
+        HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+        }
+
+        if (mTexture != NULL)
+        {
+            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, (IDirect3DBaseTexture9*)NULL);
+                    }
+
+                    IDirect3DSurface9 *dest;
+                    result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
+
+                    if (FAILED(result))
+                    {
+                        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+                        texture->Release();
+                        source->Release();
+
+                        return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+                    }
+
+                    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, (IDirect3DBaseTexture9*)NULL);
+                    }
+                }
+            }
+        }
+    }
+
+    if (mTexture != NULL)
+    {
+        mTexture->Release();
+    }
+
+    mTexture = texture;
+    return mTexture;
+}
+
+void TextureCubeMap::setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    redefineTexture(level, internalFormat, width);
+
+    Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[face][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;
+}
+
+bool TextureCubeMap::dirtyImageData() const
+{
+    int q = log2(mWidth);
+
+    for (int f = 0; f < 6; f++)
+    {
+        for (int i = 0; i <= q; i++)
+        {
+            if (mImageArray[f][i].dirty) return true;
+        }
+    }
+
+    return false;
+}
+
+// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
+// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels & faces.
+// Call this when a particular level of the texture must be defined with a specific format, width and height.
+//
+// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set
+// a new size for the texture by working backwards from the given size.
+bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei width)
+{
+    // Are these settings compatible with level 0?
+    bool sizeOkay = (mImageArray[0][0].width >> level == width);
+
+    bool textureOkay = (sizeOkay && internalFormat == mImageArray[0][0].format);
+
+    if (!textureOkay)
+    {
+        TRACE("Redefining cube texture (%d, 0x%04X, %d => 0x%04X, %d).", level,
+              mImageArray[0][0].format, mImageArray[0][0].width,
+              internalFormat, width);
+
+        // Purge all the levels and the texture.
+        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].dirty = false;
+
+                    mImageArray[f][i].surface->Release();
+                    mImageArray[f][i].surface = NULL;
+                }
+            }
+        }
+
+        if (mTexture != NULL)
+        {
+            mTexture->Release();
+            mTexture = NULL;
+            dropTexture();
+        }
+
+        mWidth = width << level;
+        mImageArray[0][0].width = width << level;
+        mHeight = width << level;
+        mImageArray[0][0].height = width << level;
+
+        mImageArray[0][0].format = internalFormat;
+    }
+
+    return !textureOkay;
+}
+
+void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat, 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);
+    bool redefined = redefineTexture(level, internalFormat, width);
+
+    if (!isRenderableFormat())
+    {
+        copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget);
+    }
+    else
+    {
+        if (redefined)
+        {
+            convertToRenderTarget();
+            pushTexture(mTexture, true);
+        }
+        else
+        {
+            needRenderTarget();
+        }
+
+        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());
+
+            IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
+
+            getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
+            dest->Release();
+        }
+    }
+
+    mImageArray[faceindex][level].width = width;
+    mImageArray[faceindex][level].height = height;
+    mImageArray[faceindex][level].format = internalFormat;
+}
+
+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;
+}
+
+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;
+
+    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);
+    bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width);
+   
+    if (!isRenderableFormat())
+    {
+        copyNonRenderable(&mImageArray[faceindex][level], getInternalFormat(), 0, 0, x, y, width, height, renderTarget);
+    }
+    else
+    {
+        if (redefined)
+        {
+            convertToRenderTarget();
+            pushTexture(mTexture, true);
+        }
+        else
+        {
+            needRenderTarget();
+        }
+
+        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()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, destYOffset, dest);
+            dest->Release();
+        }
+    }
+}
+
+bool TextureCubeMap::isCubeComplete() const
+{
+    if (mImageArray[0][0].width == 0)
+    {
+        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)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void TextureCubeMap::generateMipmaps()
+{
+    if (!isPow2(mImageArray[0][0].width) || !isCubeComplete())
+    {
+        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);
+    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].dirty = false;
+
+            mImageArray[f][i].format = mImageArray[f][0].format;
+            mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);
+            mImageArray[f][i].height = mImageArray[f][i].width;
+        }
+    }
+
+    if (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);
+
+                if (upper != NULL && lower != NULL)
+                {
+                    getBlitter()->boxFilter(upper, lower);
+                }
+
+                if (upper != NULL) upper->Release();
+                if (lower != NULL) lower->Release();
+            }
+        }
+    }
+    else
+    {
+        for (unsigned int f = 0; f < 6; f++)
+        {
+            for (unsigned int i = 1; i <= q; i++)
+            {
+                createSurface(mImageArray[f][i].width, mImageArray[f][i].height, mImageArray[f][i].format, mType, &mImageArray[f][i]);
+                if (mImageArray[f][i].surface == 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)))
+                {
+                    ERR(" failed to load filter %d to %d.", i - 1, i);
+                }
+
+                mImageArray[f][i].dirty = true;
+            }
+        }
+
+        mDirtyMetaData = true;
+    }
+}
+
+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)));
+    }
+
+    return mFaceProxies[face].get();
+}
+
+IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
+{
+    ASSERT(IsCubemapTextureTarget(target));
+
+    needRenderTarget();
+    
+    if (mTexture == NULL)
+    {
+        return NULL;
+    }
+    
+    IDirect3DSurface9 *renderTarget = NULL;
+    mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(target), 0, &renderTarget);
+
+    return renderTarget;
+}
+
+}
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 1fd42e0..4060b32 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -57,10 +57,10 @@
     GLenum getWrapS() const;
     GLenum getWrapT() const;
 
-    GLuint getWidth() const;
-    GLuint getHeight() const;
+    GLsizei getWidth() const;
+    GLsizei getHeight() const;
 
-    virtual GLenum getFormat() const = 0;
+    virtual GLenum getInternalFormat() const = 0;
     virtual bool isComplete() const = 0;
     virtual bool isCompressed() const = 0;
     bool isFloatingPoint() const;
@@ -68,38 +68,17 @@
 
     D3DFORMAT getD3DFormat() const;
     IDirect3DBaseTexture9 *getTexture();
-    virtual Renderbuffer *getColorbuffer(GLenum target) = 0;
+    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 isDirty() 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.
+    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:
-    class TextureColorbufferProxy;
-    friend class TextureColorbufferProxy;
-    class TextureColorbufferProxy : public Colorbuffer
-    {
-      public:
-        TextureColorbufferProxy(Texture *texture, GLenum target);
-            // target is a 2D-like texture target (GL_TEXTURE_2D or one of the cube face targets)
-
-        virtual void addRef() const;
-        virtual void release() const;
-
-        virtual IDirect3DSurface9 *getRenderTarget();
-
-        virtual int getWidth() const;
-        virtual int getHeight() const;
-        virtual GLenum getFormat() const;
-        virtual bool isFloatingPoint() const;
-
-      private:
-        Texture *mTexture;
-        GLenum mTarget;
-    };
+    friend class Colorbuffer;
 
     // Helper structure representing a single image layer
     struct Image
@@ -147,8 +126,8 @@
 
     bool isRenderable() const;
 
-    unsigned int mWidth;
-    unsigned int mHeight;
+    GLsizei mWidth;
+    GLsizei mHeight;
     GLenum mMinFilter;
     GLenum mMagFilter;
     GLenum mWrapS;
@@ -218,7 +197,7 @@
     ~Texture2D();
 
     GLenum getTarget() const;
-    GLenum getFormat() const;
+    GLenum getInternalFormat() const;
 
     void setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
     void setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
@@ -232,7 +211,7 @@
 
     virtual void generateMipmaps();
 
-    virtual Renderbuffer *getColorbuffer(GLenum target);
+    virtual Renderbuffer *getRenderbuffer(GLenum target);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture2D);
@@ -262,7 +241,7 @@
     ~TextureCubeMap();
 
     GLenum getTarget() const;
-    GLenum getFormat() const;
+    GLenum getInternalFormat() const;
 
     void setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
     void setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
@@ -283,7 +262,7 @@
 
     virtual void generateMipmaps();
 
-    virtual Renderbuffer *getColorbuffer(GLenum target);
+    virtual Renderbuffer *getRenderbuffer(GLenum target);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index cfc3a45..9ab0abe 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1044,7 +1044,7 @@
             }
 
             gl::Colorbuffer *source = framebuffer->getColorbuffer();
-            GLenum colorbufferFormat = source->getFormat();
+            GLenum colorbufferFormat = source->getInternalFormat();
 
             // [OpenGL ES 2.0.24] table 3.9
             switch (internalformat)
@@ -1178,7 +1178,7 @@
             }
 
             gl::Colorbuffer *source = framebuffer->getColorbuffer();
-            GLenum colorbufferFormat = source->getFormat();
+            GLenum colorbufferFormat = source->getInternalFormat();
             gl::Texture *texture = NULL;
 
             if (target == GL_TEXTURE_2D)
@@ -1196,7 +1196,7 @@
                 return error(GL_INVALID_OPERATION);
             }
 
-            GLenum textureFormat = texture->getFormat();
+            GLenum textureFormat = texture->getInternalFormat();
 
             // [OpenGL ES 2.0.24] table 3.9
             switch (textureFormat)
@@ -2954,85 +2954,23 @@
 
             switch (pname)
             {
-              case GL_RENDERBUFFER_WIDTH:
-                *params = renderbuffer->getWidth();
-                break;
-              case GL_RENDERBUFFER_HEIGHT:
-                *params = renderbuffer->getHeight();
-                break;
-              case GL_RENDERBUFFER_INTERNAL_FORMAT:
-                *params = renderbuffer->getFormat();
-                break;
-              case GL_RENDERBUFFER_RED_SIZE:
-                if (renderbuffer->isColorbuffer())
-                {
-                    *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getRedSize();
-                }
-                else
-                {
-                    *params = 0;
-                }
-                break;
-              case GL_RENDERBUFFER_GREEN_SIZE:
-                if (renderbuffer->isColorbuffer())
-                {
-                    *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getGreenSize();
-                }
-                else
-                {
-                    *params = 0;
-                }
-                break;
-              case GL_RENDERBUFFER_BLUE_SIZE:
-                if (renderbuffer->isColorbuffer())
-                {
-                    *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getBlueSize();
-                }
-                else
-                {
-                    *params = 0;
-                }
-                break;
-              case GL_RENDERBUFFER_ALPHA_SIZE:
-                if (renderbuffer->isColorbuffer())
-                {
-                    *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getAlphaSize();
-                }
-                else
-                {
-                    *params = 0;
-                }
-                break;
-              case GL_RENDERBUFFER_DEPTH_SIZE:
-                if (renderbuffer->isDepthbuffer())
-                {
-                    *params = static_cast<gl::Depthbuffer*>(renderbuffer->getStorage())->getDepthSize();
-                }
-                else
-                {
-                    *params = 0;
-                }
-                break;
-              case GL_RENDERBUFFER_STENCIL_SIZE:
-                if (renderbuffer->isStencilbuffer())
-                {
-                    *params = static_cast<gl::Stencilbuffer*>(renderbuffer->getStorage())->getStencilSize();
-                }
-                else
-                {
-                    *params = 0;
-                }
-                break;
+              case GL_RENDERBUFFER_WIDTH:           *params = renderbuffer->getWidth();          break;
+              case GL_RENDERBUFFER_HEIGHT:          *params = renderbuffer->getHeight();         break;
+              case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
+              case GL_RENDERBUFFER_RED_SIZE:        *params = renderbuffer->getRedSize();        break;
+              case GL_RENDERBUFFER_GREEN_SIZE:      *params = renderbuffer->getGreenSize();      break;
+              case GL_RENDERBUFFER_BLUE_SIZE:       *params = renderbuffer->getBlueSize();       break;
+              case GL_RENDERBUFFER_ALPHA_SIZE:      *params = renderbuffer->getAlphaSize();      break;
+              case GL_RENDERBUFFER_DEPTH_SIZE:      *params = renderbuffer->getDepthSize();      break;
+              case GL_RENDERBUFFER_STENCIL_SIZE:    *params = renderbuffer->getStencilSize();    break;
               case GL_RENDERBUFFER_SAMPLES_ANGLE:
+                if (context->getMaxSupportedSamples() != 0)
                 {
-                    if (context->getMaxSupportedSamples() != 0)
-                    {
-                        *params = renderbuffer->getStorage()->getSamples();
-                    }
-                    else
-                    {
-                        return error(GL_INVALID_ENUM);
-                    }
+                    *params = renderbuffer->getSamples();
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
                 }
                 break;
               default:
@@ -4797,7 +4735,7 @@
                     return error(GL_INVALID_OPERATION);
                 }
 
-                if (format != texture->getFormat())
+                if (format != texture->getInternalFormat())
                 {
                     return error(GL_INVALID_OPERATION);
                 }
@@ -4818,7 +4756,7 @@
                     return error(GL_INVALID_OPERATION);
                 }
 
-                if (format != texture->getFormat())
+                if (format != texture->getInternalFormat())
                 {
                     return error(GL_INVALID_OPERATION);
                 }
diff --git a/src/libGLESv2/utilities.cpp b/src/libGLESv2/utilities.cpp
index f0f940b..ae1df8e 100644
--- a/src/libGLESv2/utilities.cpp
+++ b/src/libGLESv2/utilities.cpp
@@ -608,6 +608,75 @@
     }
 }
 
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
+                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
+{
+    switch (primitiveType)
+    {
+      case GL_POINTS:
+        *d3dPrimitiveType = D3DPT_POINTLIST;
+        *d3dPrimitiveCount = elementCount;
+        break;
+      case GL_LINES:
+        *d3dPrimitiveType = D3DPT_LINELIST;
+        *d3dPrimitiveCount = elementCount / 2;
+        break;
+      case GL_LINE_LOOP:
+        *d3dPrimitiveType = D3DPT_LINESTRIP;
+        *d3dPrimitiveCount = elementCount - 1;   // D3D doesn't support line loops, so we draw the last line separately
+        break;
+      case GL_LINE_STRIP:
+        *d3dPrimitiveType = D3DPT_LINESTRIP;
+        *d3dPrimitiveCount = elementCount - 1;
+        break;
+      case GL_TRIANGLES:
+        *d3dPrimitiveType = D3DPT_TRIANGLELIST;
+        *d3dPrimitiveCount = elementCount / 3;
+        break;
+      case GL_TRIANGLE_STRIP:
+        *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
+        *d3dPrimitiveCount = elementCount - 2;
+        break;
+      case GL_TRIANGLE_FAN:
+        *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
+        *d3dPrimitiveCount = elementCount - 2;
+        break;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+D3DFORMAT ConvertRenderbufferFormat(GLenum format)
+{
+    switch (format)
+    {
+      case GL_RGBA4:
+      case GL_RGB5_A1:
+      case GL_RGBA8_OES:            return D3DFMT_A8R8G8B8;
+      case GL_RGB565:               return D3DFMT_R5G6B5;
+      case GL_RGB8_OES:             return D3DFMT_X8R8G8B8;
+      case GL_DEPTH_COMPONENT16:
+      case GL_STENCIL_INDEX8:       
+      case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
+      default: UNREACHABLE();       return D3DFMT_A8R8G8B8;
+    }
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
+{
+    if (samples <= 1)
+        return D3DMULTISAMPLE_NONE;
+    else
+        return (D3DMULTISAMPLE_TYPE)samples;
+}
+
+}
+
+namespace dx2es
+{
+
 unsigned int GetStencilSize(D3DFORMAT stencilFormat)
 {
     switch(stencilFormat)
@@ -625,8 +694,8 @@
       case D3DFMT_D32F_LOCKABLE:
       case D3DFMT_D16:
         return 0;
-//      case D3DFMT_D32_LOCKABLE:  return 0;   // DirectX 9Ex only
-//      case D3DFMT_S8_LOCKABLE:   return 8;   // DirectX 9Ex only
+    //case D3DFMT_D32_LOCKABLE:  return 0;   // DirectX 9Ex only
+    //case D3DFMT_S8_LOCKABLE:   return 8;   // DirectX 9Ex only
       default: UNREACHABLE();
     }
     return 0;
@@ -739,62 +808,6 @@
     return 0;
 }
 
-bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
-                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
-{
-    switch (primitiveType)
-    {
-      case GL_POINTS:
-        *d3dPrimitiveType = D3DPT_POINTLIST;
-        *d3dPrimitiveCount = elementCount;
-        break;
-      case GL_LINES:
-        *d3dPrimitiveType = D3DPT_LINELIST;
-        *d3dPrimitiveCount = elementCount / 2;
-        break;
-      case GL_LINE_LOOP:
-        *d3dPrimitiveType = D3DPT_LINESTRIP;
-        *d3dPrimitiveCount = elementCount - 1;   // D3D doesn't support line loops, so we draw the last line separately
-        break;
-      case GL_LINE_STRIP:
-        *d3dPrimitiveType = D3DPT_LINESTRIP;
-        *d3dPrimitiveCount = elementCount - 1;
-        break;
-      case GL_TRIANGLES:
-        *d3dPrimitiveType = D3DPT_TRIANGLELIST;
-        *d3dPrimitiveCount = elementCount / 3;
-        break;
-      case GL_TRIANGLE_STRIP:
-        *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
-        *d3dPrimitiveCount = elementCount - 2;
-        break;
-      case GL_TRIANGLE_FAN:
-        *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
-        *d3dPrimitiveCount = elementCount - 2;
-        break;
-      default:
-        return false;
-    }
-
-    return true;
-}
-
-D3DFORMAT ConvertRenderbufferFormat(GLenum format)
-{
-    switch (format)
-    {
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGBA8_OES:            return D3DFMT_A8R8G8B8;
-      case GL_RGB565:               return D3DFMT_R5G6B5;
-      case GL_RGB8_OES:             return D3DFMT_X8R8G8B8;
-      case GL_DEPTH_COMPONENT16:
-      case GL_STENCIL_INDEX8:       
-      case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
-      default: UNREACHABLE();       return D3DFMT_A8R8G8B8;
-    }
-}
-
 GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
 {
     if (type == D3DMULTISAMPLE_NONMASKABLE)
@@ -803,19 +816,6 @@
         return type;
 }
 
-D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
-{
-    if (samples <= 1)
-        return D3DMULTISAMPLE_NONE;
-    else
-        return (D3DMULTISAMPLE_TYPE)samples;
-}
-
-}
-
-namespace dx2es
-{
-
 GLenum ConvertBackBufferFormat(D3DFORMAT format)
 {
     switch (format)
@@ -852,33 +852,33 @@
 
 std::string getTempPath()
 {
-    char path[MAX_PATH];

-    DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);

-    if (pathLen == 0)

-    {

-        UNREACHABLE();

-        return std::string();

-    }

-

-    UINT unique = GetTempFileNameA(path, "sh", 0, path);

-    if (unique == 0)

-    {

-        UNREACHABLE();

-        return std::string();

-    }

-    

-    return path;

+    char path[MAX_PATH];
+    DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
+    if (pathLen == 0)
+    {
+        UNREACHABLE();
+        return std::string();
+    }
+
+    UINT unique = GetTempFileNameA(path, "sh", 0, path);
+    if (unique == 0)
+    {
+        UNREACHABLE();
+        return std::string();
+    }
+    
+    return path;
 }
 
 void writeFile(const char* path, const void* content, size_t size)
-{

-    FILE* file = fopen(path, "w");

-    if (!file)

-    {

-        UNREACHABLE();

-        return;

-    }

-

-    fwrite(content, sizeof(char), size, file);

-    fclose(file);

+{
+    FILE* file = fopen(path, "w");
+    if (!file)
+    {
+        UNREACHABLE();
+        return;
+    }
+
+    fwrite(content, sizeof(char), size, file);
+    fclose(file);
 }
diff --git a/src/libGLESv2/utilities.h b/src/libGLESv2/utilities.h
index ea75900..bf7f4f9 100644
--- a/src/libGLESv2/utilities.h
+++ b/src/libGLESv2/utilities.h
@@ -58,22 +58,23 @@
 DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
 D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter);
 void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter);
-unsigned int GetAlphaSize(D3DFORMAT colorFormat);
-unsigned int GetRedSize(D3DFORMAT colorFormat);
-unsigned int GetGreenSize(D3DFORMAT colorFormat);
-unsigned int GetBlueSize(D3DFORMAT colorFormat);
-unsigned int GetDepthSize(D3DFORMAT depthFormat);
-unsigned int GetStencilSize(D3DFORMAT stencilFormat);
 bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
                           D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount);
 D3DFORMAT ConvertRenderbufferFormat(GLenum format);
 D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);
-GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
 
 }
 
 namespace dx2es
 {
+GLuint GetAlphaSize(D3DFORMAT colorFormat);
+GLuint GetRedSize(D3DFORMAT colorFormat);
+GLuint GetGreenSize(D3DFORMAT colorFormat);
+GLuint GetBlueSize(D3DFORMAT colorFormat);
+GLuint GetDepthSize(D3DFORMAT depthFormat);
+GLuint GetStencilSize(D3DFORMAT stencilFormat);
+
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
 
 GLenum ConvertBackBufferFormat(D3DFORMAT format);
 GLenum ConvertDepthStencilFormat(D3DFORMAT format);