Implement support for floating point textures.

Trac #12909 Implements GL_OES_texture_float, GL_OES_texture_half_float, GL_OES_texture_float_linear, and GL_OES_texture_half_float_linear when supported by the hardware. Signed-off-by: Nicolas Capens Signed-off-by: Daniel Koch Author: Shannon Woods <shannon.woods@transgaming.com> git-svn-id: https://angleproject.googlecode.com/svn/trunk@404 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 06098890
......@@ -487,4 +487,46 @@ bool Display::getCompressedTextureSupport()
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
}
bool Display::getFloatTextureSupport(bool *filtering)
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
if (SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
{
*filtering = true;
return true;
}
else
{
*filtering = false;
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
}
}
bool Display::getHalfFloatTextureSupport(bool *filtering)
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
if (SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)))
{
*filtering = true;
return true;
}
else
{
*filtering = false;
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
}
}
}
......@@ -62,6 +62,8 @@ class Display
virtual D3DCAPS9 getDeviceCaps();
virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
virtual bool getCompressedTextureSupport();
virtual bool getFloatTextureSupport(bool *filtering);
virtual bool getHalfFloatTextureSupport(bool *filtering);
private:
DISALLOW_COPY_AND_ASSIGN(Display);
......
......@@ -266,6 +266,8 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
mMaxSupportedSamples = max;
mSupportsCompressedTextures = display->getCompressedTextureSupport();
mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter);
mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter);
initExtensionString();
......@@ -2793,6 +2795,26 @@ bool Context::supportsCompressedTextures() const
return mSupportsCompressedTextures;
}
bool Context::supportsFloatTextures() const
{
return mSupportsFloatTextures;
}
bool Context::supportsFloatLinearFilter() const
{
return mSupportsFloatLinearFilter;
}
bool Context::supportsHalfFloatTextures() const
{
return mSupportsHalfFloatTextures;
}
bool Context::supportsHalfFloatLinearFilter() const
{
return mSupportsHalfFloatLinearFilter;
}
void Context::detachBuffer(GLuint buffer)
{
// [OpenGL ES 2.0.24] section 2.9 page 22:
......@@ -2994,6 +3016,26 @@ void Context::initExtensionString()
mExtensionString += "GL_EXT_texture_compression_dxt1 ";
}
if (supportsFloatTextures())
{
mExtensionString += "GL_OES_texture_float ";
}
if (supportsHalfFloatTextures())
{
mExtensionString += "GL_OES_texture_half_float ";
}
if (supportsFloatLinearFilter())
{
mExtensionString += "GL_OES_texture_float_linear ";
}
if (supportsHalfFloatLinearFilter())
{
mExtensionString += "GL_OES_texture_half_float_linear ";
}
if (getMaxSupportedSamples() != 0)
{
mExtensionString += "GL_ANGLE_framebuffer_multisample ";
......
......@@ -378,6 +378,10 @@ class Context
int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
const char *getExtensionString() const;
bool supportsCompressedTextures() const;
bool supportsFloatTextures() const;
bool supportsFloatLinearFilter() const;
bool supportsHalfFloatTextures() const;
bool supportsHalfFloatLinearFilter() const;
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
......@@ -444,6 +448,10 @@ class Context
std::map<D3DFORMAT, bool *> mMultiSampleSupport;
GLsizei mMaxSupportedSamples;
bool mSupportsCompressedTextures;
bool mSupportsFloatTextures;
bool mSupportsFloatLinearFilter;
bool mSupportsHalfFloatTextures;
bool mSupportsHalfFloatLinearFilter;
// state caching flags
bool mClearStateDirty;
......
......@@ -45,6 +45,7 @@ Texture::Texture(GLuint id) : RefCountObject(id)
mDirtyMetaData = true;
mDirty = true;
mIsRenderable = false;
mType = GL_UNSIGNED_BYTE;
mBaseTexture = NULL;
}
......@@ -174,25 +175,33 @@ GLuint Texture::getHeight() const
return mHeight;
}
bool Texture::isFloatingPoint() const
{
return (mType == GL_FLOAT || mType == GL_HALF_FLOAT_OES);
}
// 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 if (type == GL_FLOAT)
{
return D3DFMT_A32B32G32R32F;
}
else if (type == GL_HALF_FLOAT_OES)
{
return D3DFMT_A16B16G16R16F;
}
else
{
return D3DFMT_A8R8G8B8;
}
}
int Texture::imagePitch(const Image &img) const
{
return img.width * 4;
}
// 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.
void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
......@@ -200,60 +209,100 @@ void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei
{
GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment);
switch (type)
{
case GL_UNSIGNED_BYTE:
switch (format)
{
case GL_ALPHA:
loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_LUMINANCE:
loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_LUMINANCE_ALPHA:
loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_RGB:
switch (type)
{
case GL_UNSIGNED_BYTE:
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;
default: UNREACHABLE();
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
switch (format)
{
case GL_RGBA:
loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
default: UNREACHABLE();
}
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
switch (format)
{
case GL_RGBA:
loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
default: UNREACHABLE();
}
break;
case GL_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,6 +330,46 @@ 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
{
......@@ -301,6 +390,46 @@ void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei 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] = 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
{
......@@ -321,6 +450,46 @@ void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei
}
}
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];
dest[4 * x + 1] = source[2*x+0];
dest[4 * x + 2] = source[2*x+0];
dest[4 * x + 3] = source[2*x+1];
}
}
}
void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const
{
......@@ -362,6 +531,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 +633,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 +675,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 +702,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,7 +725,7 @@ 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)
{
......@@ -511,7 +748,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)
{
......@@ -716,7 +953,7 @@ GLenum Texture2D::getFormat() const
//
// Returns true if the existing texture was unsuitable 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 +962,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)
{
......@@ -756,6 +995,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 +1003,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,7 +1068,7 @@ 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))
if (redefineTexture(level, internalFormat, width, height, mType))
{
convertToRenderTarget();
pushTexture(mTexture, true);
......@@ -865,7 +1105,7 @@ void Texture2D::copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x,
return error(GL_INVALID_VALUE);
}
if (redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height))
if (redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType))
{
convertToRenderTarget();
pushTexture(mTexture, true);
......@@ -919,6 +1159,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 +1217,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 +1268,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);
......@@ -1328,6 +1578,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 +1627,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 +1683,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);
......
......@@ -58,6 +58,7 @@ class Texture : public RefCountObject
virtual GLenum getFormat() const = 0;
virtual bool isComplete() const = 0;
virtual bool isCompressed() const = 0;
bool isFloatingPoint() const;
IDirect3DBaseTexture9 *getTexture();
virtual Renderbuffer *getColorbuffer(GLenum target) = 0;
......@@ -106,8 +107,7 @@ class Texture : public RefCountObject
IDirect3DSurface9 *surface;
};
static D3DFORMAT selectFormat(GLenum format);
int imagePitch(const Image& img) const;
static D3DFORMAT selectFormat(GLenum format, GLenum type);
void setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
......@@ -140,6 +140,7 @@ class Texture : public RefCountObject
GLenum mMagFilter;
GLenum mWrapS;
GLenum mWrapT;
GLenum mType;
private:
DISALLOW_COPY_AND_ASSIGN(Texture);
......@@ -149,30 +150,51 @@ class Texture : public RefCountObject
void loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
void createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img);
IDirect3DBaseTexture9 *mBaseTexture; // This is a weak pointer. The derived class is assumed to own a strong pointer.
bool mDirty;
bool mDirtyMetaData;
bool mIsRenderable;
void createSurface(GLsizei width, GLsizei height, GLenum format, Image *img);
};
class Texture2D : public Texture
......@@ -209,7 +231,7 @@ class Texture2D : public Texture
virtual bool dirtyImageData() const;
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height);
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type);
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
Image mImageArray[MAX_TEXTURE_LEVELS];
......
......@@ -1068,6 +1068,11 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_OPERATION);
}
if (texture->isFloatingPoint())
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(level, internalformat, x, y, width, height, source);
}
else if (gl::IsCubemapTextureTarget(target))
......@@ -1084,6 +1089,11 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_OPERATION);
}
if (texture->isFloatingPoint())
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(target, level, internalformat, x, y, width, height, source);
}
else
......@@ -1156,6 +1166,11 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
return error(GL_INVALID_OPERATION);
}
if (texture->isFloatingPoint())
{
return error(GL_INVALID_OPERATION);
}
texture->copySubImage(level, xoffset, yoffset, x, y, width, height, source);
}
else if (gl::IsCubemapTextureTarget(target))
......@@ -1172,6 +1187,11 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
return error(GL_INVALID_OPERATION);
}
if (texture->isFloatingPoint())
{
return error(GL_INVALID_OPERATION);
}
texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source);
}
else
......@@ -4256,6 +4276,8 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
switch (type)
{
case GL_UNSIGNED_BYTE:
case GL_FLOAT:
case GL_HALF_FLOAT_OES:
break;
default:
return error(GL_INVALID_ENUM);
......@@ -4266,6 +4288,8 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
{
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_SHORT_5_6_5:
case GL_FLOAT:
case GL_HALF_FLOAT_OES:
break;
default:
return error(GL_INVALID_ENUM);
......@@ -4277,6 +4301,8 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_FLOAT:
case GL_HALF_FLOAT_OES:
break;
default:
return error(GL_INVALID_ENUM);
......@@ -4320,6 +4346,21 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
}
}
if (type == GL_FLOAT)
{
if (!context->supportsFloatTextures())
{
return error(GL_INVALID_ENUM);
}
}
else if (type == GL_HALF_FLOAT_OES)
{
if (!context->supportsHalfFloatTextures())
{
return error(GL_INVALID_ENUM);
}
}
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
......@@ -4486,6 +4527,21 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
if (context)
{
if (format == GL_FLOAT)
{
if (!context->supportsFloatTextures())
{
return error(GL_INVALID_ENUM);
}
}
else if (format == GL_HALF_FLOAT_OES)
{
if (!context->supportsHalfFloatTextures())
{
return error(GL_INVALID_ENUM);
}
}
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
......@@ -4500,6 +4556,11 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
return error(GL_INVALID_OPERATION);
}
if (format != texture->getFormat())
{
return error(GL_INVALID_OPERATION);
}
texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
}
else if (gl::IsCubemapTextureTarget(target))
......@@ -4516,6 +4577,11 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
return error(GL_INVALID_OPERATION);
}
if (format != texture->getFormat())
{
return error(GL_INVALID_OPERATION);
}
texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
}
else
......
......@@ -247,6 +247,28 @@ int ComputePixelSize(GLenum format, GLenum type)
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_5_6_5:
return sizeof(unsigned short);
case GL_FLOAT:
switch (format)
{
case GL_ALPHA: return sizeof(float);
case GL_LUMINANCE: return sizeof(float);
case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
case GL_RGB: return sizeof(float) * 3;
case GL_RGBA: return sizeof(float) * 4;
default: UNREACHABLE();
}
break;
case GL_HALF_FLOAT_OES:
switch (format)
{
case GL_ALPHA: return sizeof(unsigned short);
case GL_LUMINANCE: return sizeof(unsigned short);
case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
case GL_RGB: return sizeof(unsigned short) * 3;
case GL_RGBA: return sizeof(unsigned short) * 4;
default: UNREACHABLE();
}
break;
default: UNREACHABLE();
}
......@@ -283,6 +305,21 @@ bool CheckTextureFormatType(GLenum format, GLenum type)
return false;
}
case GL_FLOAT:
case GL_HALF_FLOAT_OES:
switch (format)
{
case GL_RGBA:
case GL_RGB:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
return true;
default:
return false;
}
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
return (format == GL_RGBA);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment