From 1e84f260a9f59b63341deb15734d2de402e92cc6 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 21 Jan 2015 16:53:35 -0800 Subject: [PATCH] Removing gl calls for texture from TextureCache --- libraries/fbx/src/FBXReader.cpp | 3 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 12 +- libraries/gpu/src/gpu/Texture.cpp | 146 +++++++++++++------- libraries/gpu/src/gpu/Texture.h | 79 +++++------ libraries/render-utils/src/TextureCache.cpp | 83 ++--------- libraries/render-utils/src/TextureCache.h | 17 +-- 6 files changed, 167 insertions(+), 173 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 3015de52ff..89a46f2be9 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -272,7 +272,8 @@ FBXNode parseBinaryFBXNode(QDataStream& in, int& position) { position += nameLength; for (quint32 i = 0; i < propertyCount; i++) { - node.properties.append(parseBinaryFBXProperty(in, position)); + QVariant var = parseBinaryFBXProperty(in, position); + node.properties.append(var); } while (endOffset > position) { diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index e23f6fdaec..5fa33a4210 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -215,6 +215,9 @@ void GLBackend::syncGPUObject(const Texture& texture) { // Need to update the content of the GPU object from the source sysmem of the texture needUpdate = true; } + } else if (!texture.isDefined()) { + // NO texture definition yet so let's avoid thinking + return; } // need to have a gpu object? @@ -224,6 +227,7 @@ void GLBackend::syncGPUObject(const Texture& texture) { CHECK_GL_ERROR(); Backend::setGPUObject(texture, object); } + // GO through the process of allocating the correct storage and/or update the content switch (texture.getType()) { case Texture::TEX_2D: { @@ -292,5 +296,11 @@ void GLBackend::syncGPUObject(const Texture& texture) { GLuint GLBackend::getTextureID(const Texture& texture) { GLBackend::syncGPUObject(texture); - return Backend::getGPUObject(texture)->_texture; + GLTexture* object = Backend::getGPUObject(texture); + if (object) { + return object->_texture; + } else { + return 0; + } } + diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 5a52529403..a608e74dd1 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -23,6 +23,63 @@ Texture::Pixels::Pixels(const Element& format, Size size, const Byte* bytes) : Texture::Pixels::~Pixels() { } +Stamp Texture::Storage::getStamp(uint16 level) const { + PixelsPointer mip = getMip(level); + if (mip) { + return mip->_sysmem.getStamp(); + } else { + return 0; + } +} + +void Texture::Storage::reset() { + _mips.clear(); +} + +Texture::PixelsPointer Texture::Storage::editMip(uint16 level) { + if (level > _mips.size()) { + return PixelsPointer(); + } else { + return _mips[level]; + } +} + +const Texture::PixelsPointer Texture::Storage::getMip(uint16 level) const { + if (level > _mips.size()) { + return PixelsPointer(); + } else { + return _mips[level]; + } +} + +bool Texture::Storage::isMipAvailable(uint16 level) const { + PixelsPointer mip = getMip(level); + return (mip && mip->_sysmem.getSize()); +} + +bool Texture::Storage::allocateMip(uint16 level) { + bool changed = false; + if (level >= _mips.size()) { + _mips.resize(level+1, PixelsPointer()); + changed = true; + } + + if (!_mips[level]) { + _mips[level] = PixelsPointer(new Pixels()); + changed = true; + } + + return changed; +} + +bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes) { + // Ok we should be able to do that... + allocateMip(level); + _mips[level]->_format = format; + Size allocated = _mips[level]->_sysmem.setData(size, bytes); + return allocated == size; +} + Texture* Texture::create1D(const Element& texelFormat, uint16 width) { return create(TEX_1D, texelFormat, width, 1, 1, 1, 1); } @@ -42,17 +99,25 @@ Texture* Texture::createCube(const Element& texelFormat, uint16 width) { Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) { Texture* tex = new Texture(); - + tex->_storage.reset(new Storage()); + tex->_storage->_texture = tex; tex->_type = type; - tex->_texelFormat = texelFormat; tex->_maxMip = 0; - tex->resize(type, width, height, depth, numSamples, numSlices); + tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices); return tex; } +Texture* Texture::createFromStorage(Storage* storage) { + Texture* tex = new Texture(); + tex->_storage.reset(storage); + storage->_texture = tex; + return tex; +} + Texture::Texture(): Resource(), + _storage(), _stamp(0), _size(0), _width(1), @@ -61,7 +126,9 @@ Texture::Texture(): _numSamples(1), _numSlices(1), _maxMip(0), - _autoGenerateMips(false) + _type(TEX_1D), + _autoGenerateMips(false), + _defined(false) { } @@ -69,10 +136,15 @@ Texture::~Texture() { } -Texture::Size Texture::resize(Type type, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) { +Texture::Size Texture::resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) { if (width && height && depth && numSamples && numSlices) { bool changed = false; + if ( _type != type) { + _type = type; + changed = true; + } + if (_numSlices != numSlices) { _numSlices = numSlices; changed = true; @@ -100,50 +172,47 @@ Texture::Size Texture::resize(Type type, uint16 width, uint16 height, uint16 dep changed = true; } + // Evaluate the new size with the new format const int DIM_SIZE[] = {1, 1, 1, 6}; - int size = DIM_SIZE[_type] *_width * _height * _depth * _numSamples * _texelFormat.getSize(); + int size = DIM_SIZE[_type] *_width * _height * _depth * _numSamples * texelFormat.getSize(); + // If size change then we need to reset if (changed || (size != getSize())) { _size = size; - _mips.clear(); + _storage->reset(); _stamp++; - } + } + + // TexelFormat might have change, but it's mostly interpretation + if (texelFormat != _texelFormat) { + _texelFormat = texelFormat; + _stamp++; + } + + // Here the Texture has been fully defined from the gpu point of view (size and format) + _defined = true; + } else { + _stamp++; } return _size; } Texture::Size Texture::resize1D(uint16 width, uint16 numSamples) { - return resize(TEX_1D, width, 1, 1, numSamples, 1); + return resize(TEX_1D, getTexelFormat(), width, 1, 1, numSamples, 1); } Texture::Size Texture::resize2D(uint16 width, uint16 height, uint16 numSamples) { - return resize(TEX_2D, width, height, 1, numSamples, 1); + return resize(TEX_2D, getTexelFormat(), width, height, 1, numSamples, 1); } Texture::Size Texture::resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples) { - return resize(TEX_3D, width, height, depth, numSamples, 1); + return resize(TEX_3D, getTexelFormat(), width, height, depth, numSamples, 1); } Texture::Size Texture::resizeCube(uint16 width, uint16 numSamples) { - return resize(TEX_CUBE, width, 1, 1, numSamples, 1); + return resize(TEX_CUBE, getTexelFormat(), width, 1, 1, numSamples, 1); } - -// Reformat, unless auto mips mode would destroy all the sub mips Texture::Size Texture::reformat(const Element& texelFormat) { - if (texelFormat != _texelFormat) { - - _texelFormat = texelFormat; - - const int DIM_SIZE[] = {1, 1, 1, 6}; - int size = DIM_SIZE[_type] * _width * _height * _depth * _numSamples * _texelFormat.getSize(); - - if (size != getSize()) { - _size = size; - _mips.clear(); - } - _stamp++; - } - - return _size; + return resize(_type, texelFormat, getWidth(), getHeight(), getDepth(), getNumSamples(), getNumSlices()); } bool Texture::isColorRenderTarget() const { @@ -172,19 +241,6 @@ uint16 Texture::maxMip() const { return _maxMip; } -void Texture::allocateStoredMip(uint16 level) { - if (level >= _mips.size()) { - _mips.resize(level+1, 0); - _maxMip = level; - _stamp++; - } - - if (!_mips[level]) { - _mips[level] = PixelsPointer(new Pixels()); - _stamp++; - } -} - bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes) { // Check that level accessed make sense if (level != 0) { @@ -198,12 +254,8 @@ bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, co // THen check that the mem buffer passed make sense with its format if (size == evalStoredMipSize(level, format)) { - // Ok we should be able to do that... - allocateStoredMip(level); - _mips[level]->_format = format; - _mips[level]->_sysmem.setData(size, bytes); + _storage->assignMipData(level, format, size, bytes); _stamp++; - return true; } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index e9a6afe0f2..8da500b444 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -31,6 +31,24 @@ public: }; typedef QSharedPointer< Pixels > PixelsPointer; + class Storage { + Texture* _texture; + std::vector _mips; + public: + + Storage() {} + virtual ~Storage() {} + virtual void reset(); + virtual PixelsPointer editMip(uint16 level); + virtual const PixelsPointer getMip(uint16 level) const; + virtual Stamp getStamp(uint16 level) const; + virtual bool allocateMip(uint16 level); + virtual bool assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes); + virtual bool isMipAvailable(uint16 level) const; + + friend class Texture; + }; + enum Type { TEX_1D = 0, TEX_2D, @@ -43,18 +61,14 @@ public: static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth); static Texture* createCube(const Element& texelFormat, uint16 width); + static Texture* createFromStorage(Storage* storage); + Texture(const Texture& buf); // deep copy of the sysmem texture Texture& operator=(const Texture& buf); // deep copy of the sysmem texture ~Texture(); const Stamp getStamp() const { return _stamp; } - const Stamp getDataStamp(uint16 level = 0) const { - PixelsPointer mip = accessStoredMip(level); - if (mip) { - return mip->_sysmem.getStamp(); - } - return getStamp(); - } + const Stamp getDataStamp(uint16 level = 0) const { return _storage->getStamp(level); } // The size in bytes of data stored in the texture Size getSize() const { return _size; } @@ -87,7 +101,10 @@ public: uint16 getNumSlices() const { return _numSlices; } uint16 getNumSamples() const { return _numSamples; } - // Sub Mips manipulation + // NumSamples can only have certain values based on the hw + static uint16 evalNumSamplesUsed(uint16 numSamplesTried); + + // Mips size evaluation // The number mips that a dimension could haves // = 1 + log2(size) @@ -116,7 +133,6 @@ public: return size * getNumSlices(); } - // max mip is in the range [ 1 if no sub mips, log2(max(width, height, depth))] // if autoGenerateMip is on => will provide the maxMIp level specified // else provide the deepest mip level provided through assignMip @@ -137,6 +153,8 @@ public: uint16 autoGenerateMips(uint16 maxMip); bool isAutogenerateMips() const { return _autoGenerateMips; } + // Managing Storage and mips + // Manually allocate the mips down until the specified maxMip // this is just allocating the sysmem version of it // in case autoGen is on, this doesn't allocate @@ -144,35 +162,21 @@ public: // If Bytes is NULL then simply allocate the space so mip sysmem can be accessed bool assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes); - bool isStoredMipAvailable(uint16 level) const { - const PixelsPointer mip = accessStoredMip(level); - if (mip) { - return mip->_sysmem.isAvailable(); - } - return false; - } - // Access the the sub mips - const PixelsPointer Texture::accessStoredMip(uint16 level) const { - if (level > _mips.size()) { - return 0; - } else { - return _mips[level]; - } - } - + // Access the the sub mips + bool isStoredMipAvailable(uint16 level) const { return _storage->isMipAvailable(level); } + const PixelsPointer accessStoredMip(uint16 level) const { return _storage->getMip(level); } + // access sizes for the stored mips uint16 getStoredMipWidth(uint16 level) const; uint16 getStoredMipHeight(uint16 level) const; uint16 getStoredMipDepth(uint16 level) const; uint32 getStoredMipNumTexels(uint16 level) const; uint32 getStoredMipSize(uint16 level) const; - - - static uint16 evalNumSamplesUsed(uint16 numSamplesTried); + + bool isDefined() const { return _defined; } protected: - - std::vector _mips; + std::unique_ptr< Storage > _storage; Stamp _stamp; @@ -190,23 +194,12 @@ protected: Type _type; bool _autoGenerateMips; - + bool _defined; static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); Texture(); - Size resize(Type type, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); - - void allocateStoredMip(uint16 level); - - // Access the the sub mips - PixelsPointer Texture::accessStoredMip(uint16 level) { - if (level > _mips.size()) { - return 0; - } else { - return _mips[level]; - } - } + Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); mutable GPUObject* _gpuObject = NULL; diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index c8bb936b27..07f3ad6924 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -26,9 +26,7 @@ #include "TextureCache.h" TextureCache::TextureCache() : - _permutationNormalTextureID(0), - _whiteTextureID(0), - _blueTextureID(0), + _permutationNormalTexture(0), _whiteTexture(0), _blueTexture(0), _primaryDepthTextureID(0), @@ -46,12 +44,7 @@ TextureCache::TextureCache() : } TextureCache::~TextureCache() { - if (_permutationNormalTextureID != 0) { - glDeleteTextures(1, &_permutationNormalTextureID); - } - if (_whiteTextureID != 0) { - glDeleteTextures(1, &_whiteTextureID); - } + if (_primaryFramebufferObject) { glDeleteTextures(1, &_primaryDepthTextureID); glDeleteTextures(1, &_primaryNormalTextureID); @@ -126,11 +119,9 @@ const int permutation[256] = #define USE_CHRIS_NOISE 1 -GLuint TextureCache::getPermutationNormalTextureID() { - if (_permutationNormalTextureID == 0) { - glGenTextures(1, &_permutationNormalTextureID); - glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID); - +const gpu::TexturePointer& TextureCache::getPermutationNormalTexture() { + if (_permutationNormalTexture.isNull()) { + // the first line consists of random permutation offsets unsigned char data[256 * 2 * 3]; #if (USE_CHRIS_NOISE==1) @@ -150,12 +141,14 @@ GLuint TextureCache::getPermutationNormalTextureID() { data[i + 1] = ((randvec.y + 1.0f) / 2.0f) * 255.0f; data[i + 2] = ((randvec.z + 1.0f) / 2.0f) * 255.0f; } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); + + _permutationNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), 256, 2)); + _permutationNormalTexture->assignStoredMip(0, _blueTexture->getTexelFormat(), sizeof(data), data); + + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } - return _permutationNormalTextureID; + return _permutationNormalTexture; } const unsigned char OPAQUE_WHITE[] = { 0xFF, 0xFF, 0xFF, 0xFF }; @@ -167,17 +160,7 @@ static void loadSingleColorTexture(const unsigned char* color) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, color); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } -/* -GLuint TextureCache::getWhiteTextureID() { - if (_whiteTextureID == 0) { - glGenTextures(1, &_whiteTextureID); - glBindTexture(GL_TEXTURE_2D, _whiteTextureID); - loadSingleColorTexture(OPAQUE_WHITE); - glBindTexture(GL_TEXTURE_2D, 0); - } - return _whiteTextureID; -} -*/ + const gpu::TexturePointer& TextureCache::getWhiteTexture() { if (_whiteTexture.isNull()) { _whiteTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA), 1, 1)); @@ -185,17 +168,6 @@ const gpu::TexturePointer& TextureCache::getWhiteTexture() { } return _whiteTexture; } -/* -GLuint TextureCache::getBlueTextureID() { - if (_blueTextureID == 0) { - glGenTextures(1, &_blueTextureID); - glBindTexture(GL_TEXTURE_2D, _blueTextureID); - loadSingleColorTexture(OPAQUE_BLUE); - glBindTexture(GL_TEXTURE_2D, 0); - } - return _blueTextureID; -} -*/ const gpu::TexturePointer& TextureCache::getBlueTexture() { if (_blueTexture.isNull()) { @@ -554,19 +526,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo finishedLoading(true); imageLoaded(image); - /* glBindTexture(GL_TEXTURE_2D, getID()); - if (image.hasAlphaChannel()) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, - GL_BGRA, GL_UNSIGNED_BYTE, image.constBits()); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, - GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); - } - // generate mipmaps - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - */ + if (image.hasAlphaChannel()) { _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA), image.width(), image.height())); _gpuTexture->assignStoredMip(0, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::BGRA), image.byteCount(), image.constBits()); @@ -603,20 +563,7 @@ QSharedPointer DilatableNetworkTexture::getDilatedTexture(float dilatio path.addEllipse(QPointF(_image.width() / 2.0, _image.height() / 2.0), radius, radius); painter.fillPath(path, Qt::black); painter.end(); - - /* - glBindTexture(GL_TEXTURE_2D, texture->getID()); - if (dilatedImage.hasAlphaChannel()) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dilatedImage.width(), dilatedImage.height(), 0, - GL_BGRA, GL_UNSIGNED_BYTE, dilatedImage.constBits()); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dilatedImage.width(), dilatedImage.height(), 0, - GL_RGB, GL_UNSIGNED_BYTE, dilatedImage.constBits()); - } - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - */ + if (dilatedImage.hasAlphaChannel()) { texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA), dilatedImage.width(), dilatedImage.height())); texture->_gpuTexture->assignStoredMip(0, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::BGRA), dilatedImage.byteCount(), dilatedImage.constBits()); diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 97523d93d3..b7891e5fac 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -46,19 +46,12 @@ public: /// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture /// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and /// the second, a set of random unit vectors to be used as noise gradients. - GLuint getPermutationNormalTextureID(); - - /// Returns the ID of an opaque white texture (useful for a default). - // GLuint getWhiteTextureID(); + const gpu::TexturePointer& getPermutationNormalTexture(); /// Returns an opaque white texture (useful for a default). const gpu::TexturePointer& getWhiteTexture(); - /// Returns the ID of a pale blue texture (useful for a normal map). - // GLuint getBlueTextureID(); - - /// Returns the ID of a pale blue texture (useful for a normal map). - /// Returns an opaque white texture (useful for a default). + /// Returns the a pale blue texture (useful for a normal map). const gpu::TexturePointer& getBlueTexture(); /// Loads a texture from the specified URL. @@ -108,10 +101,8 @@ private: friend class DilatableNetworkTexture; QOpenGLFramebufferObject* createFramebufferObject(); - - GLuint _permutationNormalTextureID; - GLuint _whiteTextureID; - GLuint _blueTextureID; + + gpu::TexturePointer _permutationNormalTexture; gpu::TexturePointer _whiteTexture; gpu::TexturePointer _blueTexture;