Create and load L/LA textures.
TRAC #13792
Signed-off-by: Daniel Koch

Author:    Nicolas Capens

git-svn-id: http://angleproject.googlecode.com/svn/trunk@456 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 9128f13..ea81166 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -196,16 +196,27 @@
     {
         return D3DFMT_A16B16G16R16F;
     }
-    else
+    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;
+        }
+
         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 BGRA8 pixel rectangle at output with outputPitch bytes in between each line.
+// 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) const
+                            GLint unpackAlignment, const void *input, size_t outputPitch, void *output, D3DSURFACE_DESC *description) const
 {
     GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment);
 
@@ -218,10 +229,10 @@
             loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
             break;
           case GL_LUMINANCE:
-            loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+            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);
+            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);
@@ -371,7 +382,7 @@
 }
 
 void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                     size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+                                     size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
@@ -380,12 +391,20 @@
     {
         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++)
+
+        if (!native)   // BGRA8 destination format
         {
-            dest[4 * x + 0] = source[x];
-            dest[4 * x + 1] = source[x];
-            dest[4 * x + 2] = source[x];
-            dest[4 * x + 3] = 0xFF;
+            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);
         }
     }
 }
@@ -431,7 +450,7 @@
 }
 
 void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                          size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+                                          size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
@@ -440,12 +459,20 @@
     {
         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++)
+        
+        if (!native)   // BGRA8 destination format
         {
-            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];
+            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);
         }
     }
 }
@@ -729,6 +756,9 @@
 
     if (pixels != NULL && img->surface != NULL)
     {
+        D3DSURFACE_DESC description;
+        img->surface->GetDesc(&description);
+
         D3DLOCKED_RECT locked;
         HRESULT result = img->surface->LockRect(&locked, NULL, 0);
 
@@ -736,7 +766,7 @@
 
         if (SUCCEEDED(result))
         {
-            loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
+            loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
             img->surface->UnlockRect();
         }
 
@@ -784,6 +814,9 @@
 
     if (pixels != NULL && img->surface != NULL)
     {
+        D3DSURFACE_DESC description;
+        img->surface->GetDesc(&description);
+
         D3DLOCKED_RECT locked;
         HRESULT result = img->surface->LockRect(&locked, NULL, 0);
 
@@ -791,7 +824,7 @@
 
         if (SUCCEEDED(result))
         {
-            loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
+            loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
             img->surface->UnlockRect();
         }
 
@@ -973,7 +1006,7 @@
 // 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 had to be destroyed. If so, it will also set
+// 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)
 {
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 5cf3214..256b759 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -152,7 +152,7 @@
     DISALLOW_COPY_AND_ASSIGN(Texture);
 
     void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
-                       GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output) const;
+                       GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output, D3DSURFACE_DESC *description) const;
 
     void loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
                             size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
@@ -161,13 +161,13 @@
     void loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
                                      size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
     void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+                                size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
     void loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
                                      size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
     void loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
                                          size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
     void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                     size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+                                     size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
     void loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
                                           size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
     void loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,