No-context texture constructor (OpenGL only for now)

This commit is contained in:
Jack Andersen 2016-02-15 19:47:09 -10:00
parent 8ce4e6ffd3
commit 1ab63cfb18
3 changed files with 56 additions and 25 deletions

View File

@ -34,8 +34,9 @@ public:
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz); const void* data, size_t sz);
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, GraphicsDataToken
std::unique_ptr<uint8_t[]>&& data, size_t sz); newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz, ITextureS** texOut);
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz); const void* data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);

View File

@ -201,9 +201,9 @@ struct IGraphicsDataFactory
virtual ITextureS* virtual ITextureS*
newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz)=0; const void* data, size_t sz)=0;
virtual ITextureS* virtual GraphicsDataToken
newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
std::unique_ptr<uint8_t[]>&& data, size_t sz)=0; const void* data, size_t sz, ITextureS** texOut)=0;
virtual ITextureSA* virtual ITextureSA*
newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz)=0; const void* data, size_t sz)=0;

View File

@ -133,6 +133,7 @@ class GLTextureS : public ITextureS
GLenum intFormat, format; GLenum intFormat, format;
int pxPitch; int pxPitch;
bool compressed = false;
switch (fmt) switch (fmt)
{ {
case TextureFormat::RGBA8: case TextureFormat::RGBA8:
@ -145,16 +146,34 @@ class GLTextureS : public ITextureS
format = GL_RED; format = GL_RED;
pxPitch = 1; pxPitch = 1;
break; break;
case TextureFormat::DXT1:
intFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
compressed = true;
break;
default: default:
Log.report(LogVisor::FatalError, "unsupported tex format"); Log.report(LogVisor::FatalError, "unsupported tex format");
} }
for (size_t i=0 ; i<mips ; ++i) if (compressed)
{ {
glTexImage2D(GL_TEXTURE_2D, i, intFormat, width, height, 0, format, GL_UNSIGNED_BYTE, dataIt); for (size_t i=0 ; i<mips ; ++i)
dataIt += width * height * pxPitch; {
width /= 2; size_t dataSz = width * height / 2;
height /= 2; glCompressedTexImage2D(GL_TEXTURE_2D, i, intFormat, width, height, 0, dataSz, dataIt);
dataIt += dataSz;
width /= 2;
height /= 2;
}
}
else
{
for (size_t i=0 ; i<mips ; ++i)
{
glTexImage2D(GL_TEXTURE_2D, i, intFormat, width, height, 0, format, GL_UNSIGNED_BYTE, dataIt);
dataIt += width * height * pxPitch;
width /= 2;
height /= 2;
}
} }
} }
public: public:
@ -270,16 +289,23 @@ GLDataFactory::newStaticTexture(size_t width, size_t height, size_t mips, Textur
return retval; return retval;
} }
ITextureS* GraphicsDataToken
GLDataFactory::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, GLDataFactory::newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
std::unique_ptr<uint8_t[]>&& data, size_t sz) const void* data, size_t sz, ITextureS** texOut)
{ {
std::unique_ptr<uint8_t[]> d = std::move(data); GLTextureS* retval = new GLTextureS(width, height, mips, fmt, data, sz);
GLTextureS* retval = new GLTextureS(width, height, mips, fmt, d.get(), sz); GLData* tokData = new struct GLData();
if (!m_deferredData.get()) tokData->m_STexs.emplace_back(retval);
m_deferredData.reset(new struct GLData()); *texOut = retval;
m_deferredData->m_STexs.emplace_back(retval);
return retval; std::unique_lock<std::mutex> lk(m_committedMutex);
m_committedData.insert(tokData);
lk.unlock();
/* Let's go ahead and flush to ensure our data gets to the GPU
While this isn't strictly required, some drivers might behave
differently */
glFlush();
return GraphicsDataToken(this, tokData);
} }
ITextureSA* ITextureSA*
@ -471,7 +497,7 @@ IShaderPipeline* GLDataFactory::newShaderPipeline
{ {
GLint uniLoc = glGetUniformBlockIndex(shader.m_prog, uniformBlockNames[i]); GLint uniLoc = glGetUniformBlockIndex(shader.m_prog, uniformBlockNames[i]);
if (uniLoc < 0) if (uniLoc < 0)
Log.report(LogVisor::FatalError, "unable to find uniform block '%s'", uniformBlockNames[i]); Log.report(LogVisor::Error, "unable to find uniform block '%s'", uniformBlockNames[i]);
shader.m_uniLocs.push_back(uniLoc); shader.m_uniLocs.push_back(uniLoc);
} }
} }
@ -480,11 +506,14 @@ IShaderPipeline* GLDataFactory::newShaderPipeline
{ {
GLint texLoc = glGetUniformLocation(shader.m_prog, texArrayName); GLint texLoc = glGetUniformLocation(shader.m_prog, texArrayName);
if (texLoc < 0) if (texLoc < 0)
Log.report(LogVisor::FatalError, "unable to find sampler variable '%s'", texArrayName); Log.report(LogVisor::Error, "unable to find sampler variable '%s'", texArrayName);
if (texCount > m_texUnis.size()) else
for (size_t i=m_texUnis.size() ; i<texCount ; ++i) {
m_texUnis.push_back(i); if (texCount > m_texUnis.size())
glUniform1iv(texLoc, m_texUnis.size(), m_texUnis.data()); for (size_t i=m_texUnis.size() ; i<texCount ; ++i)
m_texUnis.push_back(i);
glUniform1iv(texLoc, m_texUnis.size(), m_texUnis.data());
}
} }
GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader)); GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader));
@ -611,6 +640,7 @@ GraphicsDataToken GLDataFactory::commit()
#endif #endif
m_deferredData.reset(); m_deferredData.reset();
m_committedData.insert(retval); m_committedData.insert(retval);
lk.unlock();
/* Let's go ahead and flush to ensure our data gets to the GPU /* Let's go ahead and flush to ensure our data gets to the GPU
While this isn't strictly required, some drivers might behave While this isn't strictly required, some drivers might behave
differently */ differently */