Implementation of sRGB image support. Overhauls the linearization setup to utilize the sRGB image types, as well as refactors the use of ColorF and ColorI to be properly internally consistent. ColorIs are used only for front-facing/editing/UI settings, and ColorFs, now renamed to LinearColorF to reduce confusion of purpose, are used for color info in the engine itself. This avoids confusing and expensive conversions back and forth between types and avoids botches with linearity. Majority work done by @rextimmy

This commit is contained in:
Areloch 2017-06-23 11:36:20 -05:00
parent 8780f83262
commit 25686ed4be
294 changed files with 3894 additions and 2813 deletions

View file

@ -28,6 +28,7 @@
#include "gfx/gfxTextureManager.h"
#include "gfx/gfxCardProfile.h"
#include "gfx/bitmap/ddsFile.h"
#include "gfx/bitmap/imageUtils.h"
GLenum GFXGLCubemap::faceList[6] =
@ -71,11 +72,11 @@ void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces)
U32 reqWidth = faces[0]->getWidth();
U32 reqHeight = faces[0]->getHeight();
GFXFormat regFaceFormat = faces[0]->getFormat();
const bool isCompressed = isCompressedFormat(regFaceFormat);
const bool isCompressed = ImageUtil::isCompressedFormat(regFaceFormat);
mWidth = reqWidth;
mHeight = reqHeight;
mFaceFormat = regFaceFormat;
mMipLevels = getMax( (U32)1, faces[0]->mMipLevels);
mMipMapLevels = getMax( (U32)1, faces[0]->mMipLevels);
AssertFatal(reqWidth == reqHeight, "GFXGLCubemap::fillCubeTextures - Width and height must be equal!");
for(U32 i = 0; i < 6; i++)
@ -90,7 +91,7 @@ void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces)
GFXGLTextureObject* glTex = static_cast<GFXGLTextureObject*>(faces[i].getPointer());
if( isCompressed )
{
for( U32 mip = 0; mip < mMipLevels; ++mip )
for( U32 mip = 0; mip < mMipMapLevels; ++mip )
{
const U32 mipWidth = getMax( U32(1), faces[i]->getWidth() >> mip );
const U32 mipHeight = getMax( U32(1), faces[i]->getHeight() >> mip );
@ -136,26 +137,16 @@ void GFXGLCubemap::initStatic( DDSFile *dds )
AssertFatal( dds->isCubemap(), "GFXGLCubemap::initStatic - Got non-cubemap DDS file!" );
AssertFatal( dds->mSurfaces.size() == 6, "GFXGLCubemap::initStatic - DDS has less than 6 surfaces!" );
// HACK: I cannot put the genie back in the bottle and assign a
// DDSFile pointer back to a Resource<>.
//
// So we do a second lookup which works out ok for now, but shows
// the weakness in the ResourceManager not having a common base
// reference type.
//
mDDSFile = ResourceManager::get().load( dds->getSourcePath() );
AssertFatal( mDDSFile == dds, "GFXGLCubemap::initStatic - Couldn't find DDSFile resource!" );
mWidth = dds->getWidth();
mHeight = dds->getHeight();
mFaceFormat = dds->getFormat();
mMipLevels = dds->getMipLevels();
mMipMapLevels = dds->getMipLevels();
const bool isCompressed = ImageUtil::isCompressedFormat(mFaceFormat);
glGenTextures(1, &mCubemap);
PRESERVE_CUBEMAP_TEXTURE();
glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, mMipLevels - 1);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, mMipMapLevels - 1);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -173,12 +164,19 @@ void GFXGLCubemap::initStatic( DDSFile *dds )
continue;
}
// convert to Z up
const U32 faceIndex = _zUpFaceIndex(i);
// Now loop thru the mip levels!
for (U32 mip = 0; mip < mMipLevels; ++mip)
for (U32 mip = 0; mip < mMipMapLevels; ++mip)
{
const U32 mipWidth = getMax( U32(1), mWidth >> mip );
const U32 mipHeight = getMax( U32(1), mHeight >> mip );
glCompressedTexImage2D(faceList[i], mip, GFXGLTextureInternalFormat[mFaceFormat], mipWidth, mipHeight, 0, dds->getSurfaceSize(mip), dds->mSurfaces[i]->mMips[mip]);
if (isCompressed)
glCompressedTexImage2D(faceList[faceIndex], mip, GFXGLTextureInternalFormat[mFaceFormat], mipWidth, mipHeight, 0, dds->getSurfaceSize(mip), dds->mSurfaces[i]->mMips[mip]);
else
glTexImage2D(faceList[faceIndex], mip, GFXGLTextureInternalFormat[mFaceFormat], mipWidth, mipHeight, 0,
GFXGLTextureFormat[mFaceFormat], GFXGLTextureType[mFaceFormat], dds->mSurfaces[i]->mMips[mip]);
}
}
}
@ -187,13 +185,13 @@ void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
{
mDynamicTexSize = texSize;
mFaceFormat = faceFormat;
const bool isCompressed = isCompressedFormat(faceFormat);
mMipLevels = getMax( (U32)1, getMaxMipmaps( texSize, texSize, 1 ) );
const bool isCompressed = ImageUtil::isCompressedFormat(faceFormat);
mMipMapLevels = getMax( (U32)1, getMaxMipmaps( texSize, texSize, 1 ) );
glGenTextures(1, &mCubemap);
PRESERVE_CUBEMAP_TEXTURE();
glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, mMipLevels - 1);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, mMipMapLevels - 1);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -204,9 +202,9 @@ void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
for(U32 i = 0; i < 6; i++)
{
if( isCompressedFormat(faceFormat) )
if( ImageUtil::isCompressedFormat(faceFormat) )
{
for( U32 mip = 0; mip < mMipLevels; ++mip )
for( U32 mip = 0; mip < mMipMapLevels; ++mip )
{
const U32 mipSize = getMax( U32(1), texSize >> mip );
const U32 mipDataSize = getCompressedSurfaceSize( mFaceFormat, texSize, texSize, mip );

View file

@ -46,7 +46,6 @@ public:
// Convenience methods for GFXGLTextureTarget
U32 getWidth() { return mWidth; }
U32 getHeight() { return mHeight; }
U32 getNumMipLevels() { return mMipLevels; }
U32 getHandle() { return mCubemap; }
// GFXResource interface
@ -73,7 +72,6 @@ protected:
// Self explanatory
U32 mWidth;
U32 mHeight;
U32 mMipLevels;
GFXFormat mFaceFormat;
GFXTexHandle mTextures[6]; ///< Keep refs to our textures for resurrection of static cubemaps

View file

@ -180,6 +180,9 @@ void GFXGLDevice::initGLState()
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//enable sRGB
glEnable(GL_FRAMEBUFFER_SRGB);
}
void GFXGLDevice::vsyncCallback()
@ -450,7 +453,7 @@ void GFXGLDevice::endSceneInternal()
mCanCurrentlyRender = false;
}
void GFXGLDevice::clear(U32 flags, ColorI color, F32 z, U32 stencil)
void GFXGLDevice::clear(U32 flags, const LinearColorF& color, F32 z, U32 stencil)
{
// Make sure we have flushed our render target state.
_updateRenderTargets();
@ -470,10 +473,7 @@ void GFXGLDevice::clear(U32 flags, ColorI color, F32 z, U32 stencil)
glColorMask(true, true, true, true);
glDepthMask(true);
glStencilMask(0xFFFFFFFF);
ColorF c = color;
glClearColor(c.red, c.green, c.blue, c.alpha);
glClearColor(color.red, color.green, color.blue, color.alpha);
glClearDepth(z);
glClearStencil(stencil);
@ -581,7 +581,8 @@ void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32
{
preDrawPrimitive();
vertexStart += mCurrentVB[0]->mBufferVertexOffset;
if(mCurrentVB[0])
vertexStart += mCurrentVB[0]->mBufferVertexOffset;
if(mDrawInstancesCount)
glDrawArraysInstanced(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount);
@ -629,7 +630,7 @@ void GFXGLDevice::setLightMaterialInternal(const GFXLightMaterial mat)
// ONLY NEEDED ON FFP
}
void GFXGLDevice::setGlobalAmbientInternal(ColorF color)
void GFXGLDevice::setGlobalAmbientInternal(LinearColorF color)
{
// ONLY NEEDED ON FFP
}

View file

@ -116,7 +116,7 @@ public:
virtual GFXShader* createShader();
virtual void clear( U32 flags, ColorI color, F32 z, U32 stencil );
virtual void clear( U32 flags, const LinearColorF& color, F32 z, U32 stencil );
virtual bool beginSceneInternal();
virtual void endSceneInternal();
@ -171,7 +171,7 @@ protected:
virtual void setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable);
virtual void setLightMaterialInternal(const GFXLightMaterial mat);
virtual void setGlobalAmbientInternal(ColorF color);
virtual void setGlobalAmbientInternal(LinearColorF color);
/// @name State Initalization.
/// @{

View file

@ -142,11 +142,17 @@ void GFXGLEnumTranslate::init()
GFXGLTextureInternalFormat[GFXFormatD24X8] = GL_DEPTH24_STENCIL8;
GFXGLTextureInternalFormat[GFXFormatD24S8] = GL_DEPTH24_STENCIL8;
GFXGLTextureInternalFormat[GFXFormatR16G16B16A16] = GL_RGBA16;
GFXGLTextureInternalFormat[GFXFormatDXT1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
GFXGLTextureInternalFormat[GFXFormatDXT2] = GL_ZERO;
GFXGLTextureInternalFormat[GFXFormatDXT3] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
GFXGLTextureInternalFormat[GFXFormatDXT4] = GL_ZERO;
GFXGLTextureInternalFormat[GFXFormatDXT5] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
GFXGLTextureInternalFormat[GFXFormatBC1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
GFXGLTextureInternalFormat[GFXFormatBC2] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
GFXGLTextureInternalFormat[GFXFormatBC3] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
GFXGLTextureInternalFormat[GFXFormatBC4] = GL_COMPRESSED_RED_RGTC1;
GFXGLTextureInternalFormat[GFXFormatBC5] = GL_COMPRESSED_RG_RGTC2;
//sRGB
GFXGLTextureInternalFormat[GFXFormatR8G8B8_SRGB] = GL_SRGB8;
GFXGLTextureInternalFormat[GFXFormatR8G8B8A8_SRGB] = GL_SRGB8_ALPHA8;
GFXGLTextureInternalFormat[GFXFormatBC1_SRGB] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
GFXGLTextureInternalFormat[GFXFormatBC2_SRGB] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
GFXGLTextureInternalFormat[GFXFormatBC3_SRGB] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
GFXGLTextureFormat[GFXFormatA8] = GL_RED;
GFXGLTextureFormat[GFXFormatL8] = GL_RED;
@ -163,11 +169,17 @@ void GFXGLEnumTranslate::init()
GFXGLTextureFormat[GFXFormatD24X8] = GL_DEPTH_STENCIL;
GFXGLTextureFormat[GFXFormatD24S8] = GL_DEPTH_STENCIL;
GFXGLTextureFormat[GFXFormatR16G16B16A16] = GL_RGBA;
GFXGLTextureFormat[GFXFormatDXT1] = GL_RGBA;
GFXGLTextureFormat[GFXFormatDXT2] = GL_ZERO;
GFXGLTextureFormat[GFXFormatDXT3] = GL_RGBA;
GFXGLTextureFormat[GFXFormatDXT4] = GL_ZERO;
GFXGLTextureFormat[GFXFormatDXT5] = GL_RGBA;
GFXGLTextureFormat[GFXFormatBC1] = GL_RGBA;
GFXGLTextureFormat[GFXFormatBC2] = GL_RGBA;
GFXGLTextureFormat[GFXFormatBC3] = GL_RGBA;
GFXGLTextureFormat[GFXFormatBC4] = GL_RED;
GFXGLTextureFormat[GFXFormatBC5] = GL_RG;
//sRGB
GFXGLTextureFormat[GFXFormatR8G8B8_SRGB] = GL_RGB;
GFXGLTextureFormat[GFXFormatR8G8B8A8_SRGB] = GL_RGBA;
GFXGLTextureFormat[GFXFormatBC1_SRGB] = GL_RGBA;
GFXGLTextureFormat[GFXFormatBC2_SRGB] = GL_RGBA;
GFXGLTextureFormat[GFXFormatBC3_SRGB] = GL_RGBA;
GFXGLTextureType[GFXFormatA8] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatL8] = GL_UNSIGNED_BYTE;
@ -184,13 +196,18 @@ void GFXGLEnumTranslate::init()
GFXGLTextureType[GFXFormatD24X8] = GL_UNSIGNED_INT_24_8;
GFXGLTextureType[GFXFormatD24S8] = GL_UNSIGNED_INT_24_8;
GFXGLTextureType[GFXFormatR16G16B16A16] = GL_UNSIGNED_SHORT;
GFXGLTextureType[GFXFormatDXT1] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatDXT2] = GL_ZERO;
GFXGLTextureType[GFXFormatDXT3] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatDXT4] = GL_ZERO;
GFXGLTextureType[GFXFormatDXT5] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatBC1] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatBC2] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatBC3] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatBC4] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatBC5] = GL_UNSIGNED_BYTE;
// sRGB
GFXGLTextureType[GFXFormatR8G8B8_SRGB] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatR8G8B8A8_SRGB] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatBC1_SRGB] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatBC2_SRGB] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatBC3_SRGB] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatR8G8B8A8_SRGB] = GL_SRGB8_ALPHA8;
static GLint Swizzle_GFXFormatA8[] = { GL_NONE, GL_NONE, GL_NONE, GL_RED };
static GLint Swizzle_GFXFormatL[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };

View file

@ -197,7 +197,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv)
internalSet(handle, fv);
}
void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const ColorF& fv)
void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const LinearColorF& fv)
{
internalSet(handle, fv);
}
@ -423,17 +423,14 @@ bool GFXGLShader::_init()
Vector<GFXShaderMacro> macros;
macros.merge( mMacros );
macros.merge( smGlobalMacros );
// Add the shader version to the macros.
const U32 mjVer = (U32)mFloor( mPixVersion );
const U32 mnVer = (U32)( ( mPixVersion - F32( mjVer ) ) * 10.01f );
macros.increment();
macros.last().name = "TORQUE_SM";
macros.last().value = String::ToString( mjVer * 10 + mnVer );
macros.last().value = 40;
macros.increment();
macros.last().name = "TORQUE_VERTEX_SHADER";
macros.last().value = "";
macros.last().value = "";
// Default to true so we're "successful" if a vertex/pixel shader wasn't specified.
bool compiledVertexShader = true;
bool compiledPixelShader = true;

View file

@ -121,7 +121,7 @@ public:
virtual void set(GFXShaderConstHandle* handle, const Point3F& fv);
virtual void set(GFXShaderConstHandle* handle, const Point4F& fv);
virtual void set(GFXShaderConstHandle* handle, const PlaneF& fv);
virtual void set(GFXShaderConstHandle* handle, const ColorF& fv);
virtual void set(GFXShaderConstHandle* handle, const LinearColorF& fv);
virtual void set(GFXShaderConstHandle* handle, const S32 f);
virtual void set(GFXShaderConstHandle* handle, const Point2I& fv);
virtual void set(GFXShaderConstHandle* handle, const Point3I& fv);

View file

@ -58,7 +58,13 @@ GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) :
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
glSamplerParameteri(id, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
if(static_cast< GFXGLDevice* >( GFX )->supportsAnisotropic() )
//compare modes
const bool comparison = ssd.samplerFunc != GFXCmpNever;
glSamplerParameteri(id, GL_TEXTURE_COMPARE_MODE, comparison ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE );
glSamplerParameteri(id, GL_TEXTURE_COMPARE_FUNC, GFXGLCmpFunc[ssd.samplerFunc]);
if (static_cast< GFXGLDevice* >(GFX)->supportsAnisotropic())
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, ssd.maxAnisotropy);
mSamplersMap[ssd] = id;
@ -99,7 +105,7 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
#define STATE_CHANGE(state) (!oldState || oldState->mDesc.state != mDesc.state)
#define TOGGLE_STATE(state, enum) if(mDesc.state) glEnable(enum); else glDisable(enum)
#define CHECK_TOGGLE_STATE(state, enum) if(!oldState || oldState->mDesc.state != mDesc.state) {if(mDesc.state) glEnable(enum); else glDisable(enum);}
#define CHECK_TOGGLE_STATE(state, enum) if(!oldState || oldState->mDesc.state != mDesc.state) if(mDesc.state) glEnable(enum); else glDisable(enum)
// Blending
CHECK_TOGGLE_STATE(blendEnable, GL_BLEND);

View file

@ -92,8 +92,10 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
bool forceMips)
{
// No 24 bit formats. They trigger various oddities because hardware (and Apple's drivers apparently...) don't natively support them.
if(format == GFXFormatR8G8B8)
if (format == GFXFormatR8G8B8)
format = GFXFormatR8G8B8A8;
else if (format == GFXFormatR8G8B8_SRGB)
format = GFXFormatR8G8B8A8_SRGB;
retTex->mFormat = format;
retTex->mIsZombie = false;
@ -110,7 +112,7 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
// Create it
// @todo OPENGL - Creating mipmaps for compressed formats. Not supported on OpenGL ES and bugged on AMD. We use mipmaps present on file.
if( forceMips && !retTex->mIsNPoT2 && !isCompressedFormat(format) )
if( forceMips && !retTex->mIsNPoT2 && !ImageUtil::isCompressedFormat(format) )
{
retTex->mMipLevels = numMipLevels > 1 ? numMipLevels : 0;
}
@ -159,7 +161,7 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
{
//If it wasn't for problems on amd drivers this next part could be really simplified and we wouldn't need to go through manually creating our
//mipmap pyramid and instead just use glGenerateMipmap
if(isCompressedFormat(format))
if(ImageUtil::isCompressedFormat(format))
{
AssertFatal(binding == GL_TEXTURE_2D,
"GFXGLTextureManager::innerCreateTexture - Only compressed 2D textures are supported");
@ -226,40 +228,32 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
// loadTexture - GBitmap
//-----------------------------------------------------------------------------
static void _fastTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL)
static void _textureUpload(const S32 width, const S32 height,const S32 bytesPerPixel,const GFXGLTextureObject* texture, const GFXFormat fmt, const U8* data,const S32 mip=0, Swizzle<U8, 4> *pSwizzle = NULL)
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->getBuffer());
U32 bufSize = pDL->getWidth(0) * pDL->getHeight(0) * pDL->getBytesPerPixel();
U32 bufSize = width * height * bytesPerPixel;
glBufferData(GL_PIXEL_UNPACK_BUFFER, bufSize, NULL, GL_STREAM_DRAW);
if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8)
if(pSwizzle)
{
PROFILE_SCOPE(Swizzle32_Upload);
U8* pboMemory = (U8*)dMalloc(bufSize);
GFX->getDeviceSwizzle32()->ToBuffer(pboMemory, pDL->getBits(0), bufSize);
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, pboMemory );
pSwizzle->ToBuffer(pboMemory, data, bufSize);
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, pboMemory);
dFree(pboMemory);
}
else
{
PROFILE_SCOPE(SwizzleNull_Upload);
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, pDL->getBits(0) );
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, data);
}
if(texture->getBinding() == GL_TEXTURE_2D)
glTexSubImage2D(texture->getBinding(), 0, 0, 0, pDL->getWidth(0), pDL->getHeight(0), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], NULL);
else
glTexSubImage1D(texture->getBinding(), 0, 0, (pDL->getWidth(0) > 1 ? pDL->getWidth(0) : pDL->getHeight(0)), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
static void _slowTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL)
{
if(texture->getBinding() == GL_TEXTURE_2D)
glTexSubImage2D(texture->getBinding(), 0, 0, 0, pDL->getWidth(0), pDL->getHeight(0), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], pDL->getBits(0));
else
glTexSubImage1D(texture->getBinding(), 0, 0, (pDL->getWidth(0) > 1 ? pDL->getWidth(0) : pDL->getHeight(0)), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], pDL->getBits(0));
if (texture->getBinding() == GL_TEXTURE_2D)
glTexSubImage2D(texture->getBinding(), mip, 0, 0, width, height, GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL);
else
glTexSubImage1D(texture->getBinding(), mip, 0, (width > 1 ? width : height), GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)
@ -276,27 +270,22 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)
// No 24bit formats.
if(pDL->getFormat() == GFXFormatR8G8B8)
pDL->setFormat(GFXFormatR8G8B8A8);
else if (pDL->getFormat() == GFXFormatR8G8B8_SRGB)
pDL->setFormat(GFXFormatR8G8B8A8_SRGB);
// Bind to edit
PRESERVE_TEXTURE(texture->getBinding());
glBindTexture(texture->getBinding(), texture->getHandle());
texture->mFormat = pDL->getFormat();
if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8)
_fastTextureLoad(texture, pDL);
else
_slowTextureLoad(texture, pDL);
_textureUpload(pDL->getWidth(),pDL->getHeight(),pDL->getBytesPerPixel(),texture,pDL->getFormat(), pDL->getBits(), 0);
if(texture->getMipLevels() != 1)
glGenerateMipmap(texture->getBinding());
if(!ImageUtil::isCompressedFormat(pDL->getFormat()))
glGenerateMipmap(texture->getBinding());
return true;
}
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
{
PROFILE_SCOPE(GFXGLTextureManager_loadTextureDDS);
AssertFatal(!(dds->mFormat == GFXFormatDXT2 || dds->mFormat == GFXFormatDXT4), "GFXGLTextureManager::_loadTexture - OpenGL does not support DXT2 or DXT4 compressed textures");
GFXGLTextureObject* texture = static_cast<GFXGLTextureObject*>(aTexture);
AssertFatal(texture->getBinding() == GL_TEXTURE_2D,
@ -307,42 +296,36 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
PRESERVE_TEXTURE(texture->getBinding());
glBindTexture(texture->getBinding(), texture->getHandle());
texture->mFormat = dds->mFormat;
U32 numMips = dds->mSurfaces[0]->mMips.size();
const GFXFormat fmt = texture->mFormat;
for(U32 i = 0; i < numMips; i++)
{
PROFILE_SCOPE(GFXGLTexMan_loadSurface);
if(isCompressedFormat(dds->mFormat))
if(ImageUtil::isCompressedFormat(texture->mFormat))
{
if((!isPow2(dds->getWidth()) || !isPow2(dds->getHeight())))
if((!isPow2(dds->getWidth()) || !isPow2(dds->getHeight())) && GFX->getCardProfiler()->queryProfile("GL::Workaround::noCompressedNPoTTextures"))
{
U32 squishFlag = squish::kDxt1;
switch (dds->mFormat)
{
case GFXFormatDXT3:
squishFlag = squish::kDxt3;
break;
case GFXFormatDXT5:
squishFlag = squish::kDxt5;
break;
default:
break;
}
U8* uncompressedTex = new U8[dds->getWidth(i) * dds->getHeight(i) * 4];
squish::DecompressImage(uncompressedTex, dds->getWidth(i), dds->getHeight(i), dds->mSurfaces[0]->mMips[i], squishFlag);
ImageUtil::decompress(dds->mSurfaces[0]->mMips[i],uncompressedTex, dds->getWidth(i), dds->getHeight(i), fmt);
glTexSubImage2D(texture->getBinding(), i, 0, 0, dds->getWidth(i), dds->getHeight(i), GL_RGBA, GL_UNSIGNED_BYTE, uncompressedTex);
delete[] uncompressedTex;
}
else
glCompressedTexSubImage2D(texture->getBinding(), i, 0, 0, dds->getWidth(i), dds->getHeight(i), GFXGLTextureInternalFormat[dds->mFormat], dds->getSurfaceSize(dds->getHeight(), dds->getWidth(), i), dds->mSurfaces[0]->mMips[i]);
glCompressedTexSubImage2D(texture->getBinding(), i, 0, 0, dds->getWidth(i), dds->getHeight(i), GFXGLTextureInternalFormat[fmt], dds->getSurfaceSize(dds->getHeight(), dds->getWidth(), i), dds->mSurfaces[0]->mMips[i]);
}
else
glTexSubImage2D(texture->getBinding(), i, 0, 0, dds->getWidth(i), dds->getHeight(i), GFXGLTextureFormat[dds->mFormat], GFXGLTextureType[dds->mFormat], dds->mSurfaces[0]->mMips[i]);
{
Swizzle<U8, 4> *pSwizzle = NULL;
if (fmt == GFXFormatR8G8B8A8 || fmt == GFXFormatR8G8B8X8 || fmt == GFXFormatR8G8B8A8_SRGB || fmt == GFXFormatR8G8B8A8_LINEAR_FORCE || fmt == GFXFormatB8G8R8A8)
pSwizzle = &Swizzles::bgra;
_textureUpload(dds->getWidth(i), dds->getHeight(i),dds->mBytesPerPixel, texture, fmt, dds->mSurfaces[0]->mMips[i],i, pSwizzle);
}
}
if(numMips !=1 && !isCompressedFormat(dds->mFormat))
if(numMips !=1 && !ImageUtil::isCompressedFormat(texture->mFormat))
glGenerateMipmap(texture->getBinding());
return true;

View file

@ -57,7 +57,7 @@ GFXGLTextureObject::~GFXGLTextureObject()
GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel, RectI *inRect)
{
AssertFatal(mBinding != GL_TEXTURE_3D, "GFXGLTextureObject::lock - We don't support locking 3D textures yet");
//AssertFatal(mBinding != GL_TEXTURE_3D, "GFXGLTextureObject::lock - We don't support locking 3D textures yet");
U32 width = mTextureSize.x >> mipLevel;
U32 height = mTextureSize.y >> mipLevel;
@ -76,7 +76,7 @@ GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel, RectI *inRect)
mLockedRect.pitch = mLockedRectRect.extent.x * mBytesPerTexel;
// CodeReview [ags 12/19/07] This one texel boundary is necessary to keep the clipmap code from crashing. Figure out why.
U32 size = (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel;
U32 size = (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * getDepth() * mBytesPerTexel;
AssertFatal(!mFrameAllocatorMark && !mFrameAllocatorPtr, "");
mFrameAllocatorMark = FrameAllocator::getWaterMark();
mFrameAllocatorPtr = (U8*)FrameAllocator::alloc( size );
@ -103,8 +103,11 @@ void GFXGLTextureObject::unlock(U32 mipLevel)
glBindTexture(mBinding, mHandle);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mBuffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel, mFrameAllocatorPtr, GL_STREAM_DRAW);
if(mBinding == GL_TEXTURE_2D)
S32 z = getDepth();
if (mBinding == GL_TEXTURE_3D)
glTexSubImage3D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y, z,
mLockedRectRect.extent.x, mLockedRectRect.extent.y, z, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL);
else if(mBinding == GL_TEXTURE_2D)
glTexSubImage2D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y,
mLockedRectRect.extent.x, mLockedRectRect.extent.y, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL);
else if(mBinding == GL_TEXTURE_1D)
@ -146,12 +149,13 @@ bool GFXGLTextureObject::copyToBmp(GBitmap * bmp)
// check format limitations
// at the moment we only support RGBA for the source (other 4 byte formats should
// be easy to add though)
AssertFatal(mFormat == GFXFormatR8G8B8A8, "GFXGLTextureObject::copyToBmp - invalid format");
AssertFatal(bmp->getFormat() == GFXFormatR8G8B8A8 || bmp->getFormat() == GFXFormatR8G8B8, "GFXGLTextureObject::copyToBmp - invalid format");
if(mFormat != GFXFormatR8G8B8A8)
AssertFatal(mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8A8_SRGB , "GFXGLTextureObject::copyToBmp - invalid format");
AssertFatal(bmp->getFormat() == GFXFormatR8G8B8A8 || bmp->getFormat() == GFXFormatR8G8B8 || bmp->getFormat() == GFXFormatR8G8B8A8_SRGB, "GFXGLTextureObject::copyToBmp - invalid format");
if(mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8A8_SRGB)
return false;
if(bmp->getFormat() != GFXFormatR8G8B8A8 && bmp->getFormat() != GFXFormatR8G8B8)
if(bmp->getFormat() != GFXFormatR8G8B8A8 && bmp->getFormat() != GFXFormatR8G8B8 && bmp->getFormat() != GFXFormatR8G8B8A8_SRGB )
return false;
AssertFatal(bmp->getWidth() == getWidth(), "GFXGLTextureObject::copyToBmp - invalid size");
@ -253,7 +257,7 @@ U8* GFXGLTextureObject::getTextureData( U32 mip )
AssertFatal( mMipLevels, "");
mip = (mip < mMipLevels) ? mip : 0;
const U32 dataSize = isCompressedFormat(mFormat)
const U32 dataSize = ImageUtil::isCompressedFormat(mFormat)
? getCompressedSurfaceSize( mFormat, mTextureSize.x, mTextureSize.y, mip )
: (mTextureSize.x >> mip) * (mTextureSize.y >> mip) * mBytesPerTexel;
@ -261,7 +265,7 @@ U8* GFXGLTextureObject::getTextureData( U32 mip )
PRESERVE_TEXTURE(mBinding);
glBindTexture(mBinding, mHandle);
if( isCompressedFormat(mFormat) )
if( ImageUtil::isCompressedFormat(mFormat) )
glGetCompressedTexImage( mBinding, mip, data );
else
glGetTexImage(mBinding, mip, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], data);

View file

@ -103,7 +103,7 @@ public:
virtual U32 getWidth() { return mTex->getWidth(); }
virtual U32 getHeight() { return mTex->getHeight(); }
virtual U32 getDepth() { return 0; }
virtual bool hasMips() { return mTex->getNumMipLevels() != 1; }
virtual bool hasMips() { return mTex->getMipMapLevels() != 1; }
virtual GLenum getBinding() { return GFXGLCubemap::getEnumForFaceNumber(mFace); }
virtual GFXFormat getFormat() { return mTex->getFormat(); }
virtual bool isCompatible(const GFXGLTextureObject* tex)
@ -162,7 +162,7 @@ void _GFXGLTextureTargetFBOImpl::applyState()
PRESERVE_FRAMEBUFFER();
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
glEnable(GL_FRAMEBUFFER_SRGB);
bool drawbufs[16];
int bufsize = 0;
for (int i = 0; i < 16; i++)

View file

@ -26,6 +26,7 @@
#include "core/util/preprocessorHelpers.h"
#include "gfx/gl/gfxGLEnumTranslate.h"
#include "gfx/gl/gfxGLStateCache.h"
#include "gfx/bitmap/imageUtils.h"
inline U32 getMaxMipmaps(U32 width, U32 height, U32 depth)
{
@ -59,27 +60,10 @@ inline GLenum minificationFilter(U32 minFilter, U32 mipFilter, U32 /*mipLevels*/
}
}
// Check if format is compressed format.
// Even though dxt2/4 are not supported, they are included because they are a compressed format.
// Assert checks on supported formats are done elsewhere.
inline bool isCompressedFormat( GFXFormat format )
{
bool compressed = false;
if(format == GFXFormatDXT1 || format == GFXFormatDXT2
|| format == GFXFormatDXT3
|| format == GFXFormatDXT4
|| format == GFXFormatDXT5 )
{
compressed = true;
}
return compressed;
}
//Get the surface size of a compressed mip map level - see ddsLoader.cpp
inline U32 getCompressedSurfaceSize(GFXFormat format,U32 width, U32 height, U32 mipLevel=0 )
{
if(!isCompressedFormat(format))
if(!ImageUtil::isCompressedFormat(format))
return 0;
// Bump by the mip level.
@ -87,7 +71,7 @@ inline U32 getCompressedSurfaceSize(GFXFormat format,U32 width, U32 height, U32
width = getMax(U32(1), width >> mipLevel);
U32 sizeMultiple = 0;
if(format == GFXFormatDXT1)
if(format == GFXFormatBC1 || format == GFXFormatBC1_SRGB)
sizeMultiple = 8;
else
sizeMultiple = 16;

View file

@ -36,8 +36,8 @@ GFX_ImplementTextureProfile( BackBufferDepthProfile,
GFXTextureProfile::NONE );
GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d)
: GFXWindowTarget(win), mDevice(d), mContext(NULL), mCopyFBO(0)
, mFullscreenContext(NULL), mBackBufferFBO(0), mSecondaryWindow(false)
: GFXWindowTarget(win), mDevice(d), mContext(NULL), mFullscreenContext(NULL)
, mCopyFBO(0), mBackBufferFBO(0)
{
win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal);
}
@ -52,14 +52,7 @@ GFXGLWindowTarget::~GFXGLWindowTarget()
void GFXGLWindowTarget::resetMode()
{
// Do some validation...
bool fullscreen = mWindow->getVideoMode().fullScreen;
if (fullscreen && mSecondaryWindow)
{
AssertFatal(false, "GFXGLWindowTarget::resetMode - Cannot go fullscreen with secondary window!");
}
if(fullscreen != mWindow->isFullscreen())
if(mWindow->getVideoMode().fullScreen != mWindow->isFullscreen())
{
_teardownCurrentMode();
_setupNewMode();
@ -118,9 +111,10 @@ void GFXGLWindowTarget::resolveTo(GFXTextureObject* obj)
inline void GFXGLWindowTarget::_setupAttachments()
{
glBindFramebuffer( GL_FRAMEBUFFER, mBackBufferFBO);
glEnable(GL_FRAMEBUFFER_SRGB);
GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mBackBufferFBO);
const Point2I dstSize = getSize();
mBackBufferColorTex.set(dstSize.x, dstSize.y, getFormat(), &PostFxTargetProfile, "backBuffer");
mBackBufferColorTex.set(dstSize.x, dstSize.y, getFormat(), &GFXRenderTargetSRGBProfile, "backBuffer");
GFXGLTextureObject *color = static_cast<GFXGLTextureObject*>(mBackBufferColorTex.getPointer());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->getHandle(), 0);
mBackBufferDepthTex.set(dstSize.x, dstSize.y, GFXFormatD24S8, &BackBufferDepthProfile, "backBuffer");

View file

@ -39,7 +39,7 @@ public:
virtual GFXFormat getFormat()
{
// TODO: Fix me!
return GFXFormatR8G8B8A8;
return GFXFormatR8G8B8A8_SRGB;
}
void makeActive();
virtual bool present();
@ -50,9 +50,6 @@ public:
virtual void resolveTo(GFXTextureObject* obj);
void _onAppSignal(WindowId wnd, S32 event);
// create pixel format for the window
void createPixelFormat();
private:
friend class GFXGLDevice;
@ -61,8 +58,6 @@ private:
GFXTexHandle mBackBufferColorTex, mBackBufferDepthTex;
Point2I size;
GFXDevice* mDevice;
/// Is this a secondary window
bool mSecondaryWindow;
void* mContext;
void* mFullscreenContext;
void _teardownCurrentMode();

View file

@ -86,6 +86,7 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
SDL_GLContext tempContext = SDL_GL_CreateContext( tempWindow );
if( !tempContext )
@ -191,21 +192,19 @@ U32 GFXGLDevice::getTotalVideoMemory()
GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
{
GFXGLWindowTarget* ggwt = new GFXGLWindowTarget(window, this);
AssertFatal(!mContext, "This GFXGLDevice is already assigned to a window");
GFXGLWindowTarget* ggwt = 0;
if( !mContext )
{
// no context, init the device now
init(window->getVideoMode(), window);
ggwt = new GFXGLWindowTarget(window, this);
ggwt->registerResourceWithDevice(this);
ggwt->mContext = mContext;
}
//first window
if (!mContext)
{
init(window->getVideoMode(), window);
ggwt->mSecondaryWindow = false;
}
else
ggwt->mSecondaryWindow = true;
ggwt->registerResourceWithDevice(this);
ggwt->mContext = mContext;
return ggwt;
return ggwt;
}
GFXFence* GFXGLDevice::_createPlatformSpecificFence()

View file

@ -41,12 +41,7 @@ namespace GL
void gglPerformExtensionBinds(void *context)
{
#ifdef TORQUE_OS_WIN
if (!gladLoadWGL(wglGetCurrentDC()))
{
AssertFatal(false, "Unable to load GLAD WGL extensions. Make sure your OpenGL drivers are up to date!");
}
#endif
}
}

View file

@ -255,6 +255,14 @@ void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
HDC hdcGL = GetDC( hwnd );
AssertFatal( hdcGL != NULL, "Failed to create device context" );
// Create pixel format descriptor...
PIXELFORMATDESCRIPTOR pfd;
CreatePixelFormat( &pfd, 32, 0, 0, false ); // 32 bit color... We do not need depth or stencil, OpenGL renders into a FBO and then copy the image to window
if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) )
{
AssertFatal( false, "GFXGLDevice::init - cannot get the one and only pixel format we check for." );
}
int OGL_MAJOR = 3;
int OGL_MINOR = 2;
@ -269,7 +277,7 @@ void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
if (!wglMakeCurrent(hdcGL, tempGLRC))
AssertFatal(false, "Couldn't make temp GL context.");
if( gglHasWExtension( ARB_create_context) )
if( gglHasWExtension(hdcGL, ARB_create_context) )
{
int const create_attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, OGL_MAJOR,
@ -322,21 +330,13 @@ U32 GFXGLDevice::getTotalVideoMemory()
//------------------------------------------------------------------------------
GFXWindowTarget *GFXGLDevice::allocWindowTarget(PlatformWindow *window)
GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
{
AssertFatal(!mContext, "");
init(window->getVideoMode(), window);
GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
ggwt->registerResourceWithDevice(this);
ggwt->createPixelFormat();
//first window
if (!mContext)
{
init(window->getVideoMode(), window);
ggwt->mSecondaryWindow = false;
}
else
ggwt->mSecondaryWindow = true;
ggwt->mContext = mContext;
AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!");
@ -364,22 +364,6 @@ void GFXGLWindowTarget::_setupNewMode()
{
}
void GFXGLWindowTarget::createPixelFormat()
{
HWND hwnd = GETHWND(mWindow);
// Create a device context
HDC hdcGL = GetDC(hwnd);
AssertFatal(hdcGL != NULL, "GFXGLWindowTarget::createPixelFormat() - Failed to create device context");
// Create pixel format descriptor...
PIXELFORMATDESCRIPTOR pfd;
CreatePixelFormat(&pfd, 32, 0, 0, false); // 32 bit color... We do not need depth or stencil, OpenGL renders into a FBO and then copy the image to window
if (!SetPixelFormat(hdcGL, ChoosePixelFormat(hdcGL, &pfd), &pfd))
{
AssertFatal(false, "GFXGLWindowTarget::createPixelFormat() - cannot get the one and only pixel format we check for.");
}
}
void GFXGLWindowTarget::_makeContextCurrent()
{
HWND hwnd = GETHWND(getWindow());