Commit f47bebc4 by Brandon Jones

Refactored Texture2D, separated out D3D logic

BUG=angle:688 Change-Id: I93c2ff0b125278234d61324844b79cc58135d4d8 Reviewed-on: https://chromium-review.googlesource.com/207675Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org> Tested-by: 's avatarBrandon Jones <bajones@chromium.org>
parent 53a94a82
...@@ -374,6 +374,7 @@ if (is_win) { ...@@ -374,6 +374,7 @@ if (is_win) {
"src/libGLESv2/renderer/Renderer.h", "src/libGLESv2/renderer/Renderer.h",
"src/libGLESv2/renderer/ShaderExecutable.h", "src/libGLESv2/renderer/ShaderExecutable.h",
"src/libGLESv2/renderer/SwapChain.h", "src/libGLESv2/renderer/SwapChain.h",
"src/libGLESv2/renderer/TextureImpl.h",
"src/libGLESv2/renderer/VertexArrayImpl.h", "src/libGLESv2/renderer/VertexArrayImpl.h",
"src/libGLESv2/renderer/copyimage.cpp", "src/libGLESv2/renderer/copyimage.cpp",
"src/libGLESv2/renderer/copyimage.h", "src/libGLESv2/renderer/copyimage.h",
...@@ -421,6 +422,8 @@ if (is_win) { ...@@ -421,6 +422,8 @@ if (is_win) {
"src/libGLESv2/renderer/d3d/IndexBuffer.h", "src/libGLESv2/renderer/d3d/IndexBuffer.h",
"src/libGLESv2/renderer/d3d/IndexDataManager.cpp", "src/libGLESv2/renderer/d3d/IndexDataManager.cpp",
"src/libGLESv2/renderer/d3d/IndexDataManager.h", "src/libGLESv2/renderer/d3d/IndexDataManager.h",
"src/libGLESv2/renderer/d3d/TextureD3D.cpp",
"src/libGLESv2/renderer/d3d/TextureD3D.h",
"src/libGLESv2/renderer/d3d/TextureStorage.cpp", "src/libGLESv2/renderer/d3d/TextureStorage.cpp",
"src/libGLESv2/renderer/d3d/TextureStorage.h", "src/libGLESv2/renderer/d3d/TextureStorage.h",
"src/libGLESv2/renderer/d3d/VertexBuffer.cpp", "src/libGLESv2/renderer/d3d/VertexBuffer.cpp",
......
...@@ -158,6 +158,7 @@ ...@@ -158,6 +158,7 @@
<ClInclude Include="..\..\src\libGLESv2\Buffer.h"/> <ClInclude Include="..\..\src\libGLESv2\Buffer.h"/>
<ClInclude Include="..\..\src\libGLESv2\State.h"/> <ClInclude Include="..\..\src\libGLESv2\State.h"/>
<ClInclude Include="..\..\src\libGLESv2\validationES.h"/> <ClInclude Include="..\..\src\libGLESv2\validationES.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\TextureImpl.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\Renderer.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\Renderer.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\ShaderExecutable.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\ShaderExecutable.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\loadimage.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\loadimage.h"/>
...@@ -177,6 +178,7 @@ ...@@ -177,6 +178,7 @@
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\IndexBuffer.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\d3d\IndexBuffer.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\HLSLCompiler.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\d3d\HLSLCompiler.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\ImageD3D.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\d3d\ImageD3D.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\TextureD3D.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\TextureStorage.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\d3d\TextureStorage.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\IndexDataManager.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\d3d\IndexDataManager.h"/>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\VertexBuffer.h"/> <ClInclude Include="..\..\src\libGLESv2\renderer\d3d\VertexBuffer.h"/>
...@@ -342,10 +344,11 @@ ...@@ -342,10 +344,11 @@
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\HLSLCompiler.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\HLSLCompiler.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\BufferD3D.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\BufferD3D.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\IndexBuffer.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\IndexBuffer.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\TextureD3D.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\VertexDataManager.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\VertexDataManager.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\IndexDataManager.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\ImageD3D.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\ImageD3D.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\TextureStorage.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\TextureStorage.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\IndexDataManager.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\VertexBuffer.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\VertexBuffer.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\d3d11\Renderer11.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\d3d11\Renderer11.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\d3d11\InputLayoutCache.cpp"/> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\d3d11\InputLayoutCache.cpp"/>
......
...@@ -264,6 +264,9 @@ ...@@ -264,6 +264,9 @@
<ClCompile Include="..\..\src\libGLESv2\renderer\copyimage.cpp"> <ClCompile Include="..\..\src\libGLESv2\renderer\copyimage.cpp">
<Filter>src\libGLESv2\renderer</Filter> <Filter>src\libGLESv2\renderer</Filter>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\libGLESv2\renderer\TextureImpl.h">
<Filter>src\libGLESv2\renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\libGLESv2\renderer\Renderer.h"> <ClInclude Include="..\..\src\libGLESv2\renderer\Renderer.h">
<Filter>src\libGLESv2\renderer</Filter> <Filter>src\libGLESv2\renderer</Filter>
</ClInclude> </ClInclude>
...@@ -351,12 +354,15 @@ ...@@ -351,12 +354,15 @@
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\IndexBuffer.cpp"> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\IndexBuffer.cpp">
<Filter>src\libGLESv2\renderer\d3d</Filter> <Filter>src\libGLESv2\renderer\d3d</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\VertexDataManager.cpp"> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\TextureD3D.cpp">
<Filter>src\libGLESv2\renderer\d3d</Filter> <Filter>src\libGLESv2\renderer\d3d</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\IndexDataManager.cpp"> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\VertexDataManager.cpp">
<Filter>src\libGLESv2\renderer\d3d</Filter> <Filter>src\libGLESv2\renderer\d3d</Filter>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\TextureD3D.h">
<Filter>src\libGLESv2\renderer\d3d</Filter>
</ClInclude>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\TextureStorage.h"> <ClInclude Include="..\..\src\libGLESv2\renderer\d3d\TextureStorage.h">
<Filter>src\libGLESv2\renderer\d3d</Filter> <Filter>src\libGLESv2\renderer\d3d</Filter>
</ClInclude> </ClInclude>
...@@ -375,6 +381,9 @@ ...@@ -375,6 +381,9 @@
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d\BufferD3D.h"> <ClInclude Include="..\..\src\libGLESv2\renderer\d3d\BufferD3D.h">
<Filter>src\libGLESv2\renderer\d3d</Filter> <Filter>src\libGLESv2\renderer\d3d</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\IndexDataManager.cpp">
<Filter>src\libGLESv2\renderer\d3d</Filter>
</ClCompile>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d\VertexBuffer.cpp"> <ClCompile Include="..\..\src\libGLESv2\renderer\d3d\VertexBuffer.cpp">
<Filter>src\libGLESv2\renderer\d3d</Filter> <Filter>src\libGLESv2\renderer\d3d</Filter>
</ClCompile> </ClCompile>
......
...@@ -68,7 +68,7 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere ...@@ -68,7 +68,7 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
// In order that access to these initial textures not be lost, they are treated as texture // In order that access to these initial textures not be lost, they are treated as texture
// objects all of whose names are 0. // objects all of whose names are 0.
mTexture2DZero.set(new Texture2D(mRenderer, 0)); mTexture2DZero.set(new Texture2D(mRenderer->createTexture2D(), 0));
mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0)); mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0));
mTexture3DZero.set(new Texture3D(mRenderer, 0)); mTexture3DZero.set(new Texture3D(mRenderer, 0));
mTexture2DArrayZero.set(new Texture2DArray(mRenderer, 0)); mTexture2DArrayZero.set(new Texture2DArray(mRenderer, 0));
...@@ -2151,7 +2151,7 @@ Texture *Context::getIncompleteTexture(TextureType type) ...@@ -2151,7 +2151,7 @@ Texture *Context::getIncompleteTexture(TextureType type)
case TEXTURE_2D: case TEXTURE_2D:
{ {
Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture2D(), Texture::INCOMPLETE_TEXTURE_ID);
incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
t = incomplete2d; t = incomplete2d;
} }
......
...@@ -377,7 +377,7 @@ void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) ...@@ -377,7 +377,7 @@ void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
if (type == TEXTURE_2D) if (type == TEXTURE_2D)
{ {
textureObject = new Texture2D(mRenderer, texture); textureObject = new Texture2D(mRenderer->createTexture2D(), texture);
} }
else if (type == TEXTURE_CUBE) else if (type == TEXTURE_CUBE)
{ {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "libGLESv2/Buffer.h" #include "libGLESv2/Buffer.h"
#include "libGLESv2/renderer/BufferImpl.h" #include "libGLESv2/renderer/BufferImpl.h"
#include "libGLESv2/renderer/RenderTarget.h" #include "libGLESv2/renderer/RenderTarget.h"
#include "libGLESv2/renderer/TextureImpl.h"
namespace gl namespace gl
{ {
...@@ -50,17 +51,12 @@ bool IsRenderTargetUsage(GLenum usage) ...@@ -50,17 +51,12 @@ bool IsRenderTargetUsage(GLenum usage)
return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
} }
Texture::Texture(rx::Renderer *renderer, GLuint id, GLenum target) : RefCountObject(id) Texture::Texture(GLuint id, GLenum target)
: RefCountObject(id),
mUsage(GL_NONE),
mImmutable(false),
mTarget(target)
{ {
mRenderer = renderer;
mUsage = GL_NONE;
mDirtyImages = true;
mImmutable = false;
mTarget = target;
} }
Texture::~Texture() Texture::~Texture()
...@@ -119,7 +115,66 @@ GLenum Texture::getBaseLevelInternalFormat() const ...@@ -119,7 +115,66 @@ GLenum Texture::getBaseLevelInternalFormat() const
return (baseImage ? baseImage->getInternalFormat() : GL_NONE); return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
} }
void Texture::setImage(const PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image) unsigned int Texture::getTextureSerial()
{
rx::TextureStorageInterface *texture = getNativeTexture();
return texture ? texture->getTextureSerial() : 0;
}
bool Texture::isImmutable() const
{
return mImmutable;
}
int Texture::immutableLevelCount()
{
return (mImmutable ? getNativeTexture()->getStorageInstance()->getLevelCount() : 0);
}
int Texture::mipLevels() const
{
return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
}
TextureWithRenderer::TextureWithRenderer(rx::Renderer *renderer, GLuint id, GLenum target)
: Texture(id, target),
mRenderer(renderer),
mDirtyImages(true)
{
}
TextureWithRenderer::~TextureWithRenderer()
{
}
// TODO: This is only used by the D3D backends and FramebufferAttachment. Once
// FramebufferAttachment has been refactored this function should be pushed
// down to TextureD3D.
rx::TextureStorageInterface *TextureWithRenderer::getNativeTexture()
{
// ensure the underlying texture is created
initializeStorage(false);
rx::TextureStorageInterface *storage = getBaseLevelStorage();
if (storage)
{
updateStorage();
}
return storage;
}
bool TextureWithRenderer::hasDirtyImages() const
{
return mDirtyImages;
}
void TextureWithRenderer::resetDirty()
{
mDirtyImages = false;
}
void TextureWithRenderer::setImage(const PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image)
{ {
// No-op // No-op
if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
...@@ -149,12 +204,12 @@ void Texture::setImage(const PixelUnpackState &unpack, GLenum type, const void * ...@@ -149,12 +204,12 @@ void Texture::setImage(const PixelUnpackState &unpack, GLenum type, const void *
} }
} }
bool Texture::isFastUnpackable(const PixelUnpackState &unpack, GLenum sizedInternalFormat) bool TextureWithRenderer::isFastUnpackable(const PixelUnpackState &unpack, GLenum sizedInternalFormat)
{ {
return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
} }
bool Texture::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea, bool TextureWithRenderer::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea,
GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget) GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget)
{ {
if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
...@@ -171,7 +226,7 @@ bool Texture::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixel ...@@ -171,7 +226,7 @@ bool Texture::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixel
return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
} }
void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image) void TextureWithRenderer::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image)
{ {
if (pixels != NULL) if (pixels != NULL)
{ {
...@@ -180,7 +235,7 @@ void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Imag ...@@ -180,7 +235,7 @@ void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Imag
} }
} }
bool Texture::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, bool TextureWithRenderer::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels, rx::Image *image) GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels, rx::Image *image)
{ {
const void *pixelData = pixels; const void *pixelData = pixels;
...@@ -205,7 +260,7 @@ bool Texture::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt ...@@ -205,7 +260,7 @@ bool Texture::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt
return true; return true;
} }
bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, bool TextureWithRenderer::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image) GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image)
{ {
if (pixels != NULL) if (pixels != NULL)
...@@ -217,47 +272,7 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GL ...@@ -217,47 +272,7 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GL
return true; return true;
} }
rx::TextureStorageInterface *Texture::getNativeTexture() GLint TextureWithRenderer::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
{
// ensure the underlying texture is created
initializeStorage(false);
rx::TextureStorageInterface *storage = getBaseLevelStorage();
if (storage)
{
updateStorage();
}
return storage;
}
bool Texture::hasDirtyImages() const
{
return mDirtyImages;
}
void Texture::resetDirty()
{
mDirtyImages = false;
}
unsigned int Texture::getTextureSerial()
{
rx::TextureStorageInterface *texture = getNativeTexture();
return texture ? texture->getTextureSerial() : 0;
}
bool Texture::isImmutable() const
{
return mImmutable;
}
int Texture::immutableLevelCount()
{
return (mImmutable ? getNativeTexture()->getStorageInstance()->getLevelCount() : 0);
}
GLint Texture::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
{ {
// TODO(geofflang): use context's extensions // TODO(geofflang): use context's extensions
if ((isPow2(width) && isPow2(height) && isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT) if ((isPow2(width) && isPow2(height) && isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT)
...@@ -272,43 +287,49 @@ GLint Texture::creationLevels(GLsizei width, GLsizei height, GLsizei depth) cons ...@@ -272,43 +287,49 @@ GLint Texture::creationLevels(GLsizei width, GLsizei height, GLsizei depth) cons
} }
} }
int Texture::mipLevels() const Texture2D::Texture2D(rx::Texture2DImpl *impl, GLuint id)
: Texture(id, GL_TEXTURE_2D),
mTexture(impl)
{ {
return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
}
Texture2D::Texture2D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_2D)
{
mTexStorage = NULL;
mSurface = NULL; mSurface = NULL;
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
mImageArray[i] = renderer->createImage();
}
} }
Texture2D::~Texture2D() Texture2D::~Texture2D()
{ {
delete mTexStorage; SafeDelete(mTexture);
mTexStorage = NULL;
if (mSurface) if (mSurface)
{ {
mSurface->setBoundTexture(NULL); mSurface->setBoundTexture(NULL);
mSurface = NULL; mSurface = NULL;
} }
}
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) rx::TextureStorageInterface *Texture2D::getNativeTexture()
{ {
delete mImageArray[i]; return mTexture->getNativeTexture();
} }
void Texture2D::setUsage(GLenum usage)
{
mUsage = usage;
mTexture->setUsage(usage);
}
bool Texture2D::hasDirtyImages() const
{
return mTexture->hasDirtyImages();
}
void Texture2D::resetDirty()
{
mTexture->resetDirty();
} }
GLsizei Texture2D::getWidth(GLint level) const GLsizei Texture2D::getWidth(GLint level) const
{ {
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getWidth(); return mTexture->getImage(level)->getWidth();
else else
return 0; return 0;
} }
...@@ -316,7 +337,7 @@ GLsizei Texture2D::getWidth(GLint level) const ...@@ -316,7 +337,7 @@ GLsizei Texture2D::getWidth(GLint level) const
GLsizei Texture2D::getHeight(GLint level) const GLsizei Texture2D::getHeight(GLint level) const
{ {
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getHeight(); return mTexture->getImage(level)->getHeight();
else else
return 0; return 0;
} }
...@@ -324,7 +345,7 @@ GLsizei Texture2D::getHeight(GLint level) const ...@@ -324,7 +345,7 @@ GLsizei Texture2D::getHeight(GLint level) const
GLenum Texture2D::getInternalFormat(GLint level) const GLenum Texture2D::getInternalFormat(GLint level) const
{ {
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getInternalFormat(); return mTexture->getImage(level)->getInternalFormat();
else else
return GL_NONE; return GL_NONE;
} }
...@@ -332,7 +353,7 @@ GLenum Texture2D::getInternalFormat(GLint level) const ...@@ -332,7 +353,7 @@ GLenum Texture2D::getInternalFormat(GLint level) const
GLenum Texture2D::getActualFormat(GLint level) const GLenum Texture2D::getActualFormat(GLint level) const
{ {
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getActualFormat(); return mTexture->getImage(level)->getActualFormat();
else else
return GL_NONE; return GL_NONE;
} }
...@@ -341,32 +362,7 @@ void Texture2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, ...@@ -341,32 +362,7 @@ void Texture2D::redefineImage(GLint level, GLenum internalformat, GLsizei width,
{ {
releaseTexImage(); releaseTexImage();
// If there currently is a corresponding storage texture image, it has these parameters mTexture->redefineImage(level, internalformat, width, height);
const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false);
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
if ((level >= storageLevels && storageLevels != 0) ||
width != storageWidth ||
height != storageHeight ||
internalformat != storageFormat) // Discard mismatched storage
{
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
mImageArray[i]->markDirty();
}
delete mTexStorage;
mTexStorage = NULL;
mDirtyImages = true;
}
}
} }
void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
...@@ -375,42 +371,15 @@ void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum inte ...@@ -375,42 +371,15 @@ void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum inte
: GetSizedInternalFormat(format, type); : GetSizedInternalFormat(format, type);
redefineImage(level, sizedInternalFormat, width, height); redefineImage(level, sizedInternalFormat, width, height);
bool fastUnpacked = false; mTexture->setImage(level, width, height, internalFormat, format, type, unpack, pixels);
// Attempt a fast gpu copy of the pixel data to the surface
if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
{
// Will try to create RT storage if it does not exist
rx::RenderTarget *destRenderTarget = getRenderTarget(level);
Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
{
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
fastUnpacked = true;
}
}
if (!fastUnpacked)
{
Texture::setImage(unpack, type, pixels, mImageArray[level]);
}
} }
void Texture2D::bindTexImage(egl::Surface *surface) void Texture2D::bindTexImage(egl::Surface *surface)
{ {
releaseTexImage(); releaseTexImage();
GLenum internalformat = surface->getFormat(); mTexture->bindTexImage(surface);
mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true);
delete mTexStorage;
mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain());
mDirtyImages = true;
mSurface = surface; mSurface = surface;
mSurface->setBoundTexture(this); mSurface->setBoundTexture(this);
} }
...@@ -422,16 +391,7 @@ void Texture2D::releaseTexImage() ...@@ -422,16 +391,7 @@ void Texture2D::releaseTexImage()
mSurface->setBoundTexture(NULL); mSurface->setBoundTexture(NULL);
mSurface = NULL; mSurface = NULL;
if (mTexStorage) mTexture->releaseTexImage();
{
delete mTexStorage;
mTexStorage = NULL;
}
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
}
} }
} }
...@@ -440,51 +400,17 @@ void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL ...@@ -440,51 +400,17 @@ void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
redefineImage(level, format, width, height); redefineImage(level, format, width, height);
Texture::setCompressedImage(imageSize, pixels, mImageArray[level]); mTexture->setCompressedImage(level, format, width, height, imageSize, pixels);
}
void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
if (isValidLevel(level))
{
rx::ImageD3D *image = rx::ImageD3D::makeImageD3D(mImageArray[level]);
if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height))
{
image->markClean();
}
}
} }
void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{ {
bool fastUnpacked = false; mTexture->subImage(level, xoffset, yoffset, width, height, format, type, unpack, pixels);
if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
{
rx::RenderTarget *renderTarget = getRenderTarget(level);
Box destArea(xoffset, yoffset, 0, width, height, 1);
if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget))
{
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
fastUnpacked = true;
}
}
if (!fastUnpacked && Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[level]))
{
commitRect(level, xoffset, yoffset, width, height);
}
} }
void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
{ {
if (Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level])) mTexture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, pixels);
{
commitRect(level, xoffset, yoffset, width, height);
}
} }
void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
...@@ -493,223 +419,25 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei ...@@ -493,223 +419,25 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei
: GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); : GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
redefineImage(level, sizedInternalFormat, width, height); redefineImage(level, sizedInternalFormat, width, height);
if (!mImageArray[level]->isRenderableFormat()) mTexture->copyImage(level, format, x, y, width, height, source);
{
mImageArray[level]->copy(0, 0, 0, x, y, width, height, source);
mDirtyImages = true;
}
else
{
ensureRenderTarget();
mImageArray[level]->markClean();
if (width != 0 && height != 0 && isValidLevel(level))
{
gl::Rectangle sourceRect;
sourceRect.x = x;
sourceRect.width = width;
sourceRect.y = y;
sourceRect.height = height;
mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level);
}
}
} }
void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{ {
// can only make our texture storage to a render target if level 0 is defined (with a width & height) and mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
// the current level we're copying to is defined (with appropriate format, width & height)
bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
{
mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source);
mDirtyImages = true;
}
else
{
ensureRenderTarget();
if (isValidLevel(level))
{
updateStorageLevel(level);
gl::Rectangle sourceRect;
sourceRect.x = x;
sourceRect.width = width;
sourceRect.y = y;
sourceRect.height = height;
mRenderer->copyImage(source, sourceRect,
gl::GetFormat(getBaseLevelInternalFormat()),
xoffset, yoffset, mTexStorage, level);
}
}
} }
void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{ {
for (int level = 0; level < levels; level++)
{
GLsizei levelWidth = std::max(1, width >> level);
GLsizei levelHeight = std::max(1, height >> level);
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true);
}
for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
}
mImmutable = true; mImmutable = true;
setCompleteTexStorage(new rx::TextureStorageInterface2D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, levels)); mTexture->storage(levels, internalformat, width, height);
}
void Texture2D::setCompleteTexStorage(rx::TextureStorageInterface2D *newCompleteTexStorage)
{
SafeDelete(mTexStorage);
mTexStorage = newCompleteTexStorage;
if (mTexStorage && mTexStorage->isManaged())
{
for (int level = 0; level < mTexStorage->getLevelCount(); level++)
{
rx::ImageD3D::makeImageD3D(mImageArray[level])->setManagedSurface(mTexStorage, level);
}
}
mDirtyImages = true;
} }
// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const
{ {
GLsizei width = getBaseLevelWidth(); return mTexture->isSamplerComplete(samplerState);
GLsizei height = getBaseLevelHeight();
if (width <= 0 || height <= 0)
{
return false;
}
// TODO(geofflang): use context's texture caps
if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(0)).filtering)
{
if (samplerState.magFilter != GL_NEAREST ||
(samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
{
return false;
}
}
// TODO(geofflang): use context's extensions
bool npotSupport = mRenderer->getRendererExtensions().textureNPOT;
if (!npotSupport)
{
if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
(samplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(height)))
{
return false;
}
}
if (IsMipmapFiltered(samplerState))
{
if (!npotSupport)
{
if (!isPow2(width) || !isPow2(height))
{
return false;
}
}
if (!isMipmapComplete())
{
return false;
}
}
// OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
// The internalformat specified for the texture arrays is a sized internal depth or
// depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
// MODE is NONE, and either the magnification filter is not NEAREST or the mini-
// fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
if (gl::GetDepthBits(getInternalFormat(0)) > 0 && mRenderer->getCurrentClientVersion() > 2)
{
if (mSamplerState.compareMode == GL_NONE)
{
if ((mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
mSamplerState.magFilter != GL_NEAREST)
{
return false;
}
}
}
return true;
}
// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool Texture2D::isMipmapComplete() const
{
int levelCount = mipLevels();
for (int level = 0; level < levelCount; level++)
{
if (!isLevelComplete(level))
{
return false;
}
}
return true;
}
bool Texture2D::isLevelComplete(int level) const
{
if (isImmutable())
{
return true;
}
const rx::Image *baseImage = getBaseLevelImage();
GLsizei width = baseImage->getWidth();
GLsizei height = baseImage->getHeight();
if (width <= 0 || height <= 0)
{
return false;
}
// The base image level is complete if the width and height are positive
if (level == 0)
{
return true;
}
ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
rx::Image *image = mImageArray[level];
if (image->getInternalFormat() != baseImage->getInternalFormat())
{
return false;
}
if (image->getWidth() != std::max(1, width >> level))
{
return false;
}
if (image->getHeight() != std::max(1, height >> level))
{
return false;
}
return true;
} }
bool Texture2D::isCompressed(GLint level) const bool Texture2D::isCompressed(GLint level) const
...@@ -722,91 +450,6 @@ bool Texture2D::isDepth(GLint level) const ...@@ -722,91 +450,6 @@ bool Texture2D::isDepth(GLint level) const
return GetDepthBits(getInternalFormat(level)) > 0; return GetDepthBits(getInternalFormat(level)) > 0;
} }
// Constructs a native texture resource from the texture images
void Texture2D::initializeStorage(bool renderTarget)
{
// Only initialize the first time this texture is used as a render target or shader resource
if (mTexStorage)
{
return;
}
// do not attempt to create storage for nonexistant data
if (!isLevelComplete(0))
{
return;
}
bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
setCompleteTexStorage(createCompleteStorage(createRenderTarget));
ASSERT(mTexStorage);
// flush image data to the storage
updateStorage();
}
rx::TextureStorageInterface2D *Texture2D::createCompleteStorage(bool renderTarget) const
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
ASSERT(width > 0 && height > 0);
// use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
return new rx::TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels);
}
void Texture2D::updateStorage()
{
ASSERT(mTexStorage != NULL);
GLint storageLevels = mTexStorage->getLevelCount();
for (int level = 0; level < storageLevels; level++)
{
if (mImageArray[level]->isDirty() && isLevelComplete(level))
{
updateStorageLevel(level);
}
}
}
void Texture2D::updateStorageLevel(int level)
{
ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
ASSERT(isLevelComplete(level));
if (mImageArray[level]->isDirty())
{
commitRect(level, 0, 0, getWidth(level), getHeight(level));
}
}
bool Texture2D::ensureRenderTarget()
{
initializeStorage(true);
if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0)
{
ASSERT(mTexStorage);
if (!mTexStorage->isRenderTarget())
{
rx::TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true);
if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
{
delete newRenderTargetStorage;
return gl::error(GL_OUT_OF_MEMORY, false);
}
setCompleteTexStorage(newRenderTargetStorage);
}
}
return (mTexStorage && mTexStorage->isRenderTarget());
}
void Texture2D::generateMipmaps() void Texture2D::generateMipmaps()
{ {
// Purge array levels 1 through q and reset them to represent the generated mipmap levels. // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
...@@ -818,83 +461,31 @@ void Texture2D::generateMipmaps() ...@@ -818,83 +461,31 @@ void Texture2D::generateMipmaps()
std::max(getBaseLevelHeight() >> level, 1)); std::max(getBaseLevelHeight() >> level, 1));
} }
if (mTexStorage && mTexStorage->isRenderTarget()) mTexture->generateMipmaps();
{
for (int level = 1; level < levelCount; level++)
{
mTexStorage->generateMipmap(level);
mImageArray[level]->markClean();
}
}
else
{
for (int level = 1; level < levelCount; level++)
{
mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]);
}
}
} }
const rx::Image *Texture2D::getBaseLevelImage() const const rx::Image *Texture2D::getBaseLevelImage() const
{ {
return mImageArray[0]; return mTexture->getImage(0);
}
rx::TextureStorageInterface *Texture2D::getBaseLevelStorage()
{
return mTexStorage;
} }
unsigned int Texture2D::getRenderTargetSerial(GLint level) unsigned int Texture2D::getRenderTargetSerial(GLint level)
{ {
return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level) : 0); return mTexture->getRenderTargetSerial(level);
} }
rx::RenderTarget *Texture2D::getRenderTarget(GLint level) rx::RenderTarget *Texture2D::getRenderTarget(GLint level)
{ {
// ensure the underlying texture is created return mTexture->getRenderTarget(level);
if (!ensureRenderTarget())
{
return NULL;
}
updateStorageLevel(level);
// ensure this is NOT a depth texture
if (isDepth(level))
{
return NULL;
}
return mTexStorage->getRenderTarget(level);
} }
rx::RenderTarget *Texture2D::getDepthSencil(GLint level) rx::RenderTarget *Texture2D::getDepthSencil(GLint level)
{ {
// ensure the underlying texture is created return mTexture->getDepthSencil(level);
if (!ensureRenderTarget())
{
return NULL;
}
updateStorageLevel(level);
// ensure this is actually a depth texture
if (!isDepth(level))
{
return NULL;
}
return mTexStorage->getRenderTarget(level);
}
bool Texture2D::isValidLevel(int level) const
{
return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false);
} }
TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_CUBE_MAP) TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id)
: TextureWithRenderer(renderer, id, GL_TEXTURE_CUBE_MAP)
{ {
mTexStorage = NULL; mTexStorage = NULL;
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
...@@ -988,7 +579,7 @@ void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum forma ...@@ -988,7 +579,7 @@ void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum forma
int faceIndex = targetToIndex(target); int faceIndex = targetToIndex(target);
redefineImage(faceIndex, level, format, width, height); redefineImage(faceIndex, level, format, width, height);
Texture::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]); TextureWithRenderer::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]);
} }
void TextureCubeMap::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) void TextureCubeMap::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
...@@ -1004,7 +595,7 @@ void TextureCubeMap::commitRect(int faceIndex, GLint level, GLint xoffset, GLint ...@@ -1004,7 +595,7 @@ void TextureCubeMap::commitRect(int faceIndex, GLint level, GLint xoffset, GLint
void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{ {
int faceIndex = targetToIndex(target); int faceIndex = targetToIndex(target);
if (Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[faceIndex][level])) if (TextureWithRenderer::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[faceIndex][level]))
{ {
commitRect(faceIndex, level, xoffset, yoffset, width, height); commitRect(faceIndex, level, xoffset, yoffset, width, height);
} }
...@@ -1013,7 +604,7 @@ void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint y ...@@ -1013,7 +604,7 @@ void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint y
void TextureCubeMap::subImageCompressed(GLenum target, 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)
{ {
int faceIndex = targetToIndex(target); int faceIndex = targetToIndex(target);
if (Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level])) if (TextureWithRenderer::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level]))
{ {
commitRect(faceIndex, level, xoffset, yoffset, width, height); commitRect(faceIndex, level, xoffset, yoffset, width, height);
} }
...@@ -1280,7 +871,7 @@ void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei ...@@ -1280,7 +871,7 @@ void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei
redefineImage(faceIndex, level, sizedInternalFormat, width, height); redefineImage(faceIndex, level, sizedInternalFormat, width, height);
Texture::setImage(unpack, type, pixels, mImageArray[faceIndex][level]); TextureWithRenderer::setImage(unpack, type, pixels, mImageArray[faceIndex][level]);
} }
int TextureCubeMap::targetToIndex(GLenum target) int TextureCubeMap::targetToIndex(GLenum target)
...@@ -1519,7 +1110,8 @@ bool TextureCubeMap::isValidFaceLevel(int faceIndex, int level) const ...@@ -1519,7 +1110,8 @@ bool TextureCubeMap::isValidFaceLevel(int faceIndex, int level) const
return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
} }
Texture3D::Texture3D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_3D) Texture3D::Texture3D(rx::Renderer *renderer, GLuint id)
: TextureWithRenderer(renderer, id, GL_TEXTURE_3D)
{ {
mTexStorage = NULL; mTexStorage = NULL;
...@@ -1601,7 +1193,7 @@ void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei dep ...@@ -1601,7 +1193,7 @@ void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei dep
if (!fastUnpacked) if (!fastUnpacked)
{ {
Texture::setImage(unpack, type, pixels, mImageArray[level]); TextureWithRenderer::setImage(unpack, type, pixels, mImageArray[level]);
} }
} }
...@@ -1610,7 +1202,7 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL ...@@ -1610,7 +1202,7 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
redefineImage(level, format, width, height, depth); redefineImage(level, format, width, height, depth);
Texture::setCompressedImage(imageSize, pixels, mImageArray[level]); TextureWithRenderer::setCompressedImage(imageSize, pixels, mImageArray[level]);
} }
void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
...@@ -1632,7 +1224,7 @@ void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffse ...@@ -1632,7 +1224,7 @@ void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffse
} }
} }
if (!fastUnpacked && Texture::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level])) if (!fastUnpacked && TextureWithRenderer::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level]))
{ {
commitRect(level, xoffset, yoffset, zoffset, width, height, depth); commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
} }
...@@ -1640,7 +1232,7 @@ void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffse ...@@ -1640,7 +1232,7 @@ void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffse
void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
{ {
if (Texture::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level])) if (TextureWithRenderer::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level]))
{ {
commitRect(level, xoffset, yoffset, zoffset, width, height, depth); commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
} }
...@@ -2036,7 +1628,8 @@ void Texture3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoff ...@@ -2036,7 +1628,8 @@ void Texture3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoff
} }
} }
Texture2DArray::Texture2DArray(rx::Renderer *renderer, GLuint id) : Texture(renderer, id, GL_TEXTURE_2D_ARRAY) Texture2DArray::Texture2DArray(rx::Renderer *renderer, GLuint id)
: TextureWithRenderer(renderer, id, GL_TEXTURE_2D_ARRAY)
{ {
mTexStorage = NULL; mTexStorage = NULL;
...@@ -2115,7 +1708,7 @@ void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsize ...@@ -2115,7 +1708,7 @@ void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsize
for (int i = 0; i < depth; i++) for (int i = 0; i < depth; i++)
{ {
const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
Texture::setImage(unpack, type, layerPixels, mImageArray[level][i]); TextureWithRenderer::setImage(unpack, type, layerPixels, mImageArray[level][i]);
} }
} }
...@@ -2129,7 +1722,7 @@ void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei widt ...@@ -2129,7 +1722,7 @@ void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei widt
for (int i = 0; i < depth; i++) for (int i = 0; i < depth; i++)
{ {
const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
Texture::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]); TextureWithRenderer::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]);
} }
} }
...@@ -2143,7 +1736,7 @@ void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint z ...@@ -2143,7 +1736,7 @@ void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint z
int layer = zoffset + i; int layer = zoffset + i;
const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
if (Texture::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, mImageArray[level][layer])) if (TextureWithRenderer::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, mImageArray[level][layer]))
{ {
commitRect(level, xoffset, yoffset, layer, width, height); commitRect(level, xoffset, yoffset, layer, width, height);
} }
...@@ -2159,7 +1752,7 @@ void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffse ...@@ -2159,7 +1752,7 @@ void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffse
int layer = zoffset + i; int layer = zoffset + i;
const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
if (Texture::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer])) if (TextureWithRenderer::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer]))
{ {
commitRect(level, xoffset, yoffset, layer, width, height); commitRect(level, xoffset, yoffset, layer, width, height);
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "common/debug.h" #include "common/debug.h"
#include "common/RefCountObject.h" #include "common/RefCountObject.h"
#include "libGLESv2/angletypes.h" #include "libGLESv2/angletypes.h"
#include "libGLESv2/constants.h"
namespace egl namespace egl
{ {
...@@ -27,6 +28,7 @@ class Surface; ...@@ -27,6 +28,7 @@ class Surface;
namespace rx namespace rx
{ {
class Renderer; class Renderer;
class Texture2DImpl;
class TextureStorageInterface; class TextureStorageInterface;
class TextureStorageInterface2D; class TextureStorageInterface2D;
class TextureStorageInterfaceCube; class TextureStorageInterfaceCube;
...@@ -41,25 +43,12 @@ namespace gl ...@@ -41,25 +43,12 @@ namespace gl
class Framebuffer; class Framebuffer;
class FramebufferAttachment; class FramebufferAttachment;
enum
{
// These are the maximums the implementation can support
// The actual GL caps are limited by the device caps
// and should be queried from the Context
IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384,
IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048,
IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048,
IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE
};
bool IsMipmapFiltered(const SamplerState &samplerState); bool IsMipmapFiltered(const SamplerState &samplerState);
class Texture : public RefCountObject class Texture : public RefCountObject
{ {
public: public:
Texture(rx::Renderer *renderer, GLuint id, GLenum target); Texture(GLuint id, GLenum target);
virtual ~Texture(); virtual ~Texture();
...@@ -69,7 +58,7 @@ class Texture : public RefCountObject ...@@ -69,7 +58,7 @@ class Texture : public RefCountObject
SamplerState &getSamplerState() { return mSamplerState; } SamplerState &getSamplerState() { return mSamplerState; }
void getSamplerStateWithNativeOffset(SamplerState *sampler); void getSamplerStateWithNativeOffset(SamplerState *sampler);
void setUsage(GLenum usage); virtual void setUsage(GLenum usage);
GLenum getUsage() const; GLenum getUsage() const;
GLint getBaseLevelWidth() const; GLint getBaseLevelWidth() const;
...@@ -79,14 +68,13 @@ class Texture : public RefCountObject ...@@ -79,14 +68,13 @@ class Texture : public RefCountObject
virtual bool isSamplerComplete(const SamplerState &samplerState) const = 0; virtual bool isSamplerComplete(const SamplerState &samplerState) const = 0;
rx::TextureStorageInterface *getNativeTexture(); virtual rx::TextureStorageInterface *getNativeTexture() = 0;
virtual void generateMipmaps() = 0; virtual void generateMipmaps() = 0;
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0; virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;
bool hasDirtyParameters() const; virtual bool hasDirtyImages() const = 0;
bool hasDirtyImages() const; virtual void resetDirty() = 0;
void resetDirty();
unsigned int getTextureSerial(); unsigned int getTextureSerial();
bool isImmutable() const; bool isImmutable() const;
...@@ -95,6 +83,34 @@ class Texture : public RefCountObject ...@@ -95,6 +83,34 @@ class Texture : public RefCountObject
static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager. static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
protected: protected:
int mipLevels() const;
SamplerState mSamplerState;
GLenum mUsage;
bool mImmutable;
GLenum mTarget;
private:
DISALLOW_COPY_AND_ASSIGN(Texture);
virtual const rx::Image *getBaseLevelImage() const = 0;
};
// TODO: This class is only here to make incremental Texture refactoring easier
class TextureWithRenderer : public Texture
{
public:
TextureWithRenderer(rx::Renderer *renderer, GLuint id, GLenum target);
virtual ~TextureWithRenderer();
virtual rx::TextureStorageInterface *getNativeTexture();
virtual bool hasDirtyImages() const;
virtual void resetDirty();
protected:
void setImage(const PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image); void setImage(const PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image);
bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels, rx::Image *image); GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels, rx::Image *image);
...@@ -106,37 +122,32 @@ class Texture : public RefCountObject ...@@ -106,37 +122,32 @@ class Texture : public RefCountObject
GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget); GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget);
GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
int mipLevels() const;
virtual void initializeStorage(bool renderTarget) = 0; virtual void initializeStorage(bool renderTarget) = 0;
virtual void updateStorage() = 0; virtual void updateStorage() = 0;
virtual bool ensureRenderTarget() = 0; virtual bool ensureRenderTarget() = 0;
rx::Renderer *mRenderer; rx::Renderer *mRenderer;
SamplerState mSamplerState;
GLenum mUsage;
bool mDirtyImages; bool mDirtyImages;
bool mImmutable;
GLenum mTarget;
private: private:
DISALLOW_COPY_AND_ASSIGN(Texture); DISALLOW_COPY_AND_ASSIGN(TextureWithRenderer);
virtual rx::TextureStorageInterface *getBaseLevelStorage() = 0; virtual rx::TextureStorageInterface *getBaseLevelStorage() = 0;
virtual const rx::Image *getBaseLevelImage() const = 0;
}; };
class Texture2D : public Texture class Texture2D : public Texture
{ {
public: public:
Texture2D(rx::Renderer *renderer, GLuint id); Texture2D(rx::Texture2DImpl *impl, GLuint id);
~Texture2D(); ~Texture2D();
virtual rx::TextureStorageInterface *getNativeTexture();
virtual void setUsage(GLenum usage);
virtual bool hasDirtyImages() const;
virtual void resetDirty();
GLsizei getWidth(GLint level) const; GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const; GLsizei getHeight(GLint level) const;
GLenum getInternalFormat(GLint level) const; GLenum getInternalFormat(GLint level) const;
...@@ -168,30 +179,15 @@ class Texture2D : public Texture ...@@ -168,30 +179,15 @@ class Texture2D : public Texture
private: private:
DISALLOW_COPY_AND_ASSIGN(Texture2D); DISALLOW_COPY_AND_ASSIGN(Texture2D);
virtual void initializeStorage(bool renderTarget);
rx::TextureStorageInterface2D *createCompleteStorage(bool renderTarget) const;
void setCompleteTexStorage(rx::TextureStorageInterface2D *newCompleteTexStorage);
virtual void updateStorage();
virtual bool ensureRenderTarget();
virtual rx::TextureStorageInterface *getBaseLevelStorage();
virtual const rx::Image *getBaseLevelImage() const; virtual const rx::Image *getBaseLevelImage() const;
bool isMipmapComplete() const;
bool isValidLevel(int level) const;
bool isLevelComplete(int level) const;
void updateStorageLevel(int level);
void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height);
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
rx::TextureStorageInterface2D *mTexStorage; rx::Texture2DImpl *mTexture;
egl::Surface *mSurface; egl::Surface *mSurface;
}; };
class TextureCubeMap : public Texture class TextureCubeMap : public TextureWithRenderer
{ {
public: public:
TextureCubeMap(rx::Renderer *renderer, GLuint id); TextureCubeMap(rx::Renderer *renderer, GLuint id);
...@@ -260,7 +256,7 @@ class TextureCubeMap : public Texture ...@@ -260,7 +256,7 @@ class TextureCubeMap : public Texture
rx::TextureStorageInterfaceCube *mTexStorage; rx::TextureStorageInterfaceCube *mTexStorage;
}; };
class Texture3D : public Texture class Texture3D : public TextureWithRenderer
{ {
public: public:
Texture3D(rx::Renderer *renderer, GLuint id); Texture3D(rx::Renderer *renderer, GLuint id);
...@@ -320,7 +316,7 @@ class Texture3D : public Texture ...@@ -320,7 +316,7 @@ class Texture3D : public Texture
rx::TextureStorageInterface3D *mTexStorage; rx::TextureStorageInterface3D *mTexStorage;
}; };
class Texture2DArray : public Texture class Texture2DArray : public TextureWithRenderer
{ {
public: public:
Texture2DArray(rx::Renderer *renderer, GLuint id); Texture2DArray(rx::Renderer *renderer, GLuint id);
......
...@@ -31,6 +31,16 @@ enum ...@@ -31,6 +31,16 @@ enum
IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS, IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS,
IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4, IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4,
// These are the maximums the implementation can support
// The actual GL caps are limited by the device caps
// and should be queried from the Context
IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384,
IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048,
IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048,
IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE
}; };
} }
......
...@@ -58,6 +58,8 @@ class Image; ...@@ -58,6 +58,8 @@ class Image;
class TextureStorage; class TextureStorage;
class UniformStorage; class UniformStorage;
class Texture2DImpl;
struct ConfigDesc struct ConfigDesc
{ {
GLenum renderTargetFormat; GLenum renderTargetFormat;
...@@ -225,6 +227,9 @@ class Renderer ...@@ -225,6 +227,9 @@ class Renderer
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
// Texture creation
virtual Texture2DImpl *createTexture2D() = 0;
// Buffer creation // Buffer creation
virtual BufferImpl *createBuffer() = 0; virtual BufferImpl *createBuffer() = 0;
virtual VertexBuffer *createVertexBuffer() = 0; virtual VertexBuffer *createVertexBuffer() = 0;
......
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureImpl.h: Defines the abstract rx::TextureImpl classes.
#ifndef LIBGLESV2_RENDERER_TEXTUREIMPL_H_
#define LIBGLESV2_RENDERER_TEXTUREIMPL_H_
#include "common/angleutils.h"
namespace gl
{
class Framebuffer;
struct SamplerState;
}
namespace rx
{
class Image;
class RenderTarget;
class Renderer;
class TextureStorageInterface;
class TextureStorageInterface2D;
class Texture2DImpl
{
public:
virtual ~Texture2DImpl() {}
// TODO: If this methods could go away that would be ideal;
// TextureStorage should only be necessary for the D3D backend, and as such
// higher level code should not rely on it.
virtual TextureStorageInterface *getNativeTexture() = 0;
virtual Image *getImage(int level) const = 0;
virtual void setUsage(GLenum usage) = 0;
virtual bool hasDirtyImages() const = 0;
virtual void resetDirty() = 0;
virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0;
virtual void bindTexImage(egl::Surface *surface) = 0;
virtual void releaseTexImage() = 0;
virtual void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) = 0;
virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) = 0;
virtual void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) = 0;
virtual void generateMipmaps() = 0;
virtual unsigned int getRenderTargetSerial(GLint level) = 0;
virtual RenderTarget *getRenderTarget(GLint level) = 0;
virtual RenderTarget *getDepthSencil(GLint level) = 0;
virtual void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) = 0;
};
}
#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_
#include "precompiled.h"
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends.
#include "common/mathutil.h"
#include "libEGL/Surface.h"
#include "libGLESv2/Buffer.h"
#include "libGLESv2/Framebuffer.h"
#include "libGLESv2/main.h"
#include "libGLESv2/formatutils.h"
#include "libGLESv2/renderer/BufferImpl.h"
#include "libGLESv2/renderer/RenderTarget.h"
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/renderer/d3d/ImageD3D.h"
#include "libGLESv2/renderer/d3d/TextureD3D.h"
#include "libGLESv2/renderer/d3d/TextureStorage.h"
namespace rx
{
bool IsMipmapFiltered(const gl::SamplerState &samplerState)
{
switch (samplerState.minFilter)
{
case GL_NEAREST:
case GL_LINEAR:
return false;
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
return true;
default: UNREACHABLE();
return false;
}
}
bool IsRenderTargetUsage(GLenum usage)
{
return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
}
TextureD3D::TextureD3D(rx::Renderer *renderer)
: mRenderer(renderer),
mUsage(GL_NONE),
mDirtyImages(true),
mImmutable(false)
{
}
TextureD3D::~TextureD3D()
{
}
GLint TextureD3D::getBaseLevelWidth() const
{
const rx::Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getWidth() : 0);
}
GLint TextureD3D::getBaseLevelHeight() const
{
const rx::Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getHeight() : 0);
}
GLint TextureD3D::getBaseLevelDepth() const
{
const rx::Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getDepth() : 0);
}
// Note: "base level image" is loosely defined to be any image from the base level,
// where in the base of 2D array textures and cube maps there are several. Don't use
// the base level image for anything except querying texture format and size.
GLenum TextureD3D::getBaseLevelInternalFormat() const
{
const rx::Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
}
void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image)
{
// No-op
if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
{
return;
}
// We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
// From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
const void *pixelData = pixels;
if (unpack.pixelBuffer.id() != 0)
{
// Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
// TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
// This functionality should be moved into renderer and the getData method of BufferImpl removed.
const void *bufferData = pixelBuffer->getImplementation()->getData();
pixelData = static_cast<const unsigned char *>(bufferData) + offset;
}
if (pixelData != NULL)
{
image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
mDirtyImages = true;
}
}
bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, rx::Image *image)
{
const void *pixelData = pixels;
// CPU readback & copy where direct GPU copy is not supported
if (unpack.pixelBuffer.id() != 0)
{
gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
unsigned int offset = reinterpret_cast<unsigned int>(pixels);
// TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
// This functionality should be moved into renderer and the getData method of BufferImpl removed.
const void *bufferData = pixelBuffer->getImplementation()->getData();
pixelData = static_cast<const unsigned char *>(bufferData) + offset;
}
if (pixelData != NULL)
{
image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData);
mDirtyImages = true;
}
return true;
}
void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image)
{
if (pixels != NULL)
{
image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels);
mDirtyImages = true;
}
}
bool TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image)
{
if (pixels != NULL)
{
image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels);
mDirtyImages = true;
}
return true;
}
bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
{
return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
}
bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget)
{
if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
{
return true;
}
// In order to perform the fast copy through the shader, we must have the right format, and be able
// to create a render target.
ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
unsigned int offset = reinterpret_cast<unsigned int>(pixels);
return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
}
GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
{
if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT)
{
// Maximum number of levels
return gl::log2(std::max(std::max(width, height), depth)) + 1;
}
else
{
// OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
return 1;
}
}
int TextureD3D::mipLevels() const
{
return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
}
TextureD3D_2D::TextureD3D_2D(rx::Renderer *renderer)
: TextureD3D(renderer),
Texture2DImpl(),
mTexStorage(NULL)
{
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage());
}
}
TextureD3D_2D::~TextureD3D_2D()
{
SafeDelete(mTexStorage);
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
delete mImageArray[i];
}
}
TextureD3D_2D *TextureD3D_2D::makeTextureD3D_2D(Texture2DImpl *texture)
{
ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_2D*, texture));
return static_cast<TextureD3D_2D*>(texture);
}
TextureStorageInterface *TextureD3D_2D::getNativeTexture()
{
// ensure the underlying texture is created
initializeStorage(false);
rx::TextureStorageInterface *storage = getBaseLevelStorage();
if (storage)
{
updateStorage();
}
return storage;
}
Image *TextureD3D_2D::getImage(int level) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
return mImageArray[level];
}
void TextureD3D_2D::setUsage(GLenum usage)
{
mUsage = usage;
}
void TextureD3D_2D::resetDirty()
{
mDirtyImages = false;
}
GLsizei TextureD3D_2D::getWidth(GLint level) const
{
if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getWidth();
else
return 0;
}
GLsizei TextureD3D_2D::getHeight(GLint level) const
{
if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getHeight();
else
return 0;
}
GLenum TextureD3D_2D::getInternalFormat(GLint level) const
{
if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getInternalFormat();
else
return GL_NONE;
}
GLenum TextureD3D_2D::getActualFormat(GLint level) const
{
if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getActualFormat();
else
return GL_NONE;
}
bool TextureD3D_2D::isDepth(GLint level) const
{
return gl::GetDepthBits(getInternalFormat(level)) > 0;
}
void TextureD3D_2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
{
GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat
: gl::GetSizedInternalFormat(format, type);
bool fastUnpacked = false;
// Attempt a fast gpu copy of the pixel data to the surface
if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
{
// Will try to create RT storage if it does not exist
rx::RenderTarget *destRenderTarget = getRenderTarget(level);
gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
{
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
fastUnpacked = true;
}
}
if (!fastUnpacked)
{
TextureD3D::setImage(unpack, type, pixels, mImageArray[level]);
}
}
void TextureD3D_2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]);
}
void TextureD3D_2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
{
bool fastUnpacked = false;
if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
{
rx::RenderTarget *renderTarget = getRenderTarget(level);
gl::Box destArea(xoffset, yoffset, 0, width, height, 1);
if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget))
{
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
fastUnpacked = true;
}
}
if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[level]))
{
commitRect(level, xoffset, yoffset, width, height);
}
}
void TextureD3D_2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
{
if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level]))
{
commitRect(level, xoffset, yoffset, width, height);
}
}
void TextureD3D_2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
{
if (!mImageArray[level]->isRenderableFormat())
{
mImageArray[level]->copy(0, 0, 0, x, y, width, height, source);
mDirtyImages = true;
}
else
{
ensureRenderTarget();
mImageArray[level]->markClean();
if (width != 0 && height != 0 && isValidLevel(level))
{
gl::Rectangle sourceRect;
sourceRect.x = x;
sourceRect.width = width;
sourceRect.y = y;
sourceRect.height = height;
mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level);
}
}
}
void TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
{
// can only make our texture storage to a render target if level 0 is defined (with a width & height) and
// the current level we're copying to is defined (with appropriate format, width & height)
bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
{
mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source);
mDirtyImages = true;
}
else
{
ensureRenderTarget();
if (isValidLevel(level))
{
updateStorageLevel(level);
gl::Rectangle sourceRect;
sourceRect.x = x;
sourceRect.width = width;
sourceRect.y = y;
sourceRect.height = height;
mRenderer->copyImage(source, sourceRect,
gl::GetFormat(getBaseLevelInternalFormat()),
xoffset, yoffset, mTexStorage, level);
}
}
}
void TextureD3D_2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
for (int level = 0; level < levels; level++)
{
GLsizei levelWidth = std::max(1, width >> level);
GLsizei levelHeight = std::max(1, height >> level);
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true);
}
for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
}
mImmutable = true;
setCompleteTexStorage(new rx::TextureStorageInterface2D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, levels));
}
// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
bool TextureD3D_2D::isSamplerComplete(const gl::SamplerState &samplerState) const
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
if (width <= 0 || height <= 0)
{
return false;
}
if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(0)).filtering)
{
if (samplerState.magFilter != GL_NEAREST ||
(samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
{
return false;
}
}
// TODO(geofflang): use context's extensions
bool npotSupport = mRenderer->getRendererExtensions().textureNPOT;
if (!npotSupport)
{
if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
(samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
{
return false;
}
}
if (IsMipmapFiltered(samplerState))
{
if (!npotSupport)
{
if (!gl::isPow2(width) || !gl::isPow2(height))
{
return false;
}
}
if (!isMipmapComplete())
{
return false;
}
}
// OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
// The internalformat specified for the texture arrays is a sized internal depth or
// depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
// MODE is NONE, and either the magnification filter is not NEAREST or the mini-
// fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
if (gl::GetDepthBits(getInternalFormat(0)) > 0 && mRenderer->getCurrentClientVersion() > 2)
{
if (samplerState.compareMode == GL_NONE)
{
if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
samplerState.magFilter != GL_NEAREST)
{
return false;
}
}
}
return true;
}
void TextureD3D_2D::bindTexImage(egl::Surface *surface)
{
GLenum internalformat = surface->getFormat();
mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true);
if (mTexStorage)
{
SafeDelete(mTexStorage);
}
mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain());
mDirtyImages = true;
}
void TextureD3D_2D::releaseTexImage()
{
if (mTexStorage)
{
SafeDelete(mTexStorage);
}
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
}
}
void TextureD3D_2D::generateMipmaps()
{
int levelCount = mipLevels();
if (mTexStorage && mTexStorage->isRenderTarget())
{
for (int level = 1; level < levelCount; level++)
{
mTexStorage->generateMipmap(level);
mImageArray[level]->markClean();
}
}
else
{
for (int level = 1; level < levelCount; level++)
{
mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]);
}
}
}
unsigned int TextureD3D_2D::getRenderTargetSerial(GLint level)
{
return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level) : 0);
}
RenderTarget *TextureD3D_2D::getRenderTarget(GLint level)
{
// ensure the underlying texture is created
if (!ensureRenderTarget())
{
return NULL;
}
updateStorageLevel(level);
// ensure this is NOT a depth texture
if (isDepth(level))
{
return NULL;
}
return mTexStorage->getRenderTarget(level);
}
RenderTarget *TextureD3D_2D::getDepthSencil(GLint level)
{
// ensure the underlying texture is created
if (!ensureRenderTarget())
{
return NULL;
}
updateStorageLevel(level);
// ensure this is actually a depth texture
if (!isDepth(level))
{
return NULL;
}
return mTexStorage->getRenderTarget(level);
}
// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool TextureD3D_2D::isMipmapComplete() const
{
int levelCount = mipLevels();
for (int level = 0; level < levelCount; level++)
{
if (!isLevelComplete(level))
{
return false;
}
}
return true;
}
bool TextureD3D_2D::isValidLevel(int level) const
{
return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false);
}
bool TextureD3D_2D::isLevelComplete(int level) const
{
if (isImmutable())
{
return true;
}
const rx::Image *baseImage = getBaseLevelImage();
GLsizei width = baseImage->getWidth();
GLsizei height = baseImage->getHeight();
if (width <= 0 || height <= 0)
{
return false;
}
// The base image level is complete if the width and height are positive
if (level == 0)
{
return true;
}
ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
rx::Image *image = mImageArray[level];
if (image->getInternalFormat() != baseImage->getInternalFormat())
{
return false;
}
if (image->getWidth() != std::max(1, width >> level))
{
return false;
}
if (image->getHeight() != std::max(1, height >> level))
{
return false;
}
return true;
}
// Constructs a native texture resource from the texture images
void TextureD3D_2D::initializeStorage(bool renderTarget)
{
// Only initialize the first time this texture is used as a render target or shader resource
if (mTexStorage)
{
return;
}
// do not attempt to create storage for nonexistant data
if (!isLevelComplete(0))
{
return;
}
bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
setCompleteTexStorage(createCompleteStorage(createRenderTarget));
ASSERT(mTexStorage);
// flush image data to the storage
updateStorage();
}
rx::TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderTarget) const
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
ASSERT(width > 0 && height > 0);
// use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
return new rx::TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels);
}
void TextureD3D_2D::setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage)
{
SafeDelete(mTexStorage);
mTexStorage = newCompleteTexStorage;
if (mTexStorage && mTexStorage->isManaged())
{
for (int level = 0; level < mTexStorage->getLevelCount(); level++)
{
mImageArray[level]->setManagedSurface(mTexStorage, level);
}
}
mDirtyImages = true;
}
void TextureD3D_2D::updateStorage()
{
ASSERT(mTexStorage != NULL);
GLint storageLevels = mTexStorage->getLevelCount();
for (int level = 0; level < storageLevels; level++)
{
if (mImageArray[level]->isDirty() && isLevelComplete(level))
{
updateStorageLevel(level);
}
}
}
bool TextureD3D_2D::ensureRenderTarget()
{
initializeStorage(true);
if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0)
{
ASSERT(mTexStorage);
if (!mTexStorage->isRenderTarget())
{
rx::TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true);
if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
{
delete newRenderTargetStorage;
return gl::error(GL_OUT_OF_MEMORY, false);
}
setCompleteTexStorage(newRenderTargetStorage);
}
}
return (mTexStorage && mTexStorage->isRenderTarget());
}
TextureStorageInterface *TextureD3D_2D::getBaseLevelStorage()
{
return mTexStorage;
}
const ImageD3D *TextureD3D_2D::getBaseLevelImage() const
{
return mImageArray[0];
}
void TextureD3D_2D::updateStorageLevel(int level)
{
ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
ASSERT(isLevelComplete(level));
if (mImageArray[level]->isDirty())
{
commitRect(level, 0, 0, getWidth(level), getHeight(level));
}
}
void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height)
{
// If there currently is a corresponding storage texture image, it has these parameters
const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false);
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
if ((level >= storageLevels && storageLevels != 0) ||
width != storageWidth ||
height != storageHeight ||
internalformat != storageFormat) // Discard mismatched storage
{
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
mImageArray[i]->markDirty();
}
SafeDelete(mTexStorage);
mDirtyImages = true;
}
}
}
void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
if (isValidLevel(level))
{
rx::ImageD3D *image = mImageArray[level];
if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height))
{
image->markClean();
}
}
}
}
\ No newline at end of file
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends.
#ifndef LIBGLESV2_RENDERER_TEXTURED3D_H_
#define LIBGLESV2_RENDERER_TEXTURED3D_H_
#include "libGLESv2/renderer/TextureImpl.h"
#include "libGLESv2/angletypes.h"
#include "libGLESv2/constants.h"
namespace gl
{
class Framebuffer;
}
namespace rx
{
class Image;
class ImageD3D;
class Renderer;
class TextureStorageInterface;
class TextureStorageInterface2D;
class TextureD3D
{
public:
TextureD3D(rx::Renderer *renderer);
virtual ~TextureD3D();
GLint getBaseLevelWidth() const;
GLint getBaseLevelHeight() const;
GLint getBaseLevelDepth() const;
GLenum getBaseLevelInternalFormat() const;
bool isImmutable() const { return mImmutable; }
protected:
void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image);
bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, rx::Image *image);
void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image);
bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image);
bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat);
bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget);
GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
int mipLevels() const;
Renderer *mRenderer;
GLenum mUsage;
bool mDirtyImages;
bool mImmutable;
private:
DISALLOW_COPY_AND_ASSIGN(TextureD3D);
virtual TextureStorageInterface *getBaseLevelStorage() = 0;
virtual const ImageD3D *getBaseLevelImage() const = 0;
};
class TextureD3D_2D : public Texture2DImpl, public TextureD3D
{
public:
TextureD3D_2D(rx::Renderer *renderer);
virtual ~TextureD3D_2D();
static TextureD3D_2D *makeTextureD3D_2D(Texture2DImpl *texture);
virtual TextureStorageInterface *getNativeTexture();
virtual Image *getImage(int level) const;
virtual void setUsage(GLenum usage);
virtual bool hasDirtyImages() const { return mDirtyImages; }
virtual void resetDirty();
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLenum getInternalFormat(GLint level) const;
GLenum getActualFormat(GLint level) const;
bool isDepth(GLint level) const;
virtual void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
virtual void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
virtual void generateMipmaps();
virtual unsigned int getRenderTargetSerial(GLint level);
virtual RenderTarget *getRenderTarget(GLint level);
virtual RenderTarget *getDepthSencil(GLint level);
private:
DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D);
void initializeStorage(bool renderTarget);
TextureStorageInterface2D *createCompleteStorage(bool renderTarget) const;
void setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage);
void updateStorage();
bool ensureRenderTarget();
virtual TextureStorageInterface *getBaseLevelStorage();
virtual const ImageD3D *getBaseLevelImage() const;
bool isMipmapComplete() const;
bool isValidLevel(int level) const;
bool isLevelComplete(int level) const;
void updateStorageLevel(int level);
virtual void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height);
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
TextureStorageInterface2D *mTexStorage;
ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
};
}
#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/FramebufferAttachment.h"
#include "libGLESv2/ProgramBinary.h" #include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/Framebuffer.h" #include "libGLESv2/Framebuffer.h"
#include "libGLESv2/renderer/d3d/TextureD3D.h"
#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
...@@ -2900,6 +2901,11 @@ TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, b ...@@ -2900,6 +2901,11 @@ TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, b
return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels);
} }
Texture2DImpl *Renderer11::createTexture2D()
{
return new TextureD3D_2D(this);
}
void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format,
GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels) GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels)
{ {
......
...@@ -177,6 +177,9 @@ class Renderer11 : public Renderer ...@@ -177,6 +177,9 @@ class Renderer11 : public Renderer
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
// Texture creation
virtual Texture2DImpl *createTexture2D();
// Buffer creation // Buffer creation
virtual BufferImpl *createBuffer(); virtual BufferImpl *createBuffer();
virtual VertexBuffer *createVertexBuffer(); virtual VertexBuffer *createVertexBuffer();
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/ProgramBinary.h" #include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/renderer/d3d/IndexDataManager.h" #include "libGLESv2/renderer/d3d/IndexDataManager.h"
#include "libGLESv2/renderer/d3d/TextureD3D.h"
#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
...@@ -3193,6 +3194,11 @@ TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bo ...@@ -3193,6 +3194,11 @@ TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bo
return NULL; return NULL;
} }
Texture2DImpl *Renderer9::createTexture2D()
{
return new TextureD3D_2D(this);
}
bool Renderer9::getLUID(LUID *adapterLuid) const bool Renderer9::getLUID(LUID *adapterLuid) const
{ {
adapterLuid->HighPart = 0; adapterLuid->HighPart = 0;
......
...@@ -179,6 +179,9 @@ class Renderer9 : public Renderer ...@@ -179,6 +179,9 @@ class Renderer9 : public Renderer
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
// Texture creation
virtual Texture2DImpl *createTexture2D();
// Buffer creation // Buffer creation
virtual BufferImpl *createBuffer(); virtual BufferImpl *createBuffer();
virtual VertexBuffer *createVertexBuffer(); virtual VertexBuffer *createVertexBuffer();
......
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