Implemented glTexStorage2DEXT.

TRAC #18730 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@857 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent d30bd0a7
...@@ -339,6 +339,9 @@ typedef void* GLeglImageOES; ...@@ -339,6 +339,9 @@ typedef void* GLeglImageOES;
/* GL_EXT_texture_storage */ /* GL_EXT_texture_storage */
#ifndef GL_EXT_texture_storage #ifndef GL_EXT_texture_storage
#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F #define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
#define GL_ALPHA8_EXT 0x803C
#define GL_LUMINANCE8_EXT 0x8040
#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
#endif #endif
/*------------------------------------------------------------------------* /*------------------------------------------------------------------------*
......
...@@ -715,7 +715,10 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint ...@@ -715,7 +715,10 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
return error(EGL_BAD_MATCH, EGL_FALSE); return error(EGL_BAD_MATCH, EGL_FALSE);
} }
glBindTexImage(eglSurface); if (!glBindTexImage(eglSurface))
{
return error(EGL_BAD_MATCH, EGL_FALSE);
}
return success(EGL_TRUE); return success(EGL_TRUE);
} }
......
...@@ -615,7 +615,7 @@ void glDestroyContext(gl::Context *context); ...@@ -615,7 +615,7 @@ void glDestroyContext(gl::Context *context);
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
gl::Context *glGetCurrentContext(); gl::Context *glGetCurrentContext();
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
void __stdcall glBindTexImage(egl::Surface *surface); bool __stdcall glBindTexImage(egl::Surface *surface);
} }
#endif // INCLUDE_CONTEXT_H_ #endif // INCLUDE_CONTEXT_H_
...@@ -42,12 +42,13 @@ Image::~Image() ...@@ -42,12 +42,13 @@ Image::~Image()
} }
} }
bool Image::redefine(GLenum format, GLsizei width, GLsizei height, GLenum type) bool Image::redefine(GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRelease)
{ {
if (mWidth != width || if (mWidth != width ||
mHeight != height || mHeight != height ||
mFormat != format || mFormat != format ||
mType != type) mType != type ||
forceRelease)
{ {
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
...@@ -1637,7 +1638,7 @@ void Texture2D::redefineImage(GLint level, GLenum format, GLsizei width, GLsizei ...@@ -1637,7 +1638,7 @@ void Texture2D::redefineImage(GLint level, GLenum format, GLsizei width, GLsizei
{ {
releaseTexImage(); releaseTexImage();
bool redefined = mImageArray[level].redefine(format, width, height, type); bool redefined = mImageArray[level].redefine(format, width, height, type, false);
if (mTexture && redefined) if (mTexture && redefined)
{ {
...@@ -1678,7 +1679,7 @@ void Texture2D::bindTexImage(egl::Surface *surface) ...@@ -1678,7 +1679,7 @@ void Texture2D::bindTexImage(egl::Surface *surface)
return; return;
} }
mImageArray[0].redefine(format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE); mImageArray[0].redefine(format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true);
delete mTexture; delete mTexture;
mTexture = new TextureStorage2D(surface->getOffscreenTexture()); mTexture = new TextureStorage2D(surface->getOffscreenTexture());
...@@ -1703,7 +1704,7 @@ void Texture2D::releaseTexImage() ...@@ -1703,7 +1704,7 @@ void Texture2D::releaseTexImage()
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{ {
mImageArray[i].redefine(GL_RGBA, 0, 0, GL_UNSIGNED_BYTE); mImageArray[i].redefine(GL_RGBA, 0, 0, GL_UNSIGNED_BYTE, true);
} }
} }
} }
...@@ -1857,6 +1858,28 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo ...@@ -1857,6 +1858,28 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
renderTarget->Release(); renderTarget->Release();
} }
void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
GLenum format = gl::ExtractFormat(internalformat);
GLenum type = gl::ExtractType(internalformat);
delete mTexture;
mTexture = new TextureStorage2D(levels, mImageArray[0].getD3DFormat(), width, height, false);
mImmutable = true;
for (int level = 0; level < levels; level++)
{
mImageArray[level].redefine(format, width, height, type, true);
width = std::max(1, width >> 1);
height = std::max(1, height >> 1);
}
for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
mImageArray[level].redefine(GL_NONE, 0, 0, GL_UNSIGNED_BYTE, true);
}
}
// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. // Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool Texture2D::isComplete() const bool Texture2D::isComplete() const
{ {
...@@ -2507,7 +2530,7 @@ unsigned int TextureCubeMap::faceIndex(GLenum face) ...@@ -2507,7 +2530,7 @@ unsigned int TextureCubeMap::faceIndex(GLenum face)
void TextureCubeMap::redefineImage(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type) void TextureCubeMap::redefineImage(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
{ {
bool redefined = mImageArray[face][level].redefine(format, width, height, type); bool redefined = mImageArray[face][level].redefine(format, width, height, type, false);
if (mTexture && redefined) if (mTexture && redefined)
{ {
...@@ -2634,6 +2657,33 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi ...@@ -2634,6 +2657,33 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi
renderTarget->Release(); renderTarget->Release();
} }
void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
{
GLenum format = gl::ExtractFormat(internalformat);
GLenum type = gl::ExtractType(internalformat);
delete mTexture;
mTexture = new TextureStorageCubeMap(levels, mImageArray[0][0].getD3DFormat(), size, false);
mImmutable = true;
for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
for (int face = 0; face < 6; face++)
{
mImageArray[face][level].redefine(format, size, size, type, true);
size = std::max(1, size >> 1);
}
}
for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
for (int face = 0; face < 6; face++)
{
mImageArray[face][level].redefine(GL_NONE, 0, 0, GL_UNSIGNED_BYTE, true);
}
}
}
bool TextureCubeMap::isCubeComplete() const bool TextureCubeMap::isCubeComplete() const
{ {
if (mImageArray[0][0].getWidth() == 0) if (mImageArray[0][0].getWidth() == 0)
......
...@@ -49,7 +49,7 @@ class Image ...@@ -49,7 +49,7 @@ class Image
Image(); Image();
~Image(); ~Image();
bool redefine(GLenum format, GLsizei width, GLsizei height, GLenum type); bool redefine(GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRelease);
void markDirty() {mDirty = true;} void markDirty() {mDirty = true;}
void markClean() {mDirty = false;} void markClean() {mDirty = false;}
...@@ -279,6 +279,7 @@ class Texture2D : public Texture ...@@ -279,6 +279,7 @@ class Texture2D : public Texture
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
virtual bool isComplete() const; virtual bool isComplete() const;
virtual bool isCompressed() const; virtual bool isCompressed() const;
...@@ -357,6 +358,7 @@ class TextureCubeMap : public Texture ...@@ -357,6 +358,7 @@ class TextureCubeMap : public Texture
void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void storage(GLsizei levels, GLenum internalformat, GLsizei size);
virtual bool isComplete() const; virtual bool isComplete() const;
virtual bool isCompressed() const; virtual bool isCompressed() const;
......
...@@ -860,6 +860,11 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna ...@@ -860,6 +860,11 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
texture->setCompressedImage(level, internalformat, width, height, imageSize, data); texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
} }
else else
...@@ -871,6 +876,11 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna ...@@ -871,6 +876,11 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
switch (target) switch (target)
{ {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
...@@ -1175,6 +1185,11 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma ...@@ -1175,6 +1185,11 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(level, internalformat, x, y, width, height, framebuffer); texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
} }
else if (gl::IsCubemapTextureTarget(target)) else if (gl::IsCubemapTextureTarget(target))
...@@ -1186,6 +1201,11 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma ...@@ -1186,6 +1201,11 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
} }
else UNREACHABLE(); else UNREACHABLE();
...@@ -4700,6 +4720,11 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL ...@@ -4700,6 +4720,11 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels); texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
} }
else else
...@@ -4711,6 +4736,11 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL ...@@ -4711,6 +4736,11 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
switch (target) switch (target)
{ {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
...@@ -4818,6 +4848,94 @@ void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params ...@@ -4818,6 +4848,94 @@ void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params
glTexParameteri(target, pname, *params); glTexParameteri(target, pname, *params);
} }
void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
target, levels, internalformat, width, height);
try
{
if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
{
return error(GL_INVALID_ENUM);
}
if (width < 1 || height < 1 || levels < 1)
{
return error(GL_INVALID_VALUE);
}
if (target == GL_TEXTURE_CUBE_MAP && width != height)
{
return error(GL_INVALID_VALUE);
}
if (levels > gl::log2(std::max(width, height)) + 1)
{
return error(GL_INVALID_OPERATION);
}
GLenum format = gl::ExtractFormat(internalformat);
GLenum type = gl::ExtractType(internalformat);
if (format == GL_NONE || type == GL_NONE)
{
return error(GL_INVALID_ENUM);
}
gl::Context *context = gl::getNonLostContext();
if (context)
{
if (levels != 1 && !context->supportsNonPower2Texture())
{
if (!gl::isPow2(width) || !gl::isPow2(height))
{
return error(GL_INVALID_OPERATION);
}
}
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
if (!texture || texture->id() == 0)
{
return error(GL_INVALID_OPERATION);
}
if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
texture->storage(levels, internalformat, width, height);
}
else if (target == GL_TEXTURE_CUBE_MAP)
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
if (!texture || texture->id() == 0)
{
return error(GL_INVALID_OPERATION);
}
if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
texture->storage(levels, internalformat, width);
}
else UNREACHABLE();
}
}
catch(std::bad_alloc&)
{
return error(GL_OUT_OF_MEMORY);
}
}
void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLenum format, GLenum type, const GLvoid* pixels) GLenum format, GLenum type, const GLvoid* pixels)
{ {
...@@ -5851,7 +5969,7 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char * ...@@ -5851,7 +5969,7 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *
// Non-public functions used by EGL // Non-public functions used by EGL
void __stdcall glBindTexImage(egl::Surface *surface) bool __stdcall glBindTexImage(egl::Surface *surface)
{ {
EVENT("(egl::Surface* surface = 0x%0.8p)", EVENT("(egl::Surface* surface = 0x%0.8p)",
surface); surface);
...@@ -5864,6 +5982,11 @@ void __stdcall glBindTexImage(egl::Surface *surface) ...@@ -5864,6 +5982,11 @@ void __stdcall glBindTexImage(egl::Surface *surface)
{ {
gl::Texture2D *textureObject = context->getTexture2D(); gl::Texture2D *textureObject = context->getTexture2D();
if (textureObject->isImmutable())
{
return false;
}
if (textureObject) if (textureObject)
{ {
textureObject->bindTexImage(surface); textureObject->bindTexImage(surface);
...@@ -5872,8 +5995,10 @@ void __stdcall glBindTexImage(egl::Surface *surface) ...@@ -5872,8 +5995,10 @@ void __stdcall glBindTexImage(egl::Surface *surface)
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
return error(GL_OUT_OF_MEMORY); return error(GL_OUT_OF_MEMORY, false);
} }
return true;
} }
} }
...@@ -374,6 +374,38 @@ bool CheckTextureFormatType(GLenum format, GLenum type) ...@@ -374,6 +374,38 @@ bool CheckTextureFormatType(GLenum format, GLenum type)
} }
} }
GLenum ExtractFormat(GLenum internalformat)
{
switch (internalformat)
{
case GL_RGB565: return GL_RGB;
case GL_RGBA4: return GL_RGBA;
case GL_RGB5_A1: return GL_RGBA;
case GL_RGB8_OES: return GL_RGB;
case GL_RGBA8_OES: return GL_RGBA;
case GL_LUMINANCE8_ALPHA8_EXT: return GL_LUMINANCE_ALPHA;
case GL_LUMINANCE8_EXT: return GL_LUMINANCE;
case GL_ALPHA8_EXT: return GL_ALPHA;
default: return GL_NONE; // Unsupported
}
}
GLenum ExtractType(GLenum internalformat)
{
switch (internalformat)
{
case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
case GL_RGB8_OES: return GL_UNSIGNED_BYTE;
case GL_RGBA8_OES: return GL_UNSIGNED_BYTE;
case GL_LUMINANCE8_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
case GL_LUMINANCE8_EXT: return GL_UNSIGNED_BYTE;
case GL_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
default: return GL_NONE; // Unsupported
}
}
bool IsColorRenderable(GLenum internalformat) bool IsColorRenderable(GLenum internalformat)
{ {
switch (internalformat) switch (internalformat)
......
...@@ -38,6 +38,8 @@ bool IsCompressed(GLenum format); ...@@ -38,6 +38,8 @@ bool IsCompressed(GLenum format);
bool IsCubemapTextureTarget(GLenum target); bool IsCubemapTextureTarget(GLenum target);
bool IsTextureTarget(GLenum target); bool IsTextureTarget(GLenum target);
bool CheckTextureFormatType(GLenum format, GLenum type); bool CheckTextureFormatType(GLenum format, GLenum type);
GLenum ExtractFormat(GLenum internalformat);
GLenum ExtractType(GLenum internalformat);
bool IsColorRenderable(GLenum internalformat); bool IsColorRenderable(GLenum internalformat);
bool IsDepthRenderable(GLenum internalformat); bool IsDepthRenderable(GLenum internalformat);
......
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