From 4302db109fdab8f70f31f7b317ab555977268927 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 20 Jan 2015 16:02:26 -0800 Subject: [PATCH 01/21] First take at using the gpu::Texture in the Model rendering instead of the previous pass with raw glTexture --- libraries/gpu/src/gpu/Batch.cpp | 13 + libraries/gpu/src/gpu/Batch.h | 17 +- libraries/gpu/src/gpu/Context.h | 12 + libraries/gpu/src/gpu/Format.h | 19 +- libraries/gpu/src/gpu/GLBackend.cpp | 59 ++--- libraries/gpu/src/gpu/GLBackend.h | 20 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 194 ++++++++++++++ libraries/gpu/src/gpu/Resource.cpp | 2 +- libraries/gpu/src/gpu/Resource.h | 72 +---- libraries/gpu/src/gpu/Texture.cpp | 280 ++++++++++++++++++++ libraries/gpu/src/gpu/Texture.h | 278 +++++++++++++++++++ libraries/model/src/model/Material.h | 1 + libraries/render-utils/src/Model.cpp | 12 +- libraries/render-utils/src/TextureCache.cpp | 39 +++ libraries/render-utils/src/TextureCache.h | 19 +- 15 files changed, 911 insertions(+), 126 deletions(-) create mode 100755 libraries/gpu/src/gpu/GLBackendTexture.cpp create mode 100755 libraries/gpu/src/gpu/Texture.cpp create mode 100755 libraries/gpu/src/gpu/Texture.h diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 5604fa21c7..b15ee4fe29 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -23,6 +23,7 @@ Batch::Batch() : _resources(), _data(), _buffers(), + _textures(), _streamFormats(), _transforms() { @@ -38,6 +39,7 @@ void Batch::clear() { _resources.clear(); _data.clear(); _buffers.clear(); + _textures.clear(); _streamFormats.clear(); _transforms.clear(); } @@ -171,3 +173,14 @@ void Batch::setUniformBuffer(uint32 slot, const BufferView& view) { } +void Batch::setUniformTexture(uint32 slot, const TexturePointer& texture) { + ADD_COMMAND(setUniformTexture); + + _params.push_back(_textures.cache(texture)); + _params.push_back(slot); +} + +void Batch::setUniformTexture(uint32 slot, const TextureView& view) { + setUniformTexture(slot, view._texture); +} + diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index c3a87c8f19..f2982e1f52 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -19,6 +19,7 @@ #include #include "Stream.h" +#include "Texture.h" #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" @@ -92,6 +93,10 @@ public: void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView + void setUniformTexture(uint32 slot, const TexturePointer& view); + void setUniformTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView + + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -148,10 +153,6 @@ public: void _glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); - void _glMaterialf(GLenum face, GLenum pname, GLfloat param); - void _glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); - - enum Command { COMMAND_draw = 0, COMMAND_drawIndexed, @@ -167,6 +168,7 @@ public: COMMAND_setProjectionTransform, COMMAND_setUniformBuffer, + COMMAND_setUniformTexture, // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long @@ -219,10 +221,7 @@ public: COMMAND_glEnableVertexAttribArray, COMMAND_glDisableVertexAttribArray, - COMMAND_glColor4f, - - COMMAND_glMaterialf, - COMMAND_glMaterialfv, + COMMAND_glColor4f, NUM_COMMANDS, }; @@ -292,6 +291,7 @@ public: }; typedef Cache::Vector BufferCaches; + typedef Cache::Vector TextureCaches; typedef Cache::Vector StreamFormatCaches; typedef Cache::Vector TransformCaches; @@ -330,6 +330,7 @@ public: Bytes _data; BufferCaches _buffers; + TextureCaches _textures; StreamFormatCaches _streamFormats; TransformCaches _transforms; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 6839f9480a..b8cba3ded1 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -14,6 +14,7 @@ #include #include "Resource.h" +#include "Texture.h" namespace gpu { @@ -39,6 +40,17 @@ public: void syncGPUObject(const Buffer& buffer); + template< typename T > + static void setGPUObject(const Texture& texture, T* to) { + texture.setGPUObject(reinterpret_cast(to)); + } + template< typename T > + static T* getGPUObject(const Texture& texture) { + return reinterpret_cast(texture.getGPUObject()); + } + + void syncGPUObject(const Texture& texture); + protected: }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index aeeece8a62..be3b153e23 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -95,6 +95,7 @@ enum Semantic { RAW = 0, // used as RAW memory RGB, RGBA, + BGRA, XYZ, XYZW, POS_XYZ, @@ -102,10 +103,12 @@ enum Semantic { QUAT, DIR_XYZ, UV, - R8, INDEX, //used by index buffer of a mesh PART, // used by part buffer of a mesh + DEPTH, // Depth buffer + DEPTH_STENCIL, // Depth Stencil buffer + NUM_SEMANTICS, }; @@ -124,7 +127,7 @@ public: _dimension(SCALAR), _type(INT8) {} - + Semantic getSemantic() const { return (Semantic)_semantic; } Dimension getDimension() const { return (Dimension)_dimension; } @@ -135,11 +138,21 @@ public: uint32 getSize() const { return DIMENSION_COUNT[_dimension] * TYPE_SIZE[_type]; } -protected: + uint16 getRaw() const { return *((uint16*) (this)); } + + protected: uint8 _semantic; uint8 _dimension : 4; uint8 _type : 4; }; + + +static bool operator ==(const Element& left, const Element& right) { + return left.getRaw() == right.getRaw(); +} +static bool operator !=(const Element& left, const Element& right) { + return left.getRaw() != right.getRaw(); +} }; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index a01b39c35f..4c5f215429 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -1,6 +1,6 @@ // // GLBackend.cpp -// interface/src/gpu +// libraries/gpu/src/gpu // // Created by Sam Gateau on 10/27/2014. // Copyright 2014 High Fidelity, Inc. @@ -32,6 +32,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setProjectionTransform), (&::gpu::GLBackend::do_setUniformBuffer), + (&::gpu::GLBackend::do_setUniformTexture), (&::gpu::GLBackend::do_glEnable), (&::gpu::GLBackend::do_glDisable), @@ -82,9 +83,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glDisableVertexAttribArray), (&::gpu::GLBackend::do_glColor4f), - - (&::gpu::GLBackend::do_glMaterialf), - (&::gpu::GLBackend::do_glMaterialfv), }; static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = { @@ -174,8 +172,8 @@ void GLBackend::checkGLError() { } } -//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() -#define CHECK_GL_ERROR() +#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +//#define CHECK_GL_ERROR() void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { updateInput(); @@ -508,6 +506,20 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } +void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { + GLuint slot = batch._params[paramOffset + 1]._uint; + TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); +#if defined(Q_OS_MAC) +#elif defined(Q_OS_WIN) + GLuint to = getTextureID(*uniformTexture); + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(GL_TEXTURE_2D, to); +#else +#endif + CHECK_GL_ERROR(); +} + + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -1077,40 +1089,6 @@ void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } -void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) { - ADD_COMMAND_GL(glMaterialf); - - _params.push_back(param); - _params.push_back(pname); - _params.push_back(face); - - DO_IT_NOW(_glMaterialf, 3); -} -void GLBackend::do_glMaterialf(Batch& batch, uint32 paramOffset) { - glMaterialf( - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._uint, - batch._params[paramOffset + 0]._float); - CHECK_GL_ERROR(); -} - -void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { - ADD_COMMAND_GL(glMaterialfv); - - _params.push_back(cacheData(4 * sizeof(float), params)); - _params.push_back(pname); - _params.push_back(face); - - DO_IT_NOW(_glMaterialfv, 3); -} -void GLBackend::do_glMaterialfv(Batch& batch, uint32 paramOffset) { - glMaterialfv( - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._uint, - (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint)); - CHECK_GL_ERROR(); -} - GLBackend::GLBuffer::GLBuffer() : _stamp(0), _buffer(0), @@ -1156,3 +1134,4 @@ GLuint GLBackend::getBufferID(const Buffer& buffer) { GLBackend::syncGPUObject(buffer); return Backend::getGPUObject(buffer)->_buffer; } + diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index be7a0a594b..a15de87afd 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -1,6 +1,6 @@ // // GLBackend.h -// interface/src/gpu +// libraries/gpu/src/gpu // // Created by Sam Gateau on 10/27/2014. // Copyright 2014 High Fidelity, Inc. @@ -42,9 +42,21 @@ public: ~GLBuffer(); }; static void syncGPUObject(const Buffer& buffer); - static GLuint getBufferID(const Buffer& buffer); + class GLTexture { + public: + Stamp _storageStamp; + Stamp _contentStamp; + GLuint _texture; + GLuint _size; + + GLTexture(); + ~GLTexture(); + }; + static void syncGPUObject(const Texture& texture); + static GLuint getTextureID(const Texture& texture); + static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; @@ -124,6 +136,7 @@ protected: // Shader Stage void do_setUniformBuffer(Batch& batch, uint32 paramOffset); + void do_setUniformTexture(Batch& batch, uint32 paramOffset); void updateShader(); struct ShaderStageState { @@ -188,9 +201,6 @@ protected: void do_glColor4f(Batch& batch, uint32 paramOffset); - void do_glMaterialf(Batch& batch, uint32 paramOffset); - void do_glMaterialfv(Batch& batch, uint32 paramOffset); - typedef void (GLBackend::*CommandCall)(Batch&, uint32); static CommandCall _commandCalls[Batch::NUM_COMMANDS]; diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp new file mode 100755 index 0000000000..9582354d57 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -0,0 +1,194 @@ +// +// GLBackendTexture.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 1/19/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "GLBackend.cpp" + +GLBackend::GLTexture::GLTexture() : + _storageStamp(0), + _contentStamp(0), + _texture(0), + _size(0) +{} + +GLBackend::GLTexture::~GLTexture() { + if (_texture != 0) { + glDeleteTextures(1, &_texture); + } +} + +class GLTexelFormat { +public: + GLenum internalFormat; + GLenum format; + GLenum type; + + static GLTexelFormat evalGLTexelFormat(const Element& pixel) { + GLTexelFormat texel = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}; + + switch(pixel.getDimension()) { + case gpu::SCALAR: { + texel.format = GL_RED; + texel.type = _elementTypeToGLType[pixel.getType()]; + + switch(pixel.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RED; + break; + case gpu::DEPTH: + texel.internalFormat = GL_DEPTH_COMPONENT; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; + + case gpu::VEC2: { + texel.format = GL_RG; + texel.type = _elementTypeToGLType[pixel.getType()]; + + switch(pixel.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RG; + break; + case gpu::DEPTH_STENCIL: + texel.internalFormat = GL_DEPTH_STENCIL; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + + } + break; + + case gpu::VEC3: { + texel.format = GL_RGB; + + texel.type = _elementTypeToGLType[pixel.getType()]; + + switch(pixel.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RGB; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; + + case gpu::VEC4: { + texel.format = GL_RGBA; + texel.type = _elementTypeToGLType[pixel.getType()]; + + switch(pixel.getSemantic()) { + case gpu::RGB: + texel.internalFormat = GL_RGB; + break; + case gpu::RGBA: + texel.internalFormat = GL_RGBA; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; + + default: + qDebug() << "Unknown combination of texel format"; + } + return texel; + } +}; + + +void GLBackend::syncGPUObject(const Texture& texture) { + GLTexture* object = Backend::getGPUObject(texture); + + // If GPU object already created and in sync + bool needUpdate = false; + if (object && (object->_storageStamp == texture.getStamp())) { + // If gpu object info is in sync with sysmem version + if (object->_contentStamp >= texture.getDataStamp()) { + // Then all good, GPU object is ready to be used + return; + } else { + // Need to update the content of the GPU object from the source sysmem of the texture + needUpdate = true; + } + } + + // need to have a gpu object? + if (!object) { + object = new GLTexture(); + glGenTextures(1, &object->_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: { + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat()); + if (needUpdate) { + if (texture.isSysmemMipAvailable(0)) { + GLint boundTex = -1; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); + + glBindTexture(GL_TEXTURE_2D, object->_texture); + glTexSubImage2D(GL_TEXTURE_2D, 0, + texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0, + texelFormat.format, texelFormat.type, texture.readMip(0)); + + if (texture.isAutogenerateMips()) { + glGenerateMipmap(GL_TEXTURE_2D); + } + glBindTexture(GL_TEXTURE_2D, boundTex); + object->_contentStamp = texture.getDataStamp(); + } + } else { + const GLvoid* bytes = 0; + if (texture.isSysmemMipAvailable(0)) { + bytes = texture.readMip(0); + object->_contentStamp = texture.getDataStamp(); + } + + GLint boundTex = -1; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); + glBindTexture(GL_TEXTURE_2D, object->_texture); + + glTexImage2D(GL_TEXTURE_2D, 0, + texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0, + texelFormat.format, texelFormat.type, bytes); + + if (bytes && texture.isAutogenerateMips()) { + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + + glBindTexture(GL_TEXTURE_2D, boundTex); + object->_storageStamp = texture.getStamp(); + object->_size = texture.getSize(); + } + } + break; + default: + qDebug() << "GLBackend::syncGPUObject(const Texture&) case for Texture Type " << texture.getType() << " not supported"; + } + CHECK_GL_ERROR(); +} + + + +GLuint GLBackend::getTextureID(const Texture& texture) { + GLBackend::syncGPUObject(texture); + return Backend::getGPUObject(texture)->_texture; +} diff --git a/libraries/gpu/src/gpu/Resource.cpp b/libraries/gpu/src/gpu/Resource.cpp index f59152550b..f1956727f8 100644 --- a/libraries/gpu/src/gpu/Resource.cpp +++ b/libraries/gpu/src/gpu/Resource.cpp @@ -1,6 +1,6 @@ // // Resource.cpp -// interface/src/gpu +// libraries/gpu/src/gpu // // Created by Sam Gateau on 10/8/2014. // Copyright 2014 High Fidelity, Inc. diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index 2ec616251c..081eca0d6d 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -1,6 +1,6 @@ // // Resource.h -// interface/src/gpu +// libraries/gpu/src/gpu // // Created by Sam Gateau on 10/8/2014. // Copyright 2014 High Fidelity, Inc. @@ -79,18 +79,20 @@ protected: // Access the byte array. // The edit version allow to map data. - inline const Byte* readData() const { return _data; } - inline Byte* editData() { _stamp++; return _data; } + const Byte* readData() const { return _data; } + Byte* editData() { _stamp++; return _data; } template< typename T > const T* read() const { return reinterpret_cast< T* > ( _data ); } template< typename T > T* edit() { _stamp++; return reinterpret_cast< T* > ( _data ); } // Access the current version of the sysmem, used to compare if copies are in sync - inline Stamp getStamp() const { return _stamp; } + Stamp getStamp() const { return _stamp; } static Size allocateMemory(Byte** memAllocated, Size size); static void deallocateMemory(Byte* memDeallocated, Size size); + bool isAvailable() const { return (_data != 0); } + private: Stamp _stamp; Size _size; @@ -136,9 +138,9 @@ public: protected: - Sysmem* _sysmem; + Sysmem* _sysmem = NULL; - mutable GPUObject* _gpuObject; + mutable GPUObject* _gpuObject = NULL; // This shouldn't be used by anything else than the Backend class with the proper casting. void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } @@ -363,64 +365,6 @@ public: } }; - - // TODO: For now TextureView works with Buffer as a place holder for the Texture. - // The overall logic should be about the same except that the Texture will be a real GL Texture under the hood -class TextureView { -public: - typedef Resource::Size Size; - typedef int Index; - - BufferPointer _buffer; - Size _offset; - Size _size; - Element _element; - uint16 _stride; - - TextureView() : - _buffer(NULL), - _offset(0), - _size(0), - _element(gpu::VEC3, gpu::UINT8, gpu::RGB), - _stride(1) - {}; - - TextureView(const Element& element) : - _buffer(NULL), - _offset(0), - _size(0), - _element(element), - _stride(uint16(element.getSize())) - {}; - - // create the BufferView and own the Buffer - TextureView(Buffer* newBuffer, const Element& element) : - _buffer(newBuffer), - _offset(0), - _size(newBuffer->getSize()), - _element(element), - _stride(uint16(element.getSize())) - {}; - TextureView(const BufferPointer& buffer, const Element& element) : - _buffer(buffer), - _offset(0), - _size(buffer->getSize()), - _element(element), - _stride(uint16(element.getSize())) - {}; - TextureView(const BufferPointer& buffer, Size offset, Size size, const Element& element) : - _buffer(buffer), - _offset(offset), - _size(size), - _element(element), - _stride(uint16(element.getSize())) - {}; - ~TextureView() {} - TextureView(const TextureView& view) = default; - TextureView& operator=(const TextureView& view) = default; }; -}; - - #endif diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp new file mode 100755 index 0000000000..e0391cb43b --- /dev/null +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -0,0 +1,280 @@ +// +// Texture.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 1/17/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Texture.h" + +#include + +using namespace gpu; + +Texture::Pixels::Pixels(const Element& format, Size size, const Byte* bytes) : + _sysmem(size, bytes), + _format(format) { +} + +Texture::Pixels::~Pixels() { +} + +Texture* Texture::create1D(const Element& texelFormat, uint16 width) { + return create(TEX_1D, texelFormat, width, 1, 1, 1, 1); +} + +Texture* Texture::create2D(const Element& texelFormat, uint16 width, uint16 height) { + return create(TEX_2D, texelFormat, width, height, 1, 1, 1); +} + +Texture* Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth) { + return create(TEX_3D, texelFormat, width, height, depth, 1, 1); +} + +Texture* Texture::createCube(const Element& texelFormat, uint16 width) { + return create(TEX_CUBE, texelFormat, width, width, 1, 1, 1); +} + +Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) +{ + Texture* tex = new Texture(); + + tex->_type = type; + tex->_texelFormat = texelFormat; + tex->_maxMip = 0; + tex->resize(type, width, height, depth, numSamples, numSlices); + + return tex; +} + +Texture::Texture(): + Resource(), + _stamp(0), + _size(0), + _width(1), + _height(1), + _depth(1), + _numSamples(1), + _numSlices(1), + _maxMip(0), + _autoGenerateMips(false) +{ +} + +Texture::~Texture() +{ +} + +Texture::Size Texture::resize(Type type, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) { + if (width && height && depth && numSamples && numSlices) { + bool changed = false; + + if (_numSlices != numSlices) { + _numSlices = numSlices; + changed = true; + } + + numSamples = evalNumSamplesUsed(numSamples); + if ((_type >= TEX_2D) && (_numSamples != numSamples)) { + _numSamples = numSamples; + changed = true; + } + + if (_width != width) { + _width = width; + changed = true; + } + + if ((_type >= TEX_2D) && (_height != height)) { + _height = height; + changed = true; + } + + + if ((_type >= TEX_3D) && (_depth != depth)) { + _depth = depth; + changed = true; + } + + const int DIM_SIZE[] = {1, 1, 1, 6}; + int size = DIM_SIZE[_type] *_width * _height * _depth * _numSamples * _texelFormat.getSize(); + + if (changed || (size != getSize())) { + _size = size; + _mips.clear(); + _stamp++; + } + } + + return _size; +} + +Texture::Size Texture::resize1D(uint16 width, uint16 numSamples) { + return resize(TEX_1D, width, 1, 1, numSamples, 1); +} +Texture::Size Texture::resize2D(uint16 width, uint16 height, uint16 numSamples) { + return resize(TEX_2D, 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); +} +Texture::Size Texture::resizeCube(uint16 width, uint16 numSamples) { + return resize(TEX_CUBE, 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; +} + +bool Texture::isColorRenderTarget() const { + return (_texelFormat.getSemantic() == gpu::RGBA); +} + +bool Texture::isDepthStencilRenderTarget() const { + return (_texelFormat.getSemantic() == gpu::DEPTH) || (_texelFormat.getSemantic() == gpu::DEPTH_STENCIL); +} + +uint16 Texture::evalDimNumMips(uint16 size) { + double largerDim = size; + double val = log(largerDim)/log(2.0); + return 1 + (uint16) val; +} + +// The number mips that the texture could have if all existed +// = log2(max(width, height, depth)) +uint16 Texture::evalNumMips() const { + double largerDim = std::max(std::max(_width, _height), _depth); + double val = log(largerDim)/log(2.0); + return 1 + (uint16) val; +} + +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) { + if (_autoGenerateMips) { + return false; + } + if (level >= evalNumMips()) { + return false; + } + } + + // 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); + _stamp++; + + return true; + } + + return false; +} + +uint16 Texture::autoGenerateMips(uint16 maxMip) { + _autoGenerateMips = true; + _maxMip = std::min((uint16) (evalNumMips() - 1), maxMip); + _stamp++; + return _maxMip; +} + +uint16 Texture::getStoredMipWidth(uint16 level) const { + const Pixels* mip = accessStoredMip(level); + if (mip && mip->_sysmem.getSize()) { + return evalMipWidth(level); + } else { + return 0; + } +} + +uint16 Texture::getStoredMipHeight(uint16 level) const { + const Pixels* mip = accessStoredMip(level); + if (mip && mip->_sysmem.getSize()) { + return evalMipHeight(level); + } else { + return 0; + } +} + +uint16 Texture::getStoredMipDepth(uint16 level) const { + const Pixels* mip = accessStoredMip(level); + if (mip && mip->_sysmem.getSize()) { + return evalMipDepth(level); + } else { + return 0; + } +} + +uint32 Texture::getStoredMipNumTexels(uint16 level) const { + const Pixels* mip = accessStoredMip(level); + if (mip && mip->_sysmem.getSize()) { + return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); + } else { + return 0; + } +} + +uint32 Texture::getStoredMipSize(uint16 level) const { + const Pixels* mip = accessStoredMip(level); + if (mip && mip->_sysmem.getSize()) { + return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize(); + } else { + return 0; + } +} + +uint16 Texture::evalNumSamplesUsed(uint16 numSamplesTried) +{ + uint16 sample = numSamplesTried; + if (numSamplesTried <= 1) + sample = 1; + else if (numSamplesTried < 4) + sample = 2; + else if (numSamplesTried < 8) + sample = 4; + else if (numSamplesTried < 16) + sample = 8; + else + sample = 8; + + return sample; +} diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h new file mode 100755 index 0000000000..8f63abe005 --- /dev/null +++ b/libraries/gpu/src/gpu/Texture.h @@ -0,0 +1,278 @@ +// +// Texture.h +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 1/16/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_gpu_Texture_h +#define hifi_gpu_Texture_h + +#include "Resource.h" +#include + +namespace gpu { + +class Texture : public Resource { +public: + + class Pixels { + public: + Pixels() {} + Pixels(const Pixels& pixels) = default; + Pixels(const Element& format, Size size, const Byte* bytes); + ~Pixels(); + + Sysmem _sysmem; + Element _format; + }; + typedef std::shared_ptr PixelsPointer; + + enum Type { + TEX_1D = 0, + TEX_2D, + TEX_3D, + TEX_CUBE, + }; + + static Texture* create1D(const Element& texelFormat, uint16 width); + static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height); + static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth); + static Texture* createCube(const Element& texelFormat, uint16 width); + + 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 { + const Pixels* mip = accessStoredMip(level); + if (mip) { + return mip->_sysmem.getStamp(); + } + return getStamp(); + } + + // The size in bytes of data stored in the texture + Size getSize() const { return _size; } + + // Resize, unless auto mips mode would destroy all the sub mips + Size resize1D(uint16 width, uint16 numSamples); + Size resize2D(uint16 width, uint16 height, uint16 numSamples); + Size resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples); + Size resizeCube(uint16 width, uint16 numSamples); + + // Reformat, unless auto mips mode would destroy all the sub mips + Size reformat(const Element& texelFormat); + + // Size and format + Type getType() const { return _type; } + + bool isColorRenderTarget() const; + bool isDepthStencilRenderTarget() const; + + const Element& getTexelFormat() const { return _texelFormat; } + bool hasBorder() const { return false; } + + uint16 getWidth() const { return _width; } + uint16 getHeight() const { return _height; } + uint16 getDepth() const { return _depth; } + + uint32 getRowPitch() const { return getWidth() * getTexelFormat().getSize(); } + uint32 getNumTexels() const { return _width * _height * _depth; } + + uint16 getNumSlices() const { return _numSlices; } + uint16 getNumSamples() const { return _numSamples; } + + + //--------------------------------------------------------------------- + // Sub Mips manipulation + + // The number mips that a dimension could haves + // = 1 + log2(size) + static uint16 evalDimNumMips(uint16 size); + + // The number mips that the texture could have if all existed + // = 1 + log2(max(width, height, depth)) + uint16 evalNumMips() const; + + // Eval the size that the mips level SHOULD have + // not the one stored in the Texture + uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); } + uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); } + uint16 evalMipDepth(uint16 level) const { return std::max(_depth >> level, 1); } + uint32 evalMipNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); } + uint32 evalMipSize(uint16 level) const { return evalMipNumTexels(level) * getTexelFormat().getSize(); } + uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); } + + uint32 evalTotalSize() const { + uint32 size = 0; + uint16 minMipLevel = 0; + uint16 maxMipLevel = maxMip(); + for (uint16 l = minMipLevel; l <= maxMipLevel; l++) { + size += evalMipSize(l); + } + 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 + uint16 maxMip() const; + + // Generate the mips automatically + // But the sysmem version is not available + // Only works for the standard formats + // Specify the maximum Mip level available + // 0 is the default one + // 1 is the first level + // ... + // nbMips - 1 is the last mip level + // + // If -1 then all the mips are generated + // + // Return the totalnumber of mips that will be available + uint16 autoGenerateMips(uint16 maxMip); + bool isAutogenerateMips() const { return _autoGenerateMips; } + + // 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 + // Explicitely assign mip data for a certain level + // 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); + + template< typename T > T* editMip(uint16 level) { + Pixels* mip = accessStoredMip(level); + if (mip) { + return mip->sysmem.edit(); + } + return 0; + } + + template< typename T > const T* readMip(uint16 level) const { + const Pixels* mip = accessStoredMip(level); + if (mip) { + return mip->sysmem.read(); + } + return 0; + } + + bool isSysmemMipAvailable(uint16 level) const { + const Pixels* mip = accessStoredMip(level); + if (mip) { + return mip->_sysmem.isAvailable(); + } + return false; + } + + // 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); + +protected: + + std::vector _mips; + + Stamp _stamp; + + uint32 _size; + Element _texelFormat; + + uint16 _width; + uint16 _height; + uint16 _depth; + + uint16 _numSlices; + uint16 _numSamples; + + uint16 _maxMip; + + Type _type; + bool _autoGenerateMips; + + + 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); + + // Access the the sub mips + const Pixels* Texture::accessStoredMip(uint16 level) const { + if (level > _mips.size()) { + return 0; + } else { + return _mips[level].get(); + } + } + + // Access the the sub mips + Pixels* Texture::accessStoredMip(uint16 level) { + if (level > _mips.size()) { + return 0; + } else { + return _mips[level].get(); + } + } + + void allocateStoredMip(uint16 level); + + mutable GPUObject* _gpuObject = NULL; + + // This shouldn't be used by anything else than the Backend class with the proper casting. + void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } + GPUObject* getGPUObject() const { return _gpuObject; } + + friend class Backend; +}; + +typedef QSharedPointer TexturePointer; +typedef std::vector< TexturePointer > Textures; + + + // TODO: For now TextureView works with Buffer as a place holder for the Texture. + // The overall logic should be about the same except that the Texture will be a real GL Texture under the hood +class TextureView { +public: + typedef Resource::Size Size; + + TexturePointer _texture = TexturePointer(NULL); + uint16 _subresource = 0; + Element _element = Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); + + TextureView() {}; + + TextureView(const Element& element) : + _element(element) + {}; + + // create the TextureView and own the Texture + TextureView(Texture* newTexture, const Element& element) : + _texture(newTexture), + _subresource(0), + _element(element) + {}; + TextureView(const TexturePointer& texture, const Element& element) : + _texture(texture), + _subresource(0), + _element(element) + {}; + ~TextureView() {} + TextureView(const TextureView& view) = default; + TextureView& operator=(const TextureView& view) = default; +}; + +}; + + +#endif diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index ec15522658..efd2f35968 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -17,6 +17,7 @@ #include #include "gpu/Resource.h" +#include "gpu/Texture.h" namespace model { typedef gpu::BufferView UniformBufferView; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 97e6124517..a91081ccdb 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2224,7 +2224,10 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } GLBATCH(glUseProgram)(activeProgram->programId()); - GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold); + + if ((activeLocations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) { + GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold); + } } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, @@ -2414,9 +2417,12 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } static bool showDiffuse = true; if (showDiffuse && diffuseMap) { - GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID()); + // GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID()); + batch.setUniformTexture(0, diffuseMap->getGPUTexture()); + } else { - GLBATCH(glBindTexture)(GL_TEXTURE_2D, textureCache->getWhiteTextureID()); + // GLBATCH(glBindTexture)(GL_TEXTURE_2D, textureCache->getWhiteTextureID()); + batch.setUniformTexture(0, textureCache->getWhiteTexture()); } if (locations->texcoordMatrices >= 0) { diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 3bd05a14ee..6c623d3eb7 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -29,6 +29,8 @@ TextureCache::TextureCache() : _permutationNormalTextureID(0), _whiteTextureID(0), _blueTextureID(0), + _whiteTexture(0), + _blueTexture(0), _primaryDepthTextureID(0), _primaryNormalTextureID(0), _primarySpecularTextureID(0), @@ -176,6 +178,14 @@ GLuint TextureCache::getWhiteTextureID() { 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)); + _whiteTexture->assignStoredMip(0, _whiteTexture->getTexelFormat(), sizeof(OPAQUE_WHITE), OPAQUE_WHITE); + } + return _whiteTexture; +} + GLuint TextureCache::getBlueTextureID() { if (_blueTextureID == 0) { glGenTextures(1, &_blueTextureID); @@ -186,6 +196,15 @@ GLuint TextureCache::getBlueTextureID() { return _blueTextureID; } + +const gpu::TexturePointer& TextureCache::getBlueTexture() { + if (_blueTexture.isNull()) { + _blueTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA), 1, 1)); + _blueTexture->assignStoredMip(0, _blueTexture->getTexelFormat(), sizeof(OPAQUE_BLUE), OPAQUE_BLUE); + } + return _blueTexture; +} + /// Extra data for creating textures. class TextureExtra { public: @@ -547,6 +566,16 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo 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()); + _gpuTexture->autoGenerateMips(-1); + } else { + _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), image.width(), image.height())); + _gpuTexture->assignStoredMip(0, gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), image.byteCount(), image.constBits()); + _gpuTexture->autoGenerateMips(-1); + } } void NetworkTexture::imageLoaded(const QImage& image) { @@ -586,6 +615,16 @@ QSharedPointer DilatableNetworkTexture::getDilatedTexture(float dilatio 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()); + texture->_gpuTexture->autoGenerateMips(-1); + } else { + texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), dilatedImage.width(), dilatedImage.height())); + texture->_gpuTexture->assignStoredMip(0, gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), dilatedImage.byteCount(), dilatedImage.constBits()); + texture->_gpuTexture->autoGenerateMips(-1); + } } _dilatedTextures.insert(dilation, texture); diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 54c98a61cb..9591218f80 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -13,6 +13,7 @@ #define hifi_TextureCache_h #include +#include #include #include @@ -50,9 +51,16 @@ public: /// Returns the ID of an opaque white texture (useful for a default). GLuint getWhiteTextureID(); + /// 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). + const gpu::TexturePointer& getBlueTexture(); + /// Loads a texture from the specified URL. NetworkTexturePointer getTexture(const QUrl& url, TextureType type = DEFAULT_TEXTURE, bool dilatable = false, const QByteArray& content = QByteArray()); @@ -104,6 +112,8 @@ private: GLuint _permutationNormalTextureID; GLuint _whiteTextureID; GLuint _blueTextureID; + gpu::TexturePointer _whiteTexture; + gpu::TexturePointer _blueTexture; QHash > _dilatableNetworkTextures; @@ -124,14 +134,19 @@ private: /// A simple object wrapper for an OpenGL texture. class Texture { public: - + friend class TextureCache; + friend class DilatableNetworkTexture; Texture(); ~Texture(); GLuint getID() const { return _id; } + const gpu::TexturePointer& getGPUTexture() const { return _gpuTexture; } + +protected: + gpu::TexturePointer _gpuTexture; + private: - GLuint _id; }; From d19bfa69f2a9942f9bb6abe1334ff1b2ea0c6b1e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 21 Jan 2015 10:07:10 -0800 Subject: [PATCH 02/21] Even more gpu::Texture in the model rnedering --- libraries/gpu/src/gpu/GLBackendTexture.cpp | 246 ++++++++++++++------ libraries/gpu/src/gpu/Texture.cpp | 10 +- libraries/gpu/src/gpu/Texture.h | 61 ++--- libraries/render-utils/src/Model.cpp | 32 ++- libraries/render-utils/src/TextureCache.cpp | 15 +- libraries/render-utils/src/TextureCache.h | 4 +- 6 files changed, 231 insertions(+), 137 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 9582354d57..e23f6fdaec 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -29,84 +29,174 @@ public: GLenum format; GLenum type; - static GLTexelFormat evalGLTexelFormat(const Element& pixel) { - GLTexelFormat texel = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}; + static GLTexelFormat evalGLTexelFormat(const Element& dstFormat, const Element& srcFormat) { + if (dstFormat != srcFormat) { + GLTexelFormat texel = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}; - switch(pixel.getDimension()) { - case gpu::SCALAR: { - texel.format = GL_RED; - texel.type = _elementTypeToGLType[pixel.getType()]; + switch(dstFormat.getDimension()) { + case gpu::SCALAR: { + texel.format = GL_RED; + texel.type = _elementTypeToGLType[dstFormat.getType()]; + + switch(dstFormat.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RED; + break; + case gpu::DEPTH: + texel.internalFormat = GL_DEPTH_COMPONENT; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; + + case gpu::VEC2: { + texel.format = GL_RG; + texel.type = _elementTypeToGLType[dstFormat.getType()]; + + switch(dstFormat.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RG; + break; + case gpu::DEPTH_STENCIL: + texel.internalFormat = GL_DEPTH_STENCIL; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + + } + break; + + case gpu::VEC3: { + texel.format = GL_RGB; + + texel.type = _elementTypeToGLType[dstFormat.getType()]; + + switch(dstFormat.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RGB; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; + + case gpu::VEC4: { + texel.format = GL_RGBA; + texel.type = _elementTypeToGLType[dstFormat.getType()]; + + switch(srcFormat.getSemantic()) { + case gpu::BGRA: + texel.format = GL_BGRA; + break; + case gpu::RGB: + case gpu::RGBA: + default: + break; + }; + + switch(dstFormat.getSemantic()) { + case gpu::RGB: + texel.internalFormat = GL_RGB; + break; + case gpu::RGBA: + texel.internalFormat = GL_RGBA; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; - switch(pixel.getSemantic()) { - case gpu::RGB: - case gpu::RGBA: - texel.internalFormat = GL_RED; - break; - case gpu::DEPTH: - texel.internalFormat = GL_DEPTH_COMPONENT; - break; default: qDebug() << "Unknown combination of texel format"; } - } - break; + return texel; + } else { + GLTexelFormat texel = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}; - case gpu::VEC2: { - texel.format = GL_RG; - texel.type = _elementTypeToGLType[pixel.getType()]; + switch(dstFormat.getDimension()) { + case gpu::SCALAR: { + texel.format = GL_RED; + texel.type = _elementTypeToGLType[dstFormat.getType()]; + + switch(dstFormat.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RED; + break; + case gpu::DEPTH: + texel.internalFormat = GL_DEPTH_COMPONENT; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; + + case gpu::VEC2: { + texel.format = GL_RG; + texel.type = _elementTypeToGLType[dstFormat.getType()]; + + switch(dstFormat.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RG; + break; + case gpu::DEPTH_STENCIL: + texel.internalFormat = GL_DEPTH_STENCIL; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + + } + break; + + case gpu::VEC3: { + texel.format = GL_RGB; + + texel.type = _elementTypeToGLType[dstFormat.getType()]; + + switch(dstFormat.getSemantic()) { + case gpu::RGB: + case gpu::RGBA: + texel.internalFormat = GL_RGB; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; + + case gpu::VEC4: { + texel.format = GL_RGBA; + texel.type = _elementTypeToGLType[dstFormat.getType()]; + + switch(dstFormat.getSemantic()) { + case gpu::RGB: + texel.internalFormat = GL_RGB; + break; + case gpu::RGBA: + texel.internalFormat = GL_RGBA; + break; + default: + qDebug() << "Unknown combination of texel format"; + } + } + break; - switch(pixel.getSemantic()) { - case gpu::RGB: - case gpu::RGBA: - texel.internalFormat = GL_RG; - break; - case gpu::DEPTH_STENCIL: - texel.internalFormat = GL_DEPTH_STENCIL; - break; default: qDebug() << "Unknown combination of texel format"; } - + return texel; } - break; - - case gpu::VEC3: { - texel.format = GL_RGB; - - texel.type = _elementTypeToGLType[pixel.getType()]; - - switch(pixel.getSemantic()) { - case gpu::RGB: - case gpu::RGBA: - texel.internalFormat = GL_RGB; - break; - default: - qDebug() << "Unknown combination of texel format"; - } - } - break; - - case gpu::VEC4: { - texel.format = GL_RGBA; - texel.type = _elementTypeToGLType[pixel.getType()]; - - switch(pixel.getSemantic()) { - case gpu::RGB: - texel.internalFormat = GL_RGB; - break; - case gpu::RGBA: - texel.internalFormat = GL_RGBA; - break; - default: - qDebug() << "Unknown combination of texel format"; - } - } - break; - - default: - qDebug() << "Unknown combination of texel format"; - } - return texel; } }; @@ -137,16 +227,21 @@ void GLBackend::syncGPUObject(const Texture& texture) { // GO through the process of allocating the correct storage and/or update the content switch (texture.getType()) { case Texture::TEX_2D: { - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat()); if (needUpdate) { - if (texture.isSysmemMipAvailable(0)) { + if (texture.isStoredMipAvailable(0)) { GLint boundTex = -1; glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); + + Texture::PixelsPointer mip = texture.accessStoredMip(0); + const GLvoid* bytes = mip->_sysmem.read(); + Element srcFormat = mip->_format; + + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); glBindTexture(GL_TEXTURE_2D, object->_texture); glTexSubImage2D(GL_TEXTURE_2D, 0, texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0, - texelFormat.format, texelFormat.type, texture.readMip(0)); + texelFormat.format, texelFormat.type, bytes); if (texture.isAutogenerateMips()) { glGenerateMipmap(GL_TEXTURE_2D); @@ -156,14 +251,21 @@ void GLBackend::syncGPUObject(const Texture& texture) { } } else { const GLvoid* bytes = 0; - if (texture.isSysmemMipAvailable(0)) { - bytes = texture.readMip(0); + Element srcFormat = texture.getTexelFormat(); + if (texture.isStoredMipAvailable(0)) { + Texture::PixelsPointer mip = texture.accessStoredMip(0); + + bytes = mip->_sysmem.read(); + srcFormat = mip->_format; + object->_contentStamp = texture.getDataStamp(); } GLint boundTex = -1; glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); glBindTexture(GL_TEXTURE_2D, object->_texture); + + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); glTexImage2D(GL_TEXTURE_2D, 0, texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0, diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index e0391cb43b..5a52529403 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -218,7 +218,7 @@ uint16 Texture::autoGenerateMips(uint16 maxMip) { } uint16 Texture::getStoredMipWidth(uint16 level) const { - const Pixels* mip = accessStoredMip(level); + PixelsPointer mip = accessStoredMip(level); if (mip && mip->_sysmem.getSize()) { return evalMipWidth(level); } else { @@ -227,7 +227,7 @@ uint16 Texture::getStoredMipWidth(uint16 level) const { } uint16 Texture::getStoredMipHeight(uint16 level) const { - const Pixels* mip = accessStoredMip(level); + PixelsPointer mip = accessStoredMip(level); if (mip && mip->_sysmem.getSize()) { return evalMipHeight(level); } else { @@ -236,7 +236,7 @@ uint16 Texture::getStoredMipHeight(uint16 level) const { } uint16 Texture::getStoredMipDepth(uint16 level) const { - const Pixels* mip = accessStoredMip(level); + PixelsPointer mip = accessStoredMip(level); if (mip && mip->_sysmem.getSize()) { return evalMipDepth(level); } else { @@ -245,7 +245,7 @@ uint16 Texture::getStoredMipDepth(uint16 level) const { } uint32 Texture::getStoredMipNumTexels(uint16 level) const { - const Pixels* mip = accessStoredMip(level); + PixelsPointer mip = accessStoredMip(level); if (mip && mip->_sysmem.getSize()) { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); } else { @@ -254,7 +254,7 @@ uint32 Texture::getStoredMipNumTexels(uint16 level) const { } uint32 Texture::getStoredMipSize(uint16 level) const { - const Pixels* mip = accessStoredMip(level); + PixelsPointer mip = accessStoredMip(level); if (mip && mip->_sysmem.getSize()) { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize(); } else { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 8f63abe005..e9a6afe0f2 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -29,7 +29,7 @@ public: Sysmem _sysmem; Element _format; }; - typedef std::shared_ptr PixelsPointer; + typedef QSharedPointer< Pixels > PixelsPointer; enum Type { TEX_1D = 0, @@ -49,7 +49,7 @@ public: const Stamp getStamp() const { return _stamp; } const Stamp getDataStamp(uint16 level = 0) const { - const Pixels* mip = accessStoredMip(level); + PixelsPointer mip = accessStoredMip(level); if (mip) { return mip->_sysmem.getStamp(); } @@ -87,8 +87,6 @@ public: uint16 getNumSlices() const { return _numSlices; } uint16 getNumSamples() const { return _numSamples; } - - //--------------------------------------------------------------------- // Sub Mips manipulation // The number mips that a dimension could haves @@ -146,29 +144,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); - template< typename T > T* editMip(uint16 level) { - Pixels* mip = accessStoredMip(level); - if (mip) { - return mip->sysmem.edit(); - } - return 0; - } - - template< typename T > const T* readMip(uint16 level) const { - const Pixels* mip = accessStoredMip(level); - if (mip) { - return mip->sysmem.read(); - } - return 0; - } - - bool isSysmemMipAvailable(uint16 level) const { - const Pixels* mip = accessStoredMip(level); + 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 sizes for the stored mips uint16 getStoredMipWidth(uint16 level) const; @@ -207,25 +197,16 @@ protected: Size resize(Type type, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); - // Access the the sub mips - const Pixels* Texture::accessStoredMip(uint16 level) const { - if (level > _mips.size()) { - return 0; - } else { - return _mips[level].get(); - } - } - - // Access the the sub mips - Pixels* Texture::accessStoredMip(uint16 level) { - if (level > _mips.size()) { - return 0; - } else { - return _mips[level].get(); - } - } - void allocateStoredMip(uint16 level); + + // Access the the sub mips + PixelsPointer Texture::accessStoredMip(uint16 level) { + if (level > _mips.size()) { + return 0; + } else { + return _mips[level]; + } + } mutable GPUObject* _gpuObject = NULL; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index a91081ccdb..3163aa5f9c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2351,7 +2351,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } } - GLBATCH(glPushMatrix)(); + // GLBATCH(glPushMatrix)(); const MeshState& state = _meshStates.at(i); if (state.clusterMatrices.size() > 1) { @@ -2388,7 +2388,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod // apply material properties if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); } else { if (lastMaterialID != part.materialID) { @@ -2437,19 +2437,26 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (!mesh.tangents.isEmpty()) { - GLBATCH(glActiveTexture)(GL_TEXTURE1); + // GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ? + /* GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ? textureCache->getBlueTextureID() : normalMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); + */ + batch.setUniformTexture(1, !normalMap ? + textureCache->getBlueTexture() : normalMap->getGPUTexture()); + } if (locations->specularTextureUnit >= 0) { - GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); + // GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? + /* GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? textureCache->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); + */ + batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? + textureCache->getWhiteTexture() : specularMap->getGPUTexture()); } if (args) { @@ -2466,11 +2473,14 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod float emissiveScale = part.emissiveParams.y; GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); + // GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? + /* GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? textureCache->getWhiteTextureID() : emissiveMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); + */ + batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? + textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); } lastMaterialID = part.materialID; @@ -2496,7 +2506,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } } - if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { + /* if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { GLBATCH(glActiveTexture)(GL_TEXTURE1); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); @@ -2513,8 +2523,8 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); } - - GLBATCH(glPopMatrix)(); + */ + // GLBATCH(glPopMatrix)(); } diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 6c623d3eb7..c8bb936b27 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -167,7 +167,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); @@ -177,7 +177,7 @@ GLuint TextureCache::getWhiteTextureID() { } 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,7 +185,7 @@ const gpu::TexturePointer& TextureCache::getWhiteTexture() { } return _whiteTexture; } - +/* GLuint TextureCache::getBlueTextureID() { if (_blueTextureID == 0) { glGenTextures(1, &_blueTextureID); @@ -195,7 +195,7 @@ GLuint TextureCache::getBlueTextureID() { } return _blueTextureID; } - +*/ const gpu::TexturePointer& TextureCache::getBlueTexture() { if (_blueTexture.isNull()) { @@ -554,7 +554,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo finishedLoading(true); imageLoaded(image); - glBindTexture(GL_TEXTURE_2D, getID()); + /* 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()); @@ -566,7 +566,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo 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()); @@ -604,6 +604,7 @@ QSharedPointer DilatableNetworkTexture::getDilatedTexture(float dilatio 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, @@ -615,7 +616,7 @@ QSharedPointer DilatableNetworkTexture::getDilatedTexture(float dilatio 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 9591218f80..97523d93d3 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -49,13 +49,13 @@ public: GLuint getPermutationNormalTextureID(); /// Returns the ID of an opaque white texture (useful for a default). - GLuint getWhiteTextureID(); + // GLuint getWhiteTextureID(); /// 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(); + // GLuint getBlueTextureID(); /// Returns the ID of a pale blue texture (useful for a normal map). /// Returns an opaque white texture (useful for a default). From 1e84f260a9f59b63341deb15734d2de402e92cc6 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 21 Jan 2015 16:53:35 -0800 Subject: [PATCH 03/21] 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; From 03a5c398ec984ec85617ea74a6f08200e0a22d34 Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 22 Jan 2015 12:38:24 -0800 Subject: [PATCH 04/21] splitting the GLBackend.cpp in several files and fixing the build for mac --- libraries/gpu/src/gpu/Format.h | 17 +- libraries/gpu/src/gpu/GLBackend.cpp | 46 +--- libraries/gpu/src/gpu/GLBackendShared.h | 53 +++++ libraries/gpu/src/gpu/GLBackendTexture.cpp | 9 +- libraries/gpu/src/gpu/Texture.cpp | 34 +-- libraries/gpu/src/gpu/Texture.h | 256 ++++++++++----------- 6 files changed, 214 insertions(+), 201 deletions(-) create mode 100644 libraries/gpu/src/gpu/GLBackendShared.h diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index be3b153e23..35876ffffa 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -140,20 +140,19 @@ public: uint16 getRaw() const { return *((uint16*) (this)); } + + bool operator ==(const Element& right) const { + return getRaw() == right.getRaw(); + } + bool operator !=(const Element& right) const { + return getRaw() != right.getRaw(); + } + protected: uint8 _semantic; uint8 _dimension : 4; uint8 _type : 4; }; - - -static bool operator ==(const Element& left, const Element& right) { - return left.getRaw() == right.getRaw(); -} -static bool operator !=(const Element& left, const Element& right) { - return left.getRaw() != right.getRaw(); -} - }; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 4c5f215429..e2f923f369 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -8,13 +8,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "GLBackend.h" - -#include - -#include "Batch.h" - -using namespace gpu; +#include "GLBackendShared.h" GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = { @@ -85,35 +79,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glColor4f), }; -static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = { - GL_POINTS, - GL_LINES, - GL_LINE_STRIP, - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_QUADS, -}; - -static const GLenum _elementTypeToGLType[NUM_TYPES]= { - GL_FLOAT, - GL_INT, - GL_UNSIGNED_INT, - GL_HALF_FLOAT, - GL_SHORT, - GL_UNSIGNED_SHORT, - GL_BYTE, - GL_UNSIGNED_BYTE, - GL_FLOAT, - GL_INT, - GL_UNSIGNED_INT, - GL_HALF_FLOAT, - GL_SHORT, - GL_UNSIGNED_SHORT, - GL_BYTE, - GL_UNSIGNED_BYTE -}; - - GLBackend::GLBackend() : _input(), _transform() @@ -172,9 +137,6 @@ void GLBackend::checkGLError() { } } -#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() -//#define CHECK_GL_ERROR() - void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { updateInput(); updateTransform(); @@ -509,13 +471,11 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 1]._uint; TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); -#if defined(Q_OS_MAC) -#elif defined(Q_OS_WIN) + GLuint to = getTextureID(*uniformTexture); glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(GL_TEXTURE_2D, to); -#else -#endif + CHECK_GL_ERROR(); } diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h new file mode 100644 index 0000000000..521c0742f6 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -0,0 +1,53 @@ +// +// GLBackendShared.h +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 1/22/2014. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_gpu_GLBackend_Shared_h +#define hifi_gpu_GLBackend_Shared_h + +#include "GLBackend.h" + +#include + +#include "Batch.h" + +using namespace gpu; + +static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = { + GL_POINTS, + GL_LINES, + GL_LINE_STRIP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_QUADS, +}; + +static const GLenum _elementTypeToGLType[NUM_TYPES]= { + GL_FLOAT, + GL_INT, + GL_UNSIGNED_INT, + GL_HALF_FLOAT, + GL_SHORT, + GL_UNSIGNED_SHORT, + GL_BYTE, + GL_UNSIGNED_BYTE, + GL_FLOAT, + GL_INT, + GL_UNSIGNED_INT, + GL_HALF_FLOAT, + GL_SHORT, + GL_UNSIGNED_SHORT, + GL_BYTE, + GL_UNSIGNED_BYTE +}; + +#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +//#define CHECK_GL_ERROR() + +#endif diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 5fa33a4210..d416b5b7c9 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -8,7 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "GLBackend.cpp" +#include "GLBackendShared.h" + GLBackend::GLTexture::GLTexture() : _storageStamp(0), @@ -234,11 +235,11 @@ void GLBackend::syncGPUObject(const Texture& texture) { if (needUpdate) { if (texture.isStoredMipAvailable(0)) { GLint boundTex = -1; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); - + glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); + Texture::PixelsPointer mip = texture.accessStoredMip(0); const GLvoid* bytes = mip->_sysmem.read(); - Element srcFormat = mip->_format; + Element srcFormat = mip->_format; GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index a608e74dd1..736545e758 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -1,20 +1,20 @@ -// -// Texture.cpp -// libraries/gpu/src/gpu -// -// Created by Sam Gateau on 1/17/2015. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Texture.h" - -#include - -using namespace gpu; - +// +// Texture.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 1/17/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Texture.h" +#include +#include + +using namespace gpu; + Texture::Pixels::Pixels(const Element& format, Size size, const Byte* bytes) : _sysmem(size, bytes), _format(format) { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 8da500b444..8b8fcf6c04 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -35,7 +35,7 @@ public: Texture* _texture; std::vector _mips; public: - + Storage() {} virtual ~Storage() {} virtual void reset(); @@ -55,13 +55,13 @@ public: TEX_3D, TEX_CUBE, }; - - static Texture* create1D(const Element& texelFormat, uint16 width); - static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height); - 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); + static Texture* create1D(const Element& texelFormat, uint16 width); + static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height); + 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 @@ -72,134 +72,134 @@ public: // The size in bytes of data stored in the texture Size getSize() const { return _size; } - - // Resize, unless auto mips mode would destroy all the sub mips - Size resize1D(uint16 width, uint16 numSamples); - Size resize2D(uint16 width, uint16 height, uint16 numSamples); - Size resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples); - Size resizeCube(uint16 width, uint16 numSamples); - - // Reformat, unless auto mips mode would destroy all the sub mips - Size reformat(const Element& texelFormat); - - // Size and format - Type getType() const { return _type; } - - bool isColorRenderTarget() const; - bool isDepthStencilRenderTarget() const; - - const Element& getTexelFormat() const { return _texelFormat; } - bool hasBorder() const { return false; } - - uint16 getWidth() const { return _width; } - uint16 getHeight() const { return _height; } - uint16 getDepth() const { return _depth; } - uint32 getRowPitch() const { return getWidth() * getTexelFormat().getSize(); } - uint32 getNumTexels() const { return _width * _height * _depth; } - - uint16 getNumSlices() const { return _numSlices; } - uint16 getNumSamples() const { return _numSamples; } - - // 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) - static uint16 evalDimNumMips(uint16 size); - - // The number mips that the texture could have if all existed - // = 1 + log2(max(width, height, depth)) - uint16 evalNumMips() const; - - // Eval the size that the mips level SHOULD have - // not the one stored in the Texture - uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); } - uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); } - uint16 evalMipDepth(uint16 level) const { return std::max(_depth >> level, 1); } - uint32 evalMipNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); } - uint32 evalMipSize(uint16 level) const { return evalMipNumTexels(level) * getTexelFormat().getSize(); } - uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); } - - uint32 evalTotalSize() const { - uint32 size = 0; - uint16 minMipLevel = 0; - uint16 maxMipLevel = maxMip(); - for (uint16 l = minMipLevel; l <= maxMipLevel; l++) { - size += evalMipSize(l); - } - 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 - uint16 maxMip() const; - - // Generate the mips automatically - // But the sysmem version is not available - // Only works for the standard formats - // Specify the maximum Mip level available - // 0 is the default one - // 1 is the first level - // ... - // nbMips - 1 is the last mip level - // - // If -1 then all the mips are generated - // - // Return the totalnumber of mips that will be available - 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 - // Explicitely assign mip data for a certain level - // 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); - - // 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; + // Resize, unless auto mips mode would destroy all the sub mips + Size resize1D(uint16 width, uint16 numSamples); + Size resize2D(uint16 width, uint16 height, uint16 numSamples); + Size resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples); + Size resizeCube(uint16 width, uint16 numSamples); + + // Reformat, unless auto mips mode would destroy all the sub mips + Size reformat(const Element& texelFormat); + + // Size and format + Type getType() const { return _type; } + + bool isColorRenderTarget() const; + bool isDepthStencilRenderTarget() const; + + const Element& getTexelFormat() const { return _texelFormat; } + bool hasBorder() const { return false; } + + uint16 getWidth() const { return _width; } + uint16 getHeight() const { return _height; } + uint16 getDepth() const { return _depth; } + + uint32 getRowPitch() const { return getWidth() * getTexelFormat().getSize(); } + uint32 getNumTexels() const { return _width * _height * _depth; } + + uint16 getNumSlices() const { return _numSlices; } + uint16 getNumSamples() const { return _numSamples; } + + // 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) + static uint16 evalDimNumMips(uint16 size); + + // The number mips that the texture could have if all existed + // = 1 + log2(max(width, height, depth)) + uint16 evalNumMips() const; + + // Eval the size that the mips level SHOULD have + // not the one stored in the Texture + uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); } + uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); } + uint16 evalMipDepth(uint16 level) const { return std::max(_depth >> level, 1); } + uint32 evalMipNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); } + uint32 evalMipSize(uint16 level) const { return evalMipNumTexels(level) * getTexelFormat().getSize(); } + uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); } + + uint32 evalTotalSize() const { + uint32 size = 0; + uint16 minMipLevel = 0; + uint16 maxMipLevel = maxMip(); + for (uint16 l = minMipLevel; l <= maxMipLevel; l++) { + size += evalMipSize(l); + } + 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 + uint16 maxMip() const; + + // Generate the mips automatically + // But the sysmem version is not available + // Only works for the standard formats + // Specify the maximum Mip level available + // 0 is the default one + // 1 is the first level + // ... + // nbMips - 1 is the last mip level + // + // If -1 then all the mips are generated + // + // Return the totalnumber of mips that will be available + 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 + // Explicitely assign mip data for a certain level + // 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); + + // 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; bool isDefined() const { return _defined; } protected: std::unique_ptr< Storage > _storage; - - Stamp _stamp; - - uint32 _size; - Element _texelFormat; - - uint16 _width; - uint16 _height; - uint16 _depth; - - uint16 _numSlices; - uint16 _numSamples; - - uint16 _maxMip; - - Type _type; - bool _autoGenerateMips; + + Stamp _stamp; + + uint32 _size; + Element _texelFormat; + + uint16 _width; + uint16 _height; + uint16 _depth; + + uint16 _numSamples; + uint16 _numSlices; + + uint16 _maxMip; + + 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, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); + + static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); + Texture(); + + Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); mutable GPUObject* _gpuObject = NULL; From 49dde269a6435bc0c0e72177984284cd879c3465 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 22 Jan 2015 16:27:17 -0800 Subject: [PATCH 05/21] experimenting with linear space vs srgb space --- libraries/fbx/src/FBXReader.cpp | 3 +- libraries/gpu/src/gpu/Format.h | 8 +++-- libraries/gpu/src/gpu/GLBackend.cpp | 2 +- libraries/gpu/src/gpu/GLBackend.h | 2 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 37 ++++++++++++++++---- libraries/gpu/src/gpu/Texture.cpp | 6 +++- libraries/gpu/src/gpu/Texture.h | 11 +++--- libraries/render-utils/src/GeometryCache.cpp | 4 +-- libraries/render-utils/src/TextRenderer.cpp | 2 +- libraries/render-utils/src/TextureCache.cpp | 35 ++++++++++-------- libraries/render-utils/src/TextureCache.h | 3 +- 11 files changed, 75 insertions(+), 38 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 89a46f2be9..3015de52ff 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -272,8 +272,7 @@ FBXNode parseBinaryFBXNode(QDataStream& in, int& position) { position += nameLength; for (quint32 i = 0; i < propertyCount; i++) { - QVariant var = parseBinaryFBXProperty(in, position); - node.properties.append(var); + node.properties.append(parseBinaryFBXProperty(in, position)); } while (endOffset > position) { diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 35876ffffa..6274c294ec 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -93,15 +93,13 @@ static const int DIMENSION_COUNT[NUM_DIMENSIONS] = { // Provide information on how to use the element enum Semantic { RAW = 0, // used as RAW memory + RGB, RGBA, BGRA, XYZ, XYZW, - POS_XYZ, - POS_XYZW, QUAT, - DIR_XYZ, UV, INDEX, //used by index buffer of a mesh PART, // used by part buffer of a mesh @@ -109,6 +107,10 @@ enum Semantic { DEPTH, // Depth buffer DEPTH_STENCIL, // Depth Stencil buffer + SRGB, + SRGBA, + SBGRA, + NUM_SEMANTICS, }; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index e2f923f369..519b20eca7 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -472,7 +472,7 @@ void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 1]._uint; TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); - GLuint to = getTextureID(*uniformTexture); + GLuint to = getTextureID(uniformTexture); glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(GL_TEXTURE_2D, to); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index a15de87afd..a3f3495853 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -55,7 +55,7 @@ public: ~GLTexture(); }; static void syncGPUObject(const Texture& texture); - static GLuint getTextureID(const Texture& texture); + static GLuint getTextureID(const TexturePointer& texture); static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index d416b5b7c9..075fd7ad71 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -94,10 +94,13 @@ public: switch(srcFormat.getSemantic()) { case gpu::BGRA: + case gpu::SBGRA: texel.format = GL_BGRA; break; case gpu::RGB: case gpu::RGBA: + case gpu::SRGB: + case gpu::SRGBA: default: break; }; @@ -109,6 +112,12 @@ public: case gpu::RGBA: texel.internalFormat = GL_RGBA; break; + case gpu::SRGB: + texel.internalFormat = GL_SRGB; + break; + case gpu::SRGBA: + texel.internalFormat = GL_SRGB_ALPHA; + break; default: qDebug() << "Unknown combination of texel format"; } @@ -170,6 +179,10 @@ public: case gpu::RGBA: texel.internalFormat = GL_RGB; break; + case gpu::SRGB: + case gpu::SRGBA: + texel.internalFormat = GL_SRGB; // standard 2.2 gamma correction color + break; default: qDebug() << "Unknown combination of texel format"; } @@ -187,6 +200,12 @@ public: case gpu::RGBA: texel.internalFormat = GL_RGBA; break; + case gpu::SRGB: + texel.internalFormat = GL_SRGB; + break; + case gpu::SRGBA: + texel.internalFormat = GL_SRGB_ALPHA; // standard 2.2 gamma correction color + break; default: qDebug() << "Unknown combination of texel format"; } @@ -295,13 +314,17 @@ void GLBackend::syncGPUObject(const Texture& texture) { -GLuint GLBackend::getTextureID(const Texture& texture) { - GLBackend::syncGPUObject(texture); - GLTexture* object = Backend::getGPUObject(texture); - if (object) { - return object->_texture; - } else { +GLuint GLBackend::getTextureID(const TexturePointer& texture) { + if (texture) { + GLBackend::syncGPUObject(*texture); + GLTexture* object = Backend::getGPUObject(*texture); + if (object) { + return object->_texture; + } else { + return 0; + } + } else { return 0; - } + } } diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 736545e758..1ba0e831f4 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -23,6 +23,10 @@ Texture::Pixels::Pixels(const Element& format, Size size, const Byte* bytes) : Texture::Pixels::~Pixels() { } +void Texture::Storage::assignTexture(Texture* texture) { + _texture = texture; +} + Stamp Texture::Storage::getStamp(uint16 level) const { PixelsPointer mip = getMip(level); if (mip) { @@ -111,7 +115,7 @@ Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, ui Texture* Texture::createFromStorage(Storage* storage) { Texture* tex = new Texture(); tex->_storage.reset(storage); - storage->_texture = tex; + storage->assignTexture(tex); return tex; } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 8b8fcf6c04..f50be9e14e 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -32,10 +32,7 @@ public: typedef QSharedPointer< Pixels > PixelsPointer; class Storage { - Texture* _texture; - std::vector _mips; public: - Storage() {} virtual ~Storage() {} virtual void reset(); @@ -45,7 +42,13 @@ public: virtual bool allocateMip(uint16 level); virtual bool assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes); virtual bool isMipAvailable(uint16 level) const; - + + protected: + Texture* _texture; + std::vector _mips; + + virtual void assignTexture(Texture* tex); + friend class Texture; }; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 3806599cbf..0d9fb6f60e 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -2068,7 +2068,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int channelNum = 0; networkMesh._vertexFormat = gpu::Stream::FormatPointer(new gpu::Stream::Format()); - networkMesh._vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::POS_XYZ), 0); + networkMesh._vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::NORMAL, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); @@ -2102,7 +2102,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int channelNum = 0; networkMesh._vertexFormat = gpu::Stream::FormatPointer(new gpu::Stream::Format()); - networkMesh._vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::POS_XYZ)); + networkMesh._vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::NORMAL, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); diff --git a/libraries/render-utils/src/TextRenderer.cpp b/libraries/render-utils/src/TextRenderer.cpp index 2c677a330a..ae7523a817 100644 --- a/libraries/render-utils/src/TextRenderer.cpp +++ b/libraries/render-utils/src/TextRenderer.cpp @@ -167,7 +167,7 @@ TextRenderer::TextRenderer(const Properties& properties) : _glyphsStream(new gpu::BufferStream()), _numGlyphsBatched(0) { - _glyphsStreamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::POS_XYZ), 0); + _glyphsStreamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); const int NUM_POS_COORDS = 2; const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); _glyphsStreamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index cfd3218e5c..2de40143d5 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -531,13 +531,17 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo finishedLoading(true); imageLoaded(image); - 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()); - _gpuTexture->autoGenerateMips(-1); - } else { - _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), image.width(), image.height())); - _gpuTexture->assignStoredMip(0, gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), image.byteCount(), image.constBits()); + if ((_width > 0) && (_height > 0)) { + bool isLinearRGB = (_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); + + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + if (image.hasAlphaChannel()) { + formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + } + _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height())); + _gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); _gpuTexture->autoGenerateMips(-1); } } @@ -567,16 +571,17 @@ 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(); - + + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (_type == NORMAL_TEXTURE ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (_type == NORMAL_TEXTURE ? gpu::RGB : gpu::SRGB)); 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()); - texture->_gpuTexture->autoGenerateMips(-1); - } else { - texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), dilatedImage.width(), dilatedImage.height())); - texture->_gpuTexture->assignStoredMip(0, gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), dilatedImage.byteCount(), dilatedImage.constBits()); - texture->_gpuTexture->autoGenerateMips(-1); + formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (_type == NORMAL_TEXTURE ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (_type == NORMAL_TEXTURE ? gpu::BGRA : gpu::BGRA)); } + texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, dilatedImage.width(), dilatedImage.height())); + texture->_gpuTexture->assignStoredMip(0, formatMip, dilatedImage.byteCount(), dilatedImage.constBits()); + texture->_gpuTexture->autoGenerateMips(-1); + } _dilatedTextures.insert(dilation, texture); diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 6ce1fc80fc..4754991a11 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -168,8 +168,9 @@ protected: virtual void imageLoaded(const QImage& image); -private: TextureType _type; + +private: bool _translucent; QColor _averageColor; int _width; From 80784a7a3364a38311597291db1a1975db7bfac1 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 22 Jan 2015 16:57:33 -0800 Subject: [PATCH 06/21] fixing a bug in texture storage when accessing mip #0 --- libraries/gpu/src/gpu/Texture.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 1ba0e831f4..83e97bb3ae 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -41,18 +41,18 @@ void Texture::Storage::reset() { } Texture::PixelsPointer Texture::Storage::editMip(uint16 level) { - if (level > _mips.size()) { - return PixelsPointer(); - } else { + if (level < _mips.size()) { return _mips[level]; + } else { + return PixelsPointer(); } } const Texture::PixelsPointer Texture::Storage::getMip(uint16 level) const { - if (level > _mips.size()) { - return PixelsPointer(); - } else { + if (level < _mips.size()) { return _mips[level]; + } else { + return PixelsPointer(); } } From 22347dd794f5dbbc481ca4274f3dbd317021b19c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 22 Jan 2015 19:11:55 -0800 Subject: [PATCH 07/21] Add AudioDevice.deviceChanged() signal and use to update audio menu --- examples/selectAudioDevice.js | 10 ++++++++- interface/src/Audio.cpp | 21 +++++++++++++++++++ interface/src/Audio.h | 5 +++++ .../AudioDeviceScriptingInterface.cpp | 2 ++ .../scripting/AudioDeviceScriptingInterface.h | 1 + 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/examples/selectAudioDevice.js b/examples/selectAudioDevice.js index a90f3da4cf..440580b883 100644 --- a/examples/selectAudioDevice.js +++ b/examples/selectAudioDevice.js @@ -98,8 +98,16 @@ function setupAudioMenus() { } } +function onDevicechanged() { + Menu.removeMenu("Tools > Audio"); + setupAudioMenus(); +} + // Have a small delay before the menu's get setup and the audio devices can switch to the last selected ones -Script.setTimeout(function() { setupAudioMenus(); }, 5000); +Script.setTimeout(function () { + AudioDevice.deviceChanged.connect(onDevicechanged); + setupAudioMenus(); +}, 5000); function scriptEnding() { Menu.removeMenu("Tools > Audio"); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index ce50e093e4..0a3e019a13 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -99,6 +99,15 @@ Audio::Audio() : // Initialize GVerb initGverb(); + + const qint64 DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000; + + _inputDevices = getDeviceNames(QAudio::AudioInput); + _outputDevices = getDeviceNames(QAudio::AudioOutput); + + QTimer* updateTimer = new QTimer(this); + connect(updateTimer, &QTimer::timeout, this, &Audio::checkDevices); + updateTimer->start(DEVICE_CHECK_INTERVAL_MSECS); } void Audio::reset() { @@ -1106,3 +1115,15 @@ qint64 Audio::AudioOutputIODevice::readData(char * data, qint64 maxSize) { return bytesWritten; } + +void Audio::checkDevices() { + QVector inputDevices = getDeviceNames(QAudio::AudioInput); + QVector outputDevices = getDeviceNames(QAudio::AudioOutput); + + if (inputDevices != _inputDevices || outputDevices != _outputDevices) { + _inputDevices = inputDevices; + _outputDevices = outputDevices; + + emit deviceChanged(); + } +} diff --git a/interface/src/Audio.h b/interface/src/Audio.h index abf322627b..eac081405c 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -177,6 +177,7 @@ public slots: signals: bool muteToggled(); void inputReceived(const QByteArray& inputSamples); + void deviceChanged(); protected: Audio(); @@ -275,6 +276,10 @@ private: AudioIOStats _stats; AudioNoiseGate _inputGate; + + QVector _inputDevices; + QVector _outputDevices; + void checkDevices(); }; diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.cpp b/interface/src/scripting/AudioDeviceScriptingInterface.cpp index 1ba47fb792..2b821d7c4a 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.cpp +++ b/interface/src/scripting/AudioDeviceScriptingInterface.cpp @@ -21,6 +21,8 @@ AudioDeviceScriptingInterface* AudioDeviceScriptingInterface::getInstance() { AudioDeviceScriptingInterface::AudioDeviceScriptingInterface() { connect(DependencyManager::get