diff options
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp | 1054 |
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(); +} + } |