summaryrefslogtreecommitdiffstats
path: root/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp')
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp1054
1 files changed, 852 insertions, 202 deletions
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
index 2e0b1e3..7c040f8 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
@@ -10,6 +10,8 @@
#include "libGLESv2/Texture.h"
+#include <d3dx9tex.h>
+
#include <algorithm>
#include "common/debug.h"
@@ -45,6 +47,7 @@ Texture::Texture(GLuint id) : RefCountObject(id)
mDirtyMetaData = true;
mDirty = true;
mIsRenderable = false;
+ mType = GL_UNSIGNED_BYTE;
mBaseTexture = NULL;
}
@@ -174,86 +177,171 @@ 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)
+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
+ 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;
}
-}
-int Texture::imagePitch(const Image &img) const
-{
- return img.width * 4;
+ 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);
- switch (format)
+ switch (type)
{
- 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);
- break;
-
- case GL_LUMINANCE_ALPHA:
- loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
- break;
-
- case GL_RGB:
- switch (type)
+ case GL_UNSIGNED_BYTE:
+ switch (format)
{
- case GL_UNSIGNED_BYTE:
+ 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_UNSIGNED_SHORT_5_6_5:
- loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ 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_RGBA:
- switch (type)
+ case GL_UNSIGNED_SHORT_5_6_5:
+ switch (format)
{
- case GL_UNSIGNED_BYTE:
- loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ case GL_RGB:
+ loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
-
- case GL_UNSIGNED_SHORT_4_4_4_4:
+ 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;
-
- case GL_UNSIGNED_SHORT_5_5_5_1:
+ 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_BGRA_EXT:
- switch (type)
+ case GL_FLOAT:
+ switch (format)
{
- case GL_UNSIGNED_BYTE:
- loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ // 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;
@@ -281,36 +369,174 @@ void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GL
}
}
+void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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,
+ size_t 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,
- 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 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 * 4;
+ 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,
+ size_t 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] = 0xFF;
+ dest[4 * x + 3] = 1.0f;
+ }
+ }
+}
+
+void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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,
- 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 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 * 4;
+ 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,
+ size_t 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,
+ size_t 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];
@@ -362,6 +588,46 @@ void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, G
}
}
+void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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,
+ size_t 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,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const
{
@@ -424,6 +690,34 @@ void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width,
}
}
+void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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,
+ size_t 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,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const
{
@@ -438,7 +732,7 @@ void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLs
}
}
-void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, Image *img)
+void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img)
{
IDirect3DTexture9 *newTexture = NULL;
IDirect3DSurface9 *newSurface = NULL;
@@ -465,7 +759,7 @@ void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, Image
levelToFetch = upsampleCount;
}
- HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, selectFormat(format),
+ HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, selectFormat(format, type),
D3DPOOL_SYSTEMMEM, &newTexture, NULL);
if (FAILED(result))
@@ -488,10 +782,13 @@ void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, Image
void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
{
- createSurface(width, height, format, 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);
@@ -499,7 +796,7 @@ void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type
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();
}
@@ -511,7 +808,7 @@ void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type
void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
{
- createSurface(width, height, format, img);
+ createSurface(width, height, format, GL_UNSIGNED_BYTE, img);
if (pixels != NULL && img->surface != NULL)
{
@@ -540,18 +837,30 @@ bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
return false;
}
- D3DLOCKED_RECT locked;
- HRESULT result = img->surface->LockRect(&locked, NULL, 0);
-
- ASSERT(SUCCEEDED(result));
+ if (!img->surface)
+ {
+ createSurface(img->width, img->height, format, type, img);
+ }
- if (SUCCEEDED(result))
+ if (pixels != NULL && img->surface != NULL)
{
- loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
- img->surface->UnlockRect();
+ 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, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
+ img->surface->UnlockRect();
+ }
+
+ img->dirty = true;
}
- img->dirty = true;
return true;
}
@@ -569,32 +878,215 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL
return false;
}
- RECT updateRegion;
- updateRegion.left = xoffset;
- updateRegion.right = xoffset + width;
- updateRegion.bottom = yoffset + height;
- updateRegion.top = yoffset;
+ 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);
+ D3DLOCKED_RECT locked;
+ HRESULT result = img->surface->LockRect(&locked, &updateRegion, 0);
- ASSERT(SUCCEEDED(result));
+ ASSERT(SUCCEEDED(result));
- if (SUCCEEDED(result))
- {
- GLsizei inputPitch = ComputeCompressedPitch(width, format);
- int rows = imageSize / inputPitch;
- for (int i = 0; i < rows; ++i)
+ if (SUCCEEDED(result))
{
- memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch);
+ GLsizei inputPitch = ComputeCompressedPitch(width, format);
+ int rows = imageSize / inputPitch;
+ for (int i = 0; i < rows; ++i)
+ {
+ memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch);
+ }
+ img->surface->UnlockRect();
}
- img->surface->UnlockRect();
+
+ img->dirty = true;
}
- 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 = {x, y, x + width, y + 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};
+ RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + 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())
@@ -683,15 +1175,19 @@ int Texture::levelCount() const
return mBaseTexture ? mBaseTexture->GetLevelCount() : 0;
}
+bool Texture::isRenderable() const
+{
+ return mIsRenderable;
+}
+
Texture2D::Texture2D(GLuint id) : Texture(id)
{
mTexture = NULL;
- mColorbufferProxy = NULL;
}
Texture2D::~Texture2D()
{
- delete mColorbufferProxy;
+ mColorbufferProxy.set(NULL);
if (mTexture)
{
@@ -714,9 +1210,9 @@ GLenum Texture2D::getFormat() const
// 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)
+bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type)
{
bool widthOkay = (mWidth >> level == width);
bool heightOkay = (mHeight >> level == height);
@@ -725,7 +1221,9 @@ bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei widt
|| (widthOkay && mHeight >> level == 0 && height == 1)
|| (heightOkay && mWidth >> level == 0 && width == 1));
- bool textureOkay = (sizeOkay && internalFormat == mImageArray[0].format);
+ bool typeOkay = (type == mType);
+
+ bool textureOkay = (sizeOkay && typeOkay && internalFormat == mImageArray[0].format);
if (!textureOkay)
{
@@ -735,7 +1233,7 @@ bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei widt
// Purge all the levels and the texture.
- for (int i = 0; i < MAX_TEXTURE_LEVELS; i++)
+ for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
if (mImageArray[i].surface != NULL)
{
@@ -756,6 +1254,7 @@ bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei widt
mWidth = width << level;
mHeight = height << level;
mImageArray[0].format = internalFormat;
+ mType = type;
}
return !textureOkay;
@@ -763,14 +1262,14 @@ bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei widt
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);
+ 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);
+ redefineTexture(level, internalFormat, width, height, GL_UNSIGNED_BYTE);
Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);
}
@@ -828,29 +1327,46 @@ void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GL
void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
{
- if (redefineTexture(level, internalFormat, width, height))
+ IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+
+ if (!renderTarget)
{
- convertToRenderTarget();
- pushTexture(mTexture, true);
+ ERR("Failed to retrieve the render target.");
+ return error(GL_OUT_OF_MEMORY);
}
- else
+
+ bool redefined = redefineTexture(level, internalFormat, width, height, mType);
+
+ if (!isRenderableFormat())
{
- needRenderTarget();
+ copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget);
}
-
- if (width != 0 && height != 0 && level < levelCount())
+ else
{
- RECT sourceRect;
- sourceRect.left = x;
- sourceRect.right = x + width;
- sourceRect.top = y;
- sourceRect.bottom = y + height;
+ if (redefined)
+ {
+ convertToRenderTarget();
+ pushTexture(mTexture, true);
+ }
+ else
+ {
+ needRenderTarget();
+ }
+
+ if (width != 0 && height != 0 && level < levelCount())
+ {
+ RECT sourceRect;
+ sourceRect.left = x;
+ sourceRect.right = x + width;
+ sourceRect.top = y;
+ sourceRect.bottom = y + height;
- IDirect3DSurface9 *dest;
- HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
+ IDirect3DSurface9 *dest;
+ HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
- getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
- dest->Release();
+ getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
+ dest->Release();
+ }
}
mImageArray[level].width = width;
@@ -858,36 +1374,53 @@ void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y,
mImageArray[level].format = internalFormat;
}
-void Texture2D::copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
{
if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
{
return error(GL_INVALID_VALUE);
}
- if (redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height))
+ IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+
+ if (!renderTarget)
{
- convertToRenderTarget();
- pushTexture(mTexture, true);
+ ERR("Failed to retrieve the render target.");
+ return error(GL_OUT_OF_MEMORY);
}
- else
+
+ bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType);
+
+ if (!isRenderableFormat())
{
- needRenderTarget();
+ copyNonRenderable(&mImageArray[level], getFormat(), xoffset, yoffset, x, y, width, height, renderTarget);
}
-
- if (level < levelCount())
+ else
{
- RECT sourceRect;
- sourceRect.left = x;
- sourceRect.right = x + width;
- sourceRect.top = y;
- sourceRect.bottom = y + height;
+ if (redefined)
+ {
+ convertToRenderTarget();
+ pushTexture(mTexture, true);
+ }
+ else
+ {
+ needRenderTarget();
+ }
+
+ if (level < levelCount())
+ {
+ RECT sourceRect;
+ sourceRect.left = x;
+ sourceRect.right = x + width;
+ sourceRect.top = y;
+ sourceRect.bottom = y + height;
- IDirect3DSurface9 *dest;
- HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
+ IDirect3DSurface9 *dest;
+ HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
- getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest);
- dest->Release();
+ getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest);
+ dest->Release();
+ }
}
}
@@ -919,6 +1452,16 @@ bool Texture2D::isComplete() const
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)))
{
@@ -967,7 +1510,7 @@ IDirect3DBaseTexture9 *Texture2D::createTexture()
IDirect3DTexture9 *texture;
IDirect3DDevice9 *device = getDevice();
- D3DFORMAT format = selectFormat(mImageArray[0].format);
+ D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
@@ -1018,7 +1561,7 @@ IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()
{
egl::Display *display = getDisplay();
IDirect3DDevice9 *device = getDevice();
- D3DFORMAT format = selectFormat(mImageArray[0].format);
+ D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
@@ -1123,23 +1666,50 @@ void Texture2D::generateMipmaps()
mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
}
- needRenderTarget();
-
- for (unsigned int i = 1; i <= q; i++)
+ if (isRenderable())
{
- IDirect3DSurface9 *upper = NULL;
- IDirect3DSurface9 *lower = NULL;
+ if (mTexture == NULL)
+ {
+ ERR(" failed because mTexture was null.");
+ return;
+ }
- mTexture->GetSurfaceLevel(i-1, &upper);
- mTexture->GetSurfaceLevel(i, &lower);
+ 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 && lower != NULL)
+ if (upper != NULL) upper->Release();
+ if (lower != NULL) lower->Release();
+ }
+ }
+ else
+ {
+ for (unsigned int i = 1; i <= q; i++)
{
- getBlitter()->boxFilter(upper, lower);
+ 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;
}
- if (upper != NULL) upper->Release();
- if (lower != NULL) lower->Release();
+ mDirtyMetaData = true;
}
}
@@ -1150,13 +1720,12 @@ Renderbuffer *Texture2D::getColorbuffer(GLenum target)
return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
}
- if (mColorbufferProxy == NULL)
+ if (mColorbufferProxy.get() == NULL)
{
- mColorbufferProxy = new Renderbuffer(id(), new TextureColorbufferProxy(this, target));
- mColorbufferProxy->addRef();
+ mColorbufferProxy.set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
}
- return mColorbufferProxy;
+ return mColorbufferProxy.get();
}
IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
@@ -1165,6 +1734,11 @@ IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
needRenderTarget();
+ if (mTexture == NULL)
+ {
+ return NULL;
+ }
+
IDirect3DSurface9 *renderTarget = NULL;
mTexture->GetSurfaceLevel(0, &renderTarget);
@@ -1174,18 +1748,13 @@ IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
{
mTexture = NULL;
-
- for (int i = 0; i < 6; i++)
- {
- mFaceProxies[i] = NULL;
- }
}
TextureCubeMap::~TextureCubeMap()
{
for (int i = 0; i < 6; i++)
{
- delete mFaceProxies[i];
+ mFaceProxies[i].set(NULL);
}
if (mTexture)
@@ -1277,19 +1846,19 @@ void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, G
}
}
-void TextureCubeMap::subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+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(face)][level]))
+ if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
{
- commitRect(face, level, xoffset, yoffset, width, height);
+ commitRect(target, level, xoffset, yoffset, width, height);
}
}
-void TextureCubeMap::subImageCompressed(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
+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(face)][level]))
+ if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
{
- commitRect(face, level, xoffset, yoffset, width, height);
+ commitRect(target, level, xoffset, yoffset, width, height);
}
}
@@ -1328,6 +1897,15 @@ bool TextureCubeMap::isComplete() const
}
}
+ 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))
@@ -1368,7 +1946,7 @@ bool TextureCubeMap::isCompressed() const
IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
{
IDirect3DDevice9 *device = getDevice();
- D3DFORMAT format = selectFormat(mImageArray[0][0].format);
+ D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
IDirect3DCubeTexture9 *texture;
@@ -1424,7 +2002,7 @@ IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()
{
egl::Display *display = getDisplay();
IDirect3DDevice9 *device = getDevice();
- D3DFORMAT format = selectFormat(mImageArray[0][0].format);
+ D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
@@ -1546,7 +2124,7 @@ bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei
internalFormat, width);
// Purge all the levels and the texture.
- for (int i = 0; i < MAX_TEXTURE_LEVELS; i++)
+ for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
for (int f = 0; f < 6; f++)
{
@@ -1578,34 +2156,50 @@ bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei
return !textureOkay;
}
-void TextureCubeMap::copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
{
- unsigned int faceindex = faceIndex(face);
+ IDirect3DSurface9 *renderTarget = source->getRenderTarget();
- if (redefineTexture(level, internalFormat, width))
+ if (!renderTarget)
{
- convertToRenderTarget();
- pushTexture(mTexture, true);
+ ERR("Failed to retrieve the render target.");
+ return error(GL_OUT_OF_MEMORY);
}
- else
+
+ unsigned int faceindex = faceIndex(target);
+ bool redefined = redefineTexture(level, internalFormat, width);
+
+ if (!isRenderableFormat())
{
- needRenderTarget();
+ copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget);
}
+ else
+ {
+ if (redefined)
+ {
+ convertToRenderTarget();
+ pushTexture(mTexture, true);
+ }
+ else
+ {
+ needRenderTarget();
+ }
- ASSERT(width == height);
+ ASSERT(width == height);
- if (width > 0 && level < levelCount())
- {
- RECT sourceRect;
- sourceRect.left = x;
- sourceRect.right = x + width;
- sourceRect.top = y;
- sourceRect.bottom = y + height;
+ if (width > 0 && level < levelCount())
+ {
+ RECT sourceRect;
+ sourceRect.left = x;
+ sourceRect.right = x + width;
+ sourceRect.top = y;
+ sourceRect.bottom = y + height;
- IDirect3DSurface9 *dest = getCubeMapSurface(face, level);
+ IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
- getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
- dest->Release();
+ getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
+ dest->Release();
+ }
}
mImageArray[faceindex][level].width = width;
@@ -1644,37 +2238,55 @@ IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier
return (SUCCEEDED(hr)) ? surface : NULL;
}
-void TextureCubeMap::copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
{
- GLsizei size = mImageArray[faceIndex(face)][level].width;
+ GLsizei size = mImageArray[faceIndex(target)][level].width;
if (xoffset + width > size || yoffset + height > size)
{
return error(GL_INVALID_VALUE);
}
- if (redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width))
+ IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+
+ if (!renderTarget)
{
- convertToRenderTarget();
- pushTexture(mTexture, true);
+ ERR("Failed to retrieve the render target.");
+ return error(GL_OUT_OF_MEMORY);
}
- else
+
+ unsigned int faceindex = faceIndex(target);
+ bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width);
+
+ if (!isRenderableFormat())
{
- needRenderTarget();
+ copyNonRenderable(&mImageArray[faceindex][level], getFormat(), 0, 0, x, y, width, height, renderTarget);
}
-
- if (level < levelCount())
+ else
{
- RECT sourceRect;
- sourceRect.left = x;
- sourceRect.right = x + width;
- sourceRect.top = y;
- sourceRect.bottom = y + height;
+ if (redefined)
+ {
+ convertToRenderTarget();
+ pushTexture(mTexture, true);
+ }
+ else
+ {
+ needRenderTarget();
+ }
+
+ if (level < levelCount())
+ {
+ RECT sourceRect;
+ sourceRect.left = x;
+ sourceRect.right = x + width;
+ sourceRect.top = y;
+ sourceRect.bottom = y + height;
- IDirect3DSurface9 *dest = getCubeMapSurface(face, level);
+ IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
- getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
- dest->Release();
+ getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
+ dest->Release();
+ }
}
}
@@ -1724,23 +2336,52 @@ void TextureCubeMap::generateMipmaps()
}
}
- needRenderTarget();
-
- for (unsigned int f = 0; f < 6; f++)
+ if (isRenderable())
{
- for (unsigned int i = 1; i <= q; i++)
+ if (mTexture == NULL)
{
- IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1);
- IDirect3DSurface9 *lower = getCubeMapSurface(f, i);
+ return;
+ }
- if (upper != NULL && lower != NULL)
+ for (unsigned int f = 0; f < 6; f++)
+ {
+ for (unsigned int i = 1; i <= q; i++)
{
- getBlitter()->boxFilter(upper, lower);
+ IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1);
+ IDirect3DSurface9 *lower = getCubeMapSurface(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 (upper != NULL) upper->Release();
- if (lower != NULL) lower->Release();
+ 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;
}
}
@@ -1753,13 +2394,12 @@ Renderbuffer *TextureCubeMap::getColorbuffer(GLenum target)
unsigned int face = faceIndex(target);
- if (mFaceProxies[face] == NULL)
+ if (mFaceProxies[face].get() == NULL)
{
- mFaceProxies[face] = new Renderbuffer(id(), new TextureColorbufferProxy(this, target));
- mFaceProxies[face]->addRef();
+ mFaceProxies[face].set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
}
- return mFaceProxies[face];
+ return mFaceProxies[face].get();
}
IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
@@ -1767,7 +2407,12 @@ IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
ASSERT(IsCubemapTextureTarget(target));
needRenderTarget();
-
+
+ if (mTexture == NULL)
+ {
+ return NULL;
+ }
+
IDirect3DSurface9 *renderTarget = NULL;
mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex(target)), 0, &renderTarget);
@@ -1775,9 +2420,9 @@ IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
}
Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target)
- : Colorbuffer(NULL), mTexture(texture), mTarget(target)
+ : Colorbuffer(texture), mTexture(texture), mTarget(target)
{
- ASSERT(target == GL_TEXTURE_2D || IsCubemapTextureTarget(target));
+ ASSERT(IsTextureTarget(target));
}
void Texture::TextureColorbufferProxy::addRef() const
@@ -1814,4 +2459,9 @@ GLenum Texture::TextureColorbufferProxy::getFormat() const
return mTexture->getFormat();
}
+bool Texture::TextureColorbufferProxy::isFloatingPoint() const
+{
+ return mTexture->isFloatingPoint();
+}
+
}