Commit 78b1acdb by Brandon Jones

Refactored Texture3D, separated out D3D logic

BUG=angle:688 Change-Id: I6cda73c2e4c8a026b8c5222bc40cea93ad4e0ba3 Reviewed-on: https://chromium-review.googlesource.com/208102Tested-by: 's avatarBrandon Jones <bajones@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 0511e808
...@@ -70,7 +70,7 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere ...@@ -70,7 +70,7 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
mTexture2DZero.set(new Texture2D(mRenderer->createTexture2D(), 0)); mTexture2DZero.set(new Texture2D(mRenderer->createTexture2D(), 0));
mTextureCubeMapZero.set(new TextureCubeMap(mRenderer->createTextureCube(), 0)); mTextureCubeMapZero.set(new TextureCubeMap(mRenderer->createTextureCube(), 0));
mTexture3DZero.set(new Texture3D(mRenderer, 0)); mTexture3DZero.set(new Texture3D(mRenderer->createTexture3D(), 0));
mTexture2DArrayZero.set(new Texture2DArray(mRenderer, 0)); mTexture2DArrayZero.set(new Texture2DArray(mRenderer, 0));
bindVertexArray(0); bindVertexArray(0);
...@@ -2174,7 +2174,7 @@ Texture *Context::getIncompleteTexture(TextureType type) ...@@ -2174,7 +2174,7 @@ Texture *Context::getIncompleteTexture(TextureType type)
case TEXTURE_3D: case TEXTURE_3D:
{ {
Texture3D *incomplete3d = new Texture3D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture3D(), Texture::INCOMPLETE_TEXTURE_ID);
incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
t = incomplete3d; t = incomplete3d;
......
...@@ -385,7 +385,7 @@ void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) ...@@ -385,7 +385,7 @@ void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
} }
else if (type == TEXTURE_3D) else if (type == TEXTURE_3D)
{ {
textureObject = new Texture3D(mRenderer, texture); textureObject = new Texture3D(mRenderer->createTexture3D(), texture);
} }
else if (type == TEXTURE_2D_ARRAY) else if (type == TEXTURE_2D_ARRAY)
{ {
......
...@@ -659,51 +659,61 @@ rx::RenderTarget *TextureCubeMap::getDepthStencil(GLenum target, GLint level) ...@@ -659,51 +659,61 @@ rx::RenderTarget *TextureCubeMap::getDepthStencil(GLenum target, GLint level)
return mTexture->getDepthStencil(target, level); return mTexture->getDepthStencil(target, level);
} }
Texture3D::Texture3D(rx::Renderer *renderer, GLuint id) Texture3D::Texture3D(rx::Texture3DImpl *impl, GLuint id)
: TextureWithRenderer(renderer, id, GL_TEXTURE_3D) : Texture(id, GL_TEXTURE_3D),
mTexture(impl)
{ {
mTexStorage = NULL;
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
mImageArray[i] = renderer->createImage();
}
} }
Texture3D::~Texture3D() Texture3D::~Texture3D()
{ {
delete mTexStorage; SafeDelete(mTexture);
mTexStorage = NULL; }
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) rx::TextureStorageInterface *Texture3D::getNativeTexture()
{ {
delete mImageArray[i]; return mTexture->getNativeTexture();
} }
void Texture3D::setUsage(GLenum usage)
{
mUsage = usage;
mTexture->setUsage(usage);
}
bool Texture3D::hasDirtyImages() const
{
return mTexture->hasDirtyImages();
}
void Texture3D::resetDirty()
{
mTexture->resetDirty();
} }
GLsizei Texture3D::getWidth(GLint level) const GLsizei Texture3D::getWidth(GLint level) const
{ {
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getWidth() : 0; return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getWidth() : 0;
} }
GLsizei Texture3D::getHeight(GLint level) const GLsizei Texture3D::getHeight(GLint level) const
{ {
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getHeight() : 0; return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getHeight() : 0;
} }
GLsizei Texture3D::getDepth(GLint level) const GLsizei Texture3D::getDepth(GLint level) const
{ {
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getDepth() : 0; return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getDepth() : 0;
} }
GLenum Texture3D::getInternalFormat(GLint level) const GLenum Texture3D::getInternalFormat(GLint level) const
{ {
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getInternalFormat() : GL_NONE; return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getInternalFormat() : GL_NONE;
} }
GLenum Texture3D::getActualFormat(GLint level) const GLenum Texture3D::getActualFormat(GLint level) const
{ {
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mImageArray[level]->getActualFormat() : GL_NONE; return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getActualFormat() : GL_NONE;
} }
bool Texture3D::isCompressed(GLint level) const bool Texture3D::isCompressed(GLint level) const
...@@ -718,463 +728,74 @@ bool Texture3D::isDepth(GLint level) const ...@@ -718,463 +728,74 @@ bool Texture3D::isDepth(GLint level) const
void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{ {
GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat) ? internalFormat mTexture->setImage(level, width, height, depth, internalFormat, format, type, unpack, pixels);
: GetSizedInternalFormat(format, type);
redefineImage(level, sizedInternalFormat, width, height, depth);
bool fastUnpacked = false;
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
if (isFastUnpackable(unpack, sizedInternalFormat))
{
// 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), getDepth(level));
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)
{
TextureWithRenderer::setImage(unpack, type, pixels, mImageArray[level]);
}
} }
void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
{ {
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly mTexture->setCompressedImage(level, format, width, height, depth, imageSize, pixels);
redefineImage(level, format, width, height, depth);
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)
{ {
bool fastUnpacked = false; mTexture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
if (isFastUnpackable(unpack, getInternalFormat(level)))
{
rx::RenderTarget *destRenderTarget = getRenderTarget(level);
Box destArea(xoffset, yoffset, zoffset, width, height, depth);
if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget))
{
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
fastUnpacked = true;
}
}
if (!fastUnpacked && TextureWithRenderer::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level]))
{
commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
}
} }
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 (TextureWithRenderer::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level])) mTexture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
{
commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
}
} }
void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{ {
for (int level = 0; level < levels; level++)
{
GLsizei levelWidth = std::max(1, width >> level);
GLsizei levelHeight = std::max(1, height >> level);
GLsizei levelDepth = std::max(1, depth >> level);
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true);
}
for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true);
}
mImmutable = true; mImmutable = true;
setCompleteTexStorage(new rx::TextureStorageInterface3D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); mTexture->storage(levels, internalformat, width, height, depth);
} }
void Texture3D::generateMipmaps() void Texture3D::generateMipmaps()
{ {
// Purge array levels 1 through q and reset them to represent the generated mipmap levels. mTexture->generateMipmaps();
int levelCount = mipLevels();
for (int level = 1; level < levelCount; level++)
{
redefineImage(level, getBaseLevelInternalFormat(),
std::max(getBaseLevelWidth() >> level, 1),
std::max(getBaseLevelHeight() >> level, 1),
std::max(getBaseLevelDepth() >> level, 1));
}
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]);
}
}
} }
const rx::Image *Texture3D::getBaseLevelImage() const const rx::Image *Texture3D::getBaseLevelImage() const
{ {
return mImageArray[0]; return mTexture->getImage(0);
}
rx::TextureStorageInterface *Texture3D::getBaseLevelStorage()
{
return mTexStorage;
} }
void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) void Texture3D::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, zoffset, 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, zoffset, mTexStorage, level);
}
}
} }
bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const
{ {
GLsizei width = getBaseLevelWidth(); return mTexture->isSamplerComplete(samplerState);
GLsizei height = getBaseLevelHeight();
GLsizei depth = getBaseLevelDepth();
if (width <= 0 || height <= 0 || depth <= 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;
}
}
if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
{
return false;
}
return true;
} }
bool Texture3D::isMipmapComplete() const bool Texture3D::isMipmapComplete() const
{ {
int levelCount = mipLevels(); return mTexture->isMipmapComplete();
for (int level = 0; level < levelCount; level++)
{
if (!isLevelComplete(level))
{
return false;
}
}
return true;
}
bool Texture3D::isLevelComplete(int level) const
{
ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
if (isImmutable())
{
return true;
}
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei depth = getBaseLevelDepth();
if (width <= 0 || height <= 0 || depth <= 0)
{
return false;
}
if (level == 0)
{
return true;
}
rx::Image *levelImage = mImageArray[level];
if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
{
return false;
}
if (levelImage->getWidth() != std::max(1, width >> level))
{
return false;
}
if (levelImage->getHeight() != std::max(1, height >> level))
{
return false;
}
if (levelImage->getDepth() != std::max(1, depth >> level))
{
return false;
}
return true;
} }
unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer) unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer)
{ {
return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); return mTexture->getRenderTargetSerial(level, layer);
}
bool Texture3D::isValidLevel(int level) const
{
return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
}
void Texture3D::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 || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
setCompleteTexStorage(createCompleteStorage(createRenderTarget));
ASSERT(mTexStorage);
// flush image data to the storage
updateStorage();
}
rx::TextureStorageInterface3D *Texture3D::createCompleteStorage(bool renderTarget) const
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei depth = getBaseLevelDepth();
ASSERT(width > 0 && height > 0 && depth > 0);
// use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
return new rx::TextureStorageInterface3D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels);
}
void Texture3D::setCompleteTexStorage(rx::TextureStorageInterface3D *newCompleteTexStorage)
{
SafeDelete(mTexStorage);
mTexStorage = newCompleteTexStorage;
mDirtyImages = true;
// We do not support managed 3D storage, as that is D3D9/ES2-only
ASSERT(!mTexStorage->isManaged());
}
void Texture3D::updateStorage()
{
ASSERT(mTexStorage != NULL);
GLint storageLevels = mTexStorage->getLevelCount();
for (int level = 0; level < storageLevels; level++)
{
if (mImageArray[level]->isDirty() && isLevelComplete(level))
{
updateStorageLevel(level);
}
}
}
void Texture3D::updateStorageLevel(int level)
{
ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
ASSERT(isLevelComplete(level));
if (mImageArray[level]->isDirty())
{
commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
}
}
bool Texture3D::ensureRenderTarget()
{
initializeStorage(true);
if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0)
{
ASSERT(mTexStorage);
if (!mTexStorage->isRenderTarget())
{
rx::TextureStorageInterface3D *newRenderTargetStorage = createCompleteStorage(true);
if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
{
delete newRenderTargetStorage;
return gl::error(GL_OUT_OF_MEMORY, false);
}
setCompleteTexStorage(newRenderTargetStorage);
}
}
return (mTexStorage && mTexStorage->isRenderTarget());
} }
rx::RenderTarget *Texture3D::getRenderTarget(GLint level) rx::RenderTarget *Texture3D::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 *Texture3D::getRenderTarget(GLint level, GLint layer) rx::RenderTarget *Texture3D::getRenderTarget(GLint level, GLint layer)
{ {
// ensure the underlying texture is created return mTexture->getRenderTarget(level, layer);
if (!ensureRenderTarget())
{
return NULL;
}
updateStorage();
// ensure this is NOT a depth texture
if (isDepth(level))
{
return NULL;
}
return mTexStorage->getRenderTarget(level, layer);
} }
rx::RenderTarget *Texture3D::getDepthStencil(GLint level, GLint layer) rx::RenderTarget *Texture3D::getDepthStencil(GLint level, GLint layer)
{ {
// ensure the underlying texture is created return mTexture->getDepthStencil(level, layer);
if (!ensureRenderTarget())
{
return NULL;
}
updateStorageLevel(level);
// ensure this is a depth texture
if (!isDepth(level))
{
return NULL;
}
return mTexStorage->getRenderTarget(level, layer);
}
void Texture3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
// 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 int storageDepth = std::max(1, getBaseLevelDepth() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false);
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
if ((level >= storageLevels && storageLevels != 0) ||
width != storageWidth ||
height != storageHeight ||
depth != storageDepth ||
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 Texture3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
{
if (isValidLevel(level))
{
rx::ImageD3D *image = rx::ImageD3D::makeImageD3D(mImageArray[level]);
if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth))
{
image->markClean();
}
}
} }
Texture2DArray::Texture2DArray(rx::Renderer *renderer, GLuint id) Texture2DArray::Texture2DArray(rx::Renderer *renderer, GLuint id)
......
...@@ -30,6 +30,7 @@ namespace rx ...@@ -30,6 +30,7 @@ namespace rx
class Renderer; class Renderer;
class Texture2DImpl; class Texture2DImpl;
class TextureCubeImpl; class TextureCubeImpl;
class Texture3DImpl;
class TextureStorageInterface; class TextureStorageInterface;
class TextureStorageInterface3D; class TextureStorageInterface3D;
class TextureStorageInterface2DArray; class TextureStorageInterface2DArray;
...@@ -240,13 +241,18 @@ class TextureCubeMap : public Texture ...@@ -240,13 +241,18 @@ class TextureCubeMap : public Texture
rx::TextureCubeImpl *mTexture; rx::TextureCubeImpl *mTexture;
}; };
class Texture3D : public TextureWithRenderer class Texture3D : public Texture
{ {
public: public:
Texture3D(rx::Renderer *renderer, GLuint id); Texture3D(rx::Texture3DImpl *impl, GLuint id);
~Texture3D(); ~Texture3D();
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;
GLsizei getDepth(GLint level) const; GLsizei getDepth(GLint level) const;
...@@ -278,26 +284,9 @@ class Texture3D : public TextureWithRenderer ...@@ -278,26 +284,9 @@ class Texture3D : public TextureWithRenderer
private: private:
DISALLOW_COPY_AND_ASSIGN(Texture3D); DISALLOW_COPY_AND_ASSIGN(Texture3D);
virtual void initializeStorage(bool renderTarget);
rx::TextureStorageInterface3D *createCompleteStorage(bool renderTarget) const;
void setCompleteTexStorage(rx::TextureStorageInterface3D *newCompleteTexStorage);
virtual void updateStorage();
virtual bool ensureRenderTarget();
virtual rx::TextureStorageInterface *getBaseLevelStorage();
virtual const rx::Image *getBaseLevelImage() const; virtual const rx::Image *getBaseLevelImage() const;
void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); rx::Texture3DImpl *mTexture;
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
bool isValidLevel(int level) const;
bool isLevelComplete(int level) const;
void updateStorageLevel(int level);
rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
rx::TextureStorageInterface3D *mTexStorage;
}; };
class Texture2DArray : public TextureWithRenderer class Texture2DArray : public TextureWithRenderer
......
...@@ -57,9 +57,9 @@ class RenderTarget; ...@@ -57,9 +57,9 @@ class RenderTarget;
class Image; class Image;
class TextureStorage; class TextureStorage;
class UniformStorage; class UniformStorage;
class Texture2DImpl; class Texture2DImpl;
class TextureCubeImpl; class TextureCubeImpl;
class Texture3DImpl;
struct ConfigDesc struct ConfigDesc
{ {
...@@ -231,6 +231,7 @@ class Renderer ...@@ -231,6 +231,7 @@ class Renderer
// Texture creation // Texture creation
virtual Texture2DImpl *createTexture2D() = 0; virtual Texture2DImpl *createTexture2D() = 0;
virtual TextureCubeImpl *createTextureCube() = 0; virtual TextureCubeImpl *createTextureCube() = 0;
virtual Texture3DImpl *createTexture3D() = 0;
// Buffer creation // Buffer creation
virtual BufferImpl *createBuffer() = 0; virtual BufferImpl *createBuffer() = 0;
......
...@@ -99,6 +99,37 @@ class TextureCubeImpl ...@@ -99,6 +99,37 @@ class TextureCubeImpl
virtual RenderTarget *getDepthStencil(GLenum target, GLint level) = 0; virtual RenderTarget *getDepthStencil(GLenum target, GLint level) = 0;
}; };
class Texture3DImpl
{
public:
virtual ~Texture3DImpl() {}
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 bool isMipmapComplete() const = 0;
virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, 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 depth, GLsizei imageSize, const void *pixels) = 0;
virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 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, GLsizei depth) = 0;
virtual void generateMipmaps() = 0;
virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) = 0;
virtual RenderTarget *getRenderTarget(GLint level) = 0;
virtual RenderTarget *getRenderTarget(GLint level, GLint layer) = 0;
virtual RenderTarget *getDepthStencil(GLint level, GLint layer) = 0;
};
} }
#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_ #endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_
...@@ -46,7 +46,7 @@ bool IsRenderTargetUsage(GLenum usage) ...@@ -46,7 +46,7 @@ bool IsRenderTargetUsage(GLenum usage)
return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
} }
TextureD3D::TextureD3D(rx::Renderer *renderer) TextureD3D::TextureD3D(Renderer *renderer)
: mRenderer(renderer), : mRenderer(renderer),
mUsage(GL_NONE), mUsage(GL_NONE),
mDirtyImages(true), mDirtyImages(true),
...@@ -60,19 +60,19 @@ TextureD3D::~TextureD3D() ...@@ -60,19 +60,19 @@ TextureD3D::~TextureD3D()
GLint TextureD3D::getBaseLevelWidth() const GLint TextureD3D::getBaseLevelWidth() const
{ {
const rx::Image *baseImage = getBaseLevelImage(); const Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getWidth() : 0); return (baseImage ? baseImage->getWidth() : 0);
} }
GLint TextureD3D::getBaseLevelHeight() const GLint TextureD3D::getBaseLevelHeight() const
{ {
const rx::Image *baseImage = getBaseLevelImage(); const Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getHeight() : 0); return (baseImage ? baseImage->getHeight() : 0);
} }
GLint TextureD3D::getBaseLevelDepth() const GLint TextureD3D::getBaseLevelDepth() const
{ {
const rx::Image *baseImage = getBaseLevelImage(); const Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getDepth() : 0); return (baseImage ? baseImage->getDepth() : 0);
} }
...@@ -81,11 +81,11 @@ GLint TextureD3D::getBaseLevelDepth() const ...@@ -81,11 +81,11 @@ GLint TextureD3D::getBaseLevelDepth() const
// the base level image for anything except querying texture format and size. // the base level image for anything except querying texture format and size.
GLenum TextureD3D::getBaseLevelInternalFormat() const GLenum TextureD3D::getBaseLevelInternalFormat() const
{ {
const rx::Image *baseImage = getBaseLevelImage(); const Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getInternalFormat() : GL_NONE); return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
} }
void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image) void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, 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)
...@@ -116,7 +116,7 @@ void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const ...@@ -116,7 +116,7 @@ void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const
} }
bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, 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) GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, Image *image)
{ {
const void *pixelData = pixels; const void *pixelData = pixels;
...@@ -140,7 +140,7 @@ bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei w ...@@ -140,7 +140,7 @@ bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei w
return true; return true;
} }
void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image) void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
{ {
if (pixels != NULL) if (pixels != NULL)
{ {
...@@ -150,7 +150,7 @@ void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, rx::I ...@@ -150,7 +150,7 @@ void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, rx::I
} }
bool TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, 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) GLenum format, GLsizei imageSize, const void *pixels, Image *image)
{ {
if (pixels != NULL) if (pixels != NULL)
{ {
...@@ -167,7 +167,7 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz ...@@ -167,7 +167,7 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz
} }
bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget) GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget)
{ {
if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
{ {
...@@ -203,7 +203,7 @@ int TextureD3D::mipLevels() const ...@@ -203,7 +203,7 @@ int TextureD3D::mipLevels() const
} }
TextureD3D_2D::TextureD3D_2D(rx::Renderer *renderer) TextureD3D_2D::TextureD3D_2D(Renderer *renderer)
: TextureD3D(renderer), : TextureD3D(renderer),
Texture2DImpl(), Texture2DImpl(),
mTexStorage(NULL) mTexStorage(NULL)
...@@ -235,7 +235,7 @@ TextureStorageInterface *TextureD3D_2D::getNativeTexture() ...@@ -235,7 +235,7 @@ TextureStorageInterface *TextureD3D_2D::getNativeTexture()
// ensure the underlying texture is created // ensure the underlying texture is created
initializeStorage(false); initializeStorage(false);
rx::TextureStorageInterface *storage = getBaseLevelStorage(); TextureStorageInterface *storage = getBaseLevelStorage();
if (storage) if (storage)
{ {
updateStorage(); updateStorage();
...@@ -307,7 +307,7 @@ void TextureD3D_2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum ...@@ -307,7 +307,7 @@ void TextureD3D_2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum
if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
{ {
// Will try to create RT storage if it does not exist // Will try to create RT storage if it does not exist
rx::RenderTarget *destRenderTarget = getRenderTarget(level); RenderTarget *destRenderTarget = getRenderTarget(level);
gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
...@@ -336,7 +336,7 @@ void TextureD3D_2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei ...@@ -336,7 +336,7 @@ void TextureD3D_2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei
if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
{ {
rx::RenderTarget *renderTarget = getRenderTarget(level); RenderTarget *renderTarget = getRenderTarget(level);
gl::Box destArea(xoffset, yoffset, 0, width, height, 1); gl::Box destArea(xoffset, yoffset, 0, width, height, 1);
if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget)) if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget))
...@@ -435,7 +435,7 @@ void TextureD3D_2D::storage(GLsizei levels, GLenum internalformat, GLsizei width ...@@ -435,7 +435,7 @@ void TextureD3D_2D::storage(GLsizei levels, GLenum internalformat, GLsizei width
mImmutable = true; mImmutable = true;
setCompleteTexStorage(new rx::TextureStorageInterface2D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, levels)); setCompleteTexStorage(new 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. // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
...@@ -516,7 +516,7 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface) ...@@ -516,7 +516,7 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface)
{ {
SafeDelete(mTexStorage); SafeDelete(mTexStorage);
} }
mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain()); mTexStorage = new TextureStorageInterface2D(mRenderer, surface->getSwapChain());
mDirtyImages = true; mDirtyImages = true;
} }
...@@ -627,7 +627,7 @@ bool TextureD3D_2D::isLevelComplete(int level) const ...@@ -627,7 +627,7 @@ bool TextureD3D_2D::isLevelComplete(int level) const
return true; return true;
} }
const rx::Image *baseImage = getBaseLevelImage(); const Image *baseImage = getBaseLevelImage();
GLsizei width = baseImage->getWidth(); GLsizei width = baseImage->getWidth();
GLsizei height = baseImage->getHeight(); GLsizei height = baseImage->getHeight();
...@@ -644,7 +644,7 @@ bool TextureD3D_2D::isLevelComplete(int level) const ...@@ -644,7 +644,7 @@ bool TextureD3D_2D::isLevelComplete(int level) const
} }
ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
rx::Image *image = mImageArray[level]; ImageD3D *image = mImageArray[level];
if (image->getInternalFormat() != baseImage->getInternalFormat()) if (image->getInternalFormat() != baseImage->getInternalFormat())
{ {
...@@ -688,7 +688,7 @@ void TextureD3D_2D::initializeStorage(bool renderTarget) ...@@ -688,7 +688,7 @@ void TextureD3D_2D::initializeStorage(bool renderTarget)
updateStorage(); updateStorage();
} }
rx::TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderTarget) const TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderTarget) const
{ {
GLsizei width = getBaseLevelWidth(); GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight(); GLsizei height = getBaseLevelHeight();
...@@ -698,7 +698,7 @@ rx::TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderT ...@@ -698,7 +698,7 @@ rx::TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderT
// use existing storage level count, when previously specified by TexStorage*D // use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
return new rx::TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels); return new TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels);
} }
void TextureD3D_2D::setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage) void TextureD3D_2D::setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage)
...@@ -739,7 +739,7 @@ bool TextureD3D_2D::ensureRenderTarget() ...@@ -739,7 +739,7 @@ bool TextureD3D_2D::ensureRenderTarget()
ASSERT(mTexStorage); ASSERT(mTexStorage);
if (!mTexStorage->isRenderTarget()) if (!mTexStorage->isRenderTarget())
{ {
rx::TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true); TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true);
if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
{ {
...@@ -808,7 +808,7 @@ void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsize ...@@ -808,7 +808,7 @@ void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsize
{ {
if (isValidLevel(level)) if (isValidLevel(level))
{ {
rx::ImageD3D *image = mImageArray[level]; ImageD3D *image = mImageArray[level];
if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height)) if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height))
{ {
image->markClean(); image->markClean();
...@@ -817,7 +817,7 @@ void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsize ...@@ -817,7 +817,7 @@ void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsize
} }
TextureD3D_Cube::TextureD3D_Cube(rx::Renderer *renderer) TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer)
: TextureCubeImpl(), : TextureCubeImpl(),
TextureD3D(renderer), TextureD3D(renderer),
mTexStorage(NULL) mTexStorage(NULL)
...@@ -855,7 +855,7 @@ TextureStorageInterface *TextureD3D_Cube::getNativeTexture() ...@@ -855,7 +855,7 @@ TextureStorageInterface *TextureD3D_Cube::getNativeTexture()
// ensure the underlying texture is created // ensure the underlying texture is created
initializeStorage(false); initializeStorage(false);
rx::TextureStorageInterface *storage = getBaseLevelStorage(); TextureStorageInterface *storage = getBaseLevelStorage();
if (storage) if (storage)
{ {
updateStorage(); updateStorage();
...@@ -1017,7 +1017,7 @@ void TextureD3D_Cube::storage(GLsizei levels, GLenum internalformat, GLsizei siz ...@@ -1017,7 +1017,7 @@ void TextureD3D_Cube::storage(GLsizei levels, GLenum internalformat, GLsizei siz
mImmutable = true; mImmutable = true;
setCompleteTexStorage(new rx::TextureStorageInterfaceCube(mRenderer, internalformat, IsRenderTargetUsage(mUsage), size, levels)); setCompleteTexStorage(new TextureStorageInterfaceCube(mRenderer, internalformat, IsRenderTargetUsage(mUsage), size, levels));
} }
bool TextureD3D_Cube::isSamplerComplete(const gl::SamplerState &samplerState) const bool TextureD3D_Cube::isSamplerComplete(const gl::SamplerState &samplerState) const
...@@ -1419,4 +1419,559 @@ void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLin ...@@ -1419,4 +1419,559 @@ void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLin
} }
} }
}
\ No newline at end of file TextureD3D_3D::TextureD3D_3D(Renderer *renderer)
: Texture3DImpl(),
TextureD3D(renderer),
mTexStorage(NULL)
{
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage());
}
}
TextureD3D_3D::~TextureD3D_3D()
{
SafeDelete(mTexStorage);
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
delete mImageArray[i];
}
}
TextureD3D_3D *TextureD3D_3D::makeTextureD3D_3D(Texture3DImpl *texture)
{
ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_3D*, texture));
return static_cast<TextureD3D_3D*>(texture);
}
TextureStorageInterface *TextureD3D_3D::getNativeTexture()
{
// ensure the underlying texture is created
initializeStorage(false);
TextureStorageInterface *storage = getBaseLevelStorage();
if (storage)
{
updateStorage();
}
return storage;
}
Image *TextureD3D_3D::getImage(int level) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
return mImageArray[level];
}
void TextureD3D_3D::setUsage(GLenum usage)
{
mUsage = usage;
}
void TextureD3D_3D::resetDirty()
{
mDirtyImages = false;
}
GLsizei TextureD3D_3D::getWidth(GLint level) const
{
if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getWidth();
else
return 0;
}
GLsizei TextureD3D_3D::getHeight(GLint level) const
{
if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getHeight();
else
return 0;
}
GLsizei TextureD3D_3D::getDepth(GLint level) const
{
if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getDepth();
else
return 0;
}
GLenum TextureD3D_3D::getInternalFormat(GLint level) const
{
if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mImageArray[level]->getInternalFormat();
else
return GL_NONE;
}
bool TextureD3D_3D::isDepth(GLint level) const
{
return gl::GetDepthBits(getInternalFormat(level)) > 0;
}
void TextureD3D_3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
{
GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat
: gl::GetSizedInternalFormat(format, type);
redefineImage(level, sizedInternalFormat, width, height, depth);
bool fastUnpacked = false;
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
if (isFastUnpackable(unpack, sizedInternalFormat))
{
// Will try to create RT storage if it does not exist
RenderTarget *destRenderTarget = getRenderTarget(level);
gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
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_3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
{
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
redefineImage(level, format, width, height, depth);
TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]);
}
void TextureD3D_3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
{
bool fastUnpacked = false;
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
if (isFastUnpackable(unpack, getInternalFormat(level)))
{
RenderTarget *destRenderTarget = getRenderTarget(level);
gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth);
if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget))
{
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
fastUnpacked = true;
}
}
if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level]))
{
commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
}
}
void TextureD3D_3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
{
if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level]))
{
commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
}
}
void TextureD3D_3D::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, zoffset, 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, zoffset, mTexStorage, level);
}
}
}
void TextureD3D_3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
for (int level = 0; level < levels; level++)
{
GLsizei levelWidth = std::max(1, width >> level);
GLsizei levelHeight = std::max(1, height >> level);
GLsizei levelDepth = std::max(1, depth >> level);
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true);
}
for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true);
}
mImmutable = true;
setCompleteTexStorage(new TextureStorageInterface3D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels));
}
bool TextureD3D_3D::isSamplerComplete(const gl::SamplerState &samplerState) const
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei depth = getBaseLevelDepth();
if (width <= 0 || height <= 0 || depth <= 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;
}
}
if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
{
return false;
}
return true;
}
bool TextureD3D_3D::isMipmapComplete() const
{
int levelCount = mipLevels();
for (int level = 0; level < levelCount; level++)
{
if (!isLevelComplete(level))
{
return false;
}
}
return true;
}
void TextureD3D_3D::generateMipmaps()
{
// Purge array levels 1 through q and reset them to represent the generated mipmap levels.
int levelCount = mipLevels();
for (int level = 1; level < levelCount; level++)
{
redefineImage(level, getBaseLevelInternalFormat(),
std::max(getBaseLevelWidth() >> level, 1),
std::max(getBaseLevelHeight() >> level, 1),
std::max(getBaseLevelDepth() >> level, 1));
}
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_3D::getRenderTargetSerial(GLint level, GLint layer)
{
return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0);
}
RenderTarget *TextureD3D_3D::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_3D::getRenderTarget(GLint level, GLint layer)
{
// ensure the underlying texture is created
if (!ensureRenderTarget())
{
return NULL;
}
updateStorage();
// ensure this is NOT a depth texture
if (isDepth(level))
{
return NULL;
}
return mTexStorage->getRenderTarget(level, layer);
}
RenderTarget *TextureD3D_3D::getDepthStencil(GLint level, GLint layer)
{
// ensure the underlying texture is created
if (!ensureRenderTarget())
{
return NULL;
}
updateStorageLevel(level);
// ensure this is a depth texture
if (!isDepth(level))
{
return NULL;
}
return mTexStorage->getRenderTarget(level, layer);
}
void TextureD3D_3D::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 || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
setCompleteTexStorage(createCompleteStorage(createRenderTarget));
ASSERT(mTexStorage);
// flush image data to the storage
updateStorage();
}
TextureStorageInterface3D *TextureD3D_3D::createCompleteStorage(bool renderTarget) const
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei depth = getBaseLevelDepth();
ASSERT(width > 0 && height > 0 && depth > 0);
// use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
return new TextureStorageInterface3D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels);
}
void TextureD3D_3D::setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage)
{
SafeDelete(mTexStorage);
mTexStorage = newCompleteTexStorage;
mDirtyImages = true;
// We do not support managed 3D storage, as that is D3D9/ES2-only
ASSERT(!mTexStorage->isManaged());
}
void TextureD3D_3D::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_3D::ensureRenderTarget()
{
initializeStorage(true);
if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0)
{
ASSERT(mTexStorage);
if (!mTexStorage->isRenderTarget())
{
TextureStorageInterface3D *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_3D::getBaseLevelStorage()
{
return mTexStorage;
}
const ImageD3D *TextureD3D_3D::getBaseLevelImage() const
{
return mImageArray[0];
}
bool TextureD3D_3D::isValidLevel(int level) const
{
return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
}
bool TextureD3D_3D::isLevelComplete(int level) const
{
ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
if (isImmutable())
{
return true;
}
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei depth = getBaseLevelDepth();
if (width <= 0 || height <= 0 || depth <= 0)
{
return false;
}
if (level == 0)
{
return true;
}
ImageD3D *levelImage = mImageArray[level];
if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
{
return false;
}
if (levelImage->getWidth() != std::max(1, width >> level))
{
return false;
}
if (levelImage->getHeight() != std::max(1, height >> level))
{
return false;
}
if (levelImage->getDepth() != std::max(1, depth >> level))
{
return false;
}
return true;
}
void TextureD3D_3D::updateStorageLevel(int level)
{
ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
ASSERT(isLevelComplete(level));
if (mImageArray[level]->isDirty())
{
commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
}
}
void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
// 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 int storageDepth = std::max(1, getBaseLevelDepth() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false);
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
if ((level >= storageLevels && storageLevels != 0) ||
width != storageWidth ||
height != storageHeight ||
depth != storageDepth ||
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_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
{
if (isValidLevel(level))
{
ImageD3D *image = mImageArray[level];
if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth))
{
image->markClean();
}
}
}
}
...@@ -27,11 +27,12 @@ class Renderer; ...@@ -27,11 +27,12 @@ class Renderer;
class TextureStorageInterface; class TextureStorageInterface;
class TextureStorageInterface2D; class TextureStorageInterface2D;
class TextureStorageInterfaceCube; class TextureStorageInterfaceCube;
class TextureStorageInterface3D;
class TextureD3D class TextureD3D
{ {
public: public:
TextureD3D(rx::Renderer *renderer); TextureD3D(Renderer *renderer);
virtual ~TextureD3D(); virtual ~TextureD3D();
GLint getBaseLevelWidth() const; GLint getBaseLevelWidth() const;
...@@ -42,15 +43,15 @@ class TextureD3D ...@@ -42,15 +43,15 @@ class TextureD3D
bool isImmutable() const { return mImmutable; } bool isImmutable() const { return mImmutable; }
protected: protected:
void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image); void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, 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 gl::PixelUnpackState &unpack, const void *pixels, rx::Image *image); GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, Image *image);
void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image); void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, bool 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, Image *image);
bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat);
bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget); GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget);
GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
int mipLevels() const; int mipLevels() const;
...@@ -73,7 +74,7 @@ class TextureD3D ...@@ -73,7 +74,7 @@ class TextureD3D
class TextureD3D_2D : public Texture2DImpl, public TextureD3D class TextureD3D_2D : public Texture2DImpl, public TextureD3D
{ {
public: public:
TextureD3D_2D(rx::Renderer *renderer); TextureD3D_2D(Renderer *renderer);
virtual ~TextureD3D_2D(); virtual ~TextureD3D_2D();
static TextureD3D_2D *makeTextureD3D_2D(Texture2DImpl *texture); static TextureD3D_2D *makeTextureD3D_2D(Texture2DImpl *texture);
...@@ -139,7 +140,7 @@ class TextureD3D_2D : public Texture2DImpl, public TextureD3D ...@@ -139,7 +140,7 @@ class TextureD3D_2D : public Texture2DImpl, public TextureD3D
class TextureD3D_Cube : public TextureCubeImpl, public TextureD3D class TextureD3D_Cube : public TextureCubeImpl, public TextureD3D
{ {
public: public:
TextureD3D_Cube(rx::Renderer *renderer); TextureD3D_Cube(Renderer *renderer);
virtual ~TextureD3D_Cube(); virtual ~TextureD3D_Cube();
static TextureD3D_Cube *makeTextureD3D_Cube(TextureCubeImpl *texture); static TextureD3D_Cube *makeTextureD3D_Cube(TextureCubeImpl *texture);
...@@ -200,6 +201,70 @@ class TextureD3D_Cube : public TextureCubeImpl, public TextureD3D ...@@ -200,6 +201,70 @@ class TextureD3D_Cube : public TextureCubeImpl, public TextureD3D
TextureStorageInterfaceCube *mTexStorage; TextureStorageInterfaceCube *mTexStorage;
}; };
class TextureD3D_3D : public Texture3DImpl, public TextureD3D
{
public:
TextureD3D_3D(Renderer *renderer);
virtual ~TextureD3D_3D();
static TextureD3D_3D *makeTextureD3D_3D(Texture3DImpl *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;
GLsizei getDepth(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isDepth(GLint level) const;
virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, 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 depth, GLsizei imageSize, const void *pixels);
virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
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, GLsizei depth);
virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const;
virtual bool isMipmapComplete() const;
virtual void generateMipmaps();
virtual unsigned int getRenderTargetSerial(GLint level, GLint layer);
virtual RenderTarget *getRenderTarget(GLint level);
virtual RenderTarget *getRenderTarget(GLint level, GLint layer);
virtual RenderTarget *getDepthStencil(GLint level, GLint layer);
private:
DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D);
virtual void initializeStorage(bool renderTarget);
TextureStorageInterface3D *createCompleteStorage(bool renderTarget) const;
void setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage);
void updateStorage();
bool ensureRenderTarget();
virtual TextureStorageInterface *getBaseLevelStorage();
virtual const ImageD3D *getBaseLevelImage() 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, GLsizei depth);
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
TextureStorageInterface3D *mTexStorage;
};
} }
#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_ #endif // LIBGLESV2_RENDERER_TEXTURED3D_H_
...@@ -2911,6 +2911,11 @@ TextureCubeImpl *Renderer11::createTextureCube() ...@@ -2911,6 +2911,11 @@ TextureCubeImpl *Renderer11::createTextureCube()
return new TextureD3D_Cube(this); return new TextureD3D_Cube(this);
} }
Texture3DImpl *Renderer11::createTexture3D()
{
return new TextureD3D_3D(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)
{ {
......
...@@ -180,6 +180,7 @@ class Renderer11 : public Renderer ...@@ -180,6 +180,7 @@ class Renderer11 : public Renderer
// Texture creation // Texture creation
virtual Texture2DImpl *createTexture2D(); virtual Texture2DImpl *createTexture2D();
virtual TextureCubeImpl *createTextureCube(); virtual TextureCubeImpl *createTextureCube();
virtual Texture3DImpl *createTexture3D();
// Buffer creation // Buffer creation
virtual BufferImpl *createBuffer(); virtual BufferImpl *createBuffer();
......
...@@ -3204,6 +3204,11 @@ TextureCubeImpl *Renderer9::createTextureCube() ...@@ -3204,6 +3204,11 @@ TextureCubeImpl *Renderer9::createTextureCube()
return new TextureD3D_Cube(this); return new TextureD3D_Cube(this);
} }
Texture3DImpl *Renderer9::createTexture3D()
{
return new TextureD3D_3D(this);
}
bool Renderer9::getLUID(LUID *adapterLuid) const bool Renderer9::getLUID(LUID *adapterLuid) const
{ {
adapterLuid->HighPart = 0; adapterLuid->HighPart = 0;
......
...@@ -182,6 +182,7 @@ class Renderer9 : public Renderer ...@@ -182,6 +182,7 @@ class Renderer9 : public Renderer
// Texture creation // Texture creation
virtual Texture2DImpl *createTexture2D(); virtual Texture2DImpl *createTexture2D();
virtual TextureCubeImpl *createTextureCube(); virtual TextureCubeImpl *createTextureCube();
virtual Texture3DImpl *createTexture3D();
// Buffer creation // Buffer creation
virtual BufferImpl *createBuffer(); virtual BufferImpl *createBuffer();
......
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