mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 07:04:36 +00:00
Update GFXTextureManager and GBitmap
GBitmap Changes: Added all other formats to gbitmap that we support gbitmap now supports cubemaps added converters for all these other formats added stb_image_resize for extrudemips so we can extrude mipmaps for all other formats GFXTextureManager Can now directly make cubemaps and texture arrays based on the GFXTextureProfile API implementations for all functions that cubemaps and arrays needed
This commit is contained in:
parent
975fc924cc
commit
3aef90a6bc
66 changed files with 4235 additions and 2590 deletions
|
|
@ -55,6 +55,7 @@ GFXTextureObject *GFXGLTextureManager::_createTextureObject( U32 height,
|
|||
U32 numMipLevels,
|
||||
bool forceMips,
|
||||
S32 antialiasLevel,
|
||||
U32 arraySize,
|
||||
GFXTextureObject *inTex )
|
||||
{
|
||||
AssertFatal(format >= 0 && format < GFXFormat_COUNT, "GFXGLTextureManager::_createTexture - invalid format!");
|
||||
|
|
@ -73,7 +74,7 @@ GFXTextureObject *GFXGLTextureManager::_createTextureObject( U32 height,
|
|||
retTex->registerResourceWithDevice( GFX );
|
||||
}
|
||||
|
||||
innerCreateTexture(retTex, height, width, depth, format, profile, numMipLevels, forceMips);
|
||||
innerCreateTexture(retTex, height, width, depth, format, profile, numMipLevels, forceMips, arraySize);
|
||||
|
||||
return retTex;
|
||||
}
|
||||
|
|
@ -89,19 +90,40 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
|
|||
GFXFormat format,
|
||||
GFXTextureProfile *profile,
|
||||
U32 numMipLevels,
|
||||
bool forceMips)
|
||||
bool forceMips,
|
||||
U32 arraySize)
|
||||
{
|
||||
// No 24 bit formats. They trigger various oddities because hardware (and Apple's drivers apparently...) don't natively support them.
|
||||
if (format == GFXFormatR8G8B8)
|
||||
format = GFXFormatR8G8B8A8;
|
||||
else if (format == GFXFormatR8G8B8_SRGB)
|
||||
format = GFXFormatR8G8B8A8_SRGB;
|
||||
|
||||
|
||||
retTex->mProfile = profile;
|
||||
retTex->mFormat = format;
|
||||
retTex->mIsZombie = false;
|
||||
retTex->mIsNPoT2 = false;
|
||||
|
||||
GLenum binding = ( (height == 1 || width == 1) && ( height != width ) ) ? GL_TEXTURE_1D : ( (depth == 0) ? GL_TEXTURE_2D : GL_TEXTURE_3D );
|
||||
const bool isCube = profile->isCubeMap();
|
||||
GLenum binding;
|
||||
|
||||
if (isCube)
|
||||
{
|
||||
binding = (arraySize > 1) ? GL_TEXTURE_CUBE_MAP_ARRAY : GL_TEXTURE_CUBE_MAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool is3D = (depth > 1);
|
||||
const bool is1D = (height == 1 && width > 1);
|
||||
|
||||
if (is3D)
|
||||
binding = GL_TEXTURE_3D;
|
||||
else if (is1D)
|
||||
binding = (arraySize > 1) ? GL_TEXTURE_1D_ARRAY : GL_TEXTURE_1D;
|
||||
else
|
||||
binding = (arraySize > 1) ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
|
||||
}
|
||||
|
||||
if((profile->testFlag(GFXTextureProfile::RenderTarget) || profile->testFlag(GFXTextureProfile::ZTarget)) && (!isPow2(width) || !isPow2(height)) && !depth)
|
||||
retTex->mIsNPoT2 = true;
|
||||
retTex->mBinding = binding;
|
||||
|
|
@ -155,55 +177,155 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
|
|||
retTex->mMipLevels = getMaxMipmaps(width, height, 1);
|
||||
|
||||
glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 );
|
||||
|
||||
if( GFXGL->mCapabilities.textureStorage )
|
||||
|
||||
bool hasTexStorage = false;
|
||||
// not supported when creating these.
|
||||
if (arraySize > 1 || isCube || profile->isDynamic())
|
||||
hasTexStorage = false;
|
||||
|
||||
const bool isCompressed = ImageUtil::isCompressedFormat(format);
|
||||
|
||||
// --- Allocation by binding ---
|
||||
if (binding == GL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
if(binding == GL_TEXTURE_2D)
|
||||
glTexStorage2D( retTex->getBinding(), retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height );
|
||||
else if(binding == GL_TEXTURE_1D)
|
||||
glTexStorage1D( retTex->getBinding(), retTex->mMipLevels, GFXGLTextureInternalFormat[format], getMax(width, height) );
|
||||
else
|
||||
glTexStorage3D( retTex->getBinding(), retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height, depth );
|
||||
// Single cubemap: prefer glTexStorage2D if available, else per-face texImage2D
|
||||
if (hasTexStorage)
|
||||
{
|
||||
// Some drivers accept texStorage2D with GL_TEXTURE_CUBE_MAP
|
||||
glTexStorage2D(GL_TEXTURE_CUBE_MAP, retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Explicitly allocate each face/level
|
||||
for (U32 face = 0; face < 6; ++face)
|
||||
{
|
||||
for (U32 mip = 0; mip < retTex->mMipLevels; ++mip)
|
||||
{
|
||||
U32 mipW = getMax(1u, width >> mip);
|
||||
U32 mipH = getMax(1u, height >> mip);
|
||||
|
||||
if (isCompressed)
|
||||
{
|
||||
U32 size = getCompressedSurfaceSize(format, width, height, mip);
|
||||
glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, GFXGLTextureInternalFormat[format], mipW, mipH, 0, size, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, GFXGLTextureInternalFormat[format], mipW, mipH, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (binding == GL_TEXTURE_CUBE_MAP_ARRAY)
|
||||
{
|
||||
//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(ImageUtil::isCompressedFormat(format))
|
||||
{
|
||||
AssertFatal(binding == GL_TEXTURE_2D,
|
||||
"GFXGLTextureManager::innerCreateTexture - Only compressed 2D textures are supported");
|
||||
|
||||
U32 tempWidth = width;
|
||||
U32 tempHeight = height;
|
||||
U32 size = getCompressedSurfaceSize(format,height,width);
|
||||
//Fill compressed images with 0's
|
||||
U8 *pTemp = (U8*)dMalloc(sizeof(U8)*size);
|
||||
dMemset(pTemp,0,size);
|
||||
|
||||
for(U32 i=0;i< retTex->mMipLevels;i++)
|
||||
{
|
||||
tempWidth = getMax( U32(1), width >> i );
|
||||
tempHeight = getMax( U32(1), height >> i );
|
||||
size = getCompressedSurfaceSize(format,width,height,i);
|
||||
glCompressedTexImage2D(binding,i,GFXGLTextureInternalFormat[format],tempWidth,tempHeight,0,size,pTemp);
|
||||
}
|
||||
|
||||
dFree(pTemp);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(binding == GL_TEXTURE_2D)
|
||||
glTexImage2D(binding, 0, GFXGLTextureInternalFormat[format], width, height, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
else if(binding == GL_TEXTURE_1D)
|
||||
glTexImage1D(binding, 0, GFXGLTextureInternalFormat[format], (width > 1 ? width : height), 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
else
|
||||
glTexImage3D(GL_TEXTURE_3D, 0, GFXGLTextureInternalFormat[format], width, height, depth, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
|
||||
if(retTex->mMipLevels > 1)
|
||||
glGenerateMipmap(binding);
|
||||
}
|
||||
// cube-map array: layers = arraySize * 6
|
||||
U32 layers = getMax(1u, arraySize) * 6u;
|
||||
if (hasTexStorage)
|
||||
{
|
||||
glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height, layers);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback to glTexImage3D with NULL data
|
||||
for (U32 mip = 0; mip < retTex->mMipLevels; ++mip)
|
||||
{
|
||||
U32 mipW = getMax(1u, width >> mip);
|
||||
U32 mipH = getMax(1u, height >> mip);
|
||||
glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, GFXGLTextureInternalFormat[format], mipW, mipH, layers, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (binding == GL_TEXTURE_2D_ARRAY)
|
||||
{
|
||||
// 2D texture array: depth = arraySize (layers)
|
||||
U32 layers = getMax(1u, arraySize);
|
||||
if (hasTexStorage)
|
||||
{
|
||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height, layers);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 mip = 0; mip < retTex->mMipLevels; ++mip)
|
||||
{
|
||||
U32 mipW = getMax(1u, width >> mip);
|
||||
U32 mipH = getMax(1u, height >> mip);
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, mip, GFXGLTextureInternalFormat[format], mipW, mipH, layers, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (binding == GL_TEXTURE_1D_ARRAY)
|
||||
{
|
||||
// 1D array stored as GL_TEXTURE_1D_ARRAY. glTexStorage2D can be used for 1D arrays with height=layers on many drivers.
|
||||
U32 layers = getMax(1u, arraySize);
|
||||
if (hasTexStorage)
|
||||
{
|
||||
// glTexStorage2D works for GL_TEXTURE_1D_ARRAY (width, layers)
|
||||
glTexStorage2D(GL_TEXTURE_1D_ARRAY, retTex->mMipLevels, GFXGLTextureInternalFormat[format], getMax(width, height), layers);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback: allocate as 2D where the "height" dimension is layers via glTexImage2D? Not ideal.
|
||||
// Safer: use glTexImage2D with target GL_TEXTURE_1D_ARRAY is invalid; instead use glTexImage3D with depth=layers
|
||||
for (U32 mip = 0; mip < retTex->mMipLevels; ++mip)
|
||||
{
|
||||
U32 mipW = getMax(1u, getMax(width, height) >> mip);
|
||||
glTexImage3D(GL_TEXTURE_1D_ARRAY, mip, GFXGLTextureInternalFormat[format], mipW, layers, 1, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (binding == GL_TEXTURE_1D)
|
||||
{
|
||||
if (hasTexStorage)
|
||||
glTexStorage1D(GL_TEXTURE_1D, retTex->mMipLevels, GFXGLTextureInternalFormat[format], getMax(width, height));
|
||||
else
|
||||
{
|
||||
for (U32 mip = 0; mip < retTex->mMipLevels; ++mip)
|
||||
{
|
||||
U32 mipW = getMax(1u, getMax(width, height) >> mip);
|
||||
glTexImage1D(GL_TEXTURE_1D, mip, GFXGLTextureInternalFormat[format], mipW, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (binding == GL_TEXTURE_3D)
|
||||
{
|
||||
if (hasTexStorage)
|
||||
glTexStorage3D(GL_TEXTURE_3D, retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height, depth);
|
||||
else
|
||||
{
|
||||
for (U32 mip = 0; mip < retTex->mMipLevels; ++mip)
|
||||
{
|
||||
U32 mipW = getMax(1u, width >> mip);
|
||||
U32 mipH = getMax(1u, height >> mip);
|
||||
U32 mipD = getMax(1u, depth >> mip);
|
||||
glTexImage3D(GL_TEXTURE_3D, mip, GFXGLTextureInternalFormat[format], mipW, mipH, mipD, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // GL_TEXTURE_2D (default)
|
||||
{
|
||||
if (hasTexStorage)
|
||||
glTexStorage2D(GL_TEXTURE_2D, retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height);
|
||||
else
|
||||
{
|
||||
for (U32 mip = 0; mip < retTex->mMipLevels; ++mip)
|
||||
{
|
||||
U32 mipW = getMax(1u, width >> mip);
|
||||
U32 mipH = getMax(1u, height >> mip);
|
||||
|
||||
if (isCompressed)
|
||||
{
|
||||
U32 size = getCompressedSurfaceSize(format, width, height, mip);
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, mip, GFXGLTextureInternalFormat[format], mipW, mipH, 0, size, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, mip, GFXGLTextureInternalFormat[format], mipW, mipH, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Complete the texture
|
||||
// Complete the texture - this does get changed later but we need to complete the texture anyway
|
||||
|
|
@ -221,14 +343,20 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
|
|||
if(GFXGLTextureSwizzle[format])
|
||||
glTexParameteriv(binding, GL_TEXTURE_SWIZZLE_RGBA, GFXGLTextureSwizzle[format]);
|
||||
|
||||
// Get the size from GL (you never know...)
|
||||
GLint texHeight, texWidth, texDepth = 0;
|
||||
|
||||
glGetTexLevelParameteriv(binding, 0, GL_TEXTURE_WIDTH, &texWidth);
|
||||
glGetTexLevelParameteriv(binding, 0, GL_TEXTURE_HEIGHT, &texHeight);
|
||||
if(binding == GL_TEXTURE_3D)
|
||||
glGetTexLevelParameteriv(binding, 0, GL_TEXTURE_DEPTH, &texDepth);
|
||||
|
||||
GLint texHeight = 0, texWidth = 0, texDepth = 0;
|
||||
|
||||
GLenum queryTarget = binding;
|
||||
if (binding == GL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
// Query a specific face, e.g. +X
|
||||
queryTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
}
|
||||
|
||||
glGetTexLevelParameteriv(queryTarget, 0, GL_TEXTURE_WIDTH, &texWidth);
|
||||
glGetTexLevelParameteriv(queryTarget, 0, GL_TEXTURE_HEIGHT, &texHeight);
|
||||
if (binding == GL_TEXTURE_3D)
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &texDepth);
|
||||
|
||||
retTex->mTextureSize.set(texWidth, texHeight, texDepth);
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +364,7 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
|
|||
// loadTexture - GBitmap
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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)
|
||||
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, const U32 face = 0, Swizzle<U8, 4> *pSwizzle = NULL)
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->getBuffer());
|
||||
U32 bufSize = width * height * bytesPerPixel;
|
||||
|
|
@ -256,7 +384,9 @@ static void _textureUpload(const S32 width, const S32 height,const S32 bytesPerP
|
|||
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, data);
|
||||
}
|
||||
|
||||
if (texture->getBinding() == GL_TEXTURE_2D)
|
||||
if(texture->getBinding() == GL_TEXTURE_CUBE_MAP)
|
||||
glTexSubImage2D(GFXGLFaceType[face], mip, 0, 0, width, height, GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL);
|
||||
else 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);
|
||||
|
|
@ -266,76 +396,125 @@ static void _textureUpload(const S32 width, const S32 height,const S32 bytesPerP
|
|||
|
||||
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)
|
||||
{
|
||||
PROFILE_SCOPE(GFXGLTextureManager_loadTexture);
|
||||
PROFILE_SCOPE(GFXGLTextureManager_loadTextureGBitmap);
|
||||
GFXGLTextureObject *texture = static_cast<GFXGLTextureObject*>(aTexture);
|
||||
|
||||
AssertFatal(texture->getBinding() == GL_TEXTURE_1D || texture->getBinding() == GL_TEXTURE_2D,
|
||||
"GFXGLTextureManager::_loadTexture(GBitmap) - This method can only be used with 1D/2D textures");
|
||||
|
||||
const GLenum target = texture->getBinding();
|
||||
|
||||
AssertFatal(target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP,
|
||||
"GFXGLTextureManager::_loadTexture(GBitmap) - This method can only be used with 1D/2D and CubeMap textures");
|
||||
|
||||
if(texture->getBinding() == GL_TEXTURE_3D)
|
||||
return false;
|
||||
|
||||
// No 24bit formats.
|
||||
if(pDL->getFormat() == GFXFormatR8G8B8)
|
||||
pDL->setFormat(GFXFormatR8G8B8A8);
|
||||
else if (pDL->getFormat() == GFXFormatR8G8B8_SRGB)
|
||||
pDL->setFormat(GFXFormatR8G8B8A8_SRGB);
|
||||
//
|
||||
//// 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());
|
||||
|
||||
_textureUpload(pDL->getWidth(),pDL->getHeight(),pDL->getBytesPerPixel(),texture,pDL->getFormat(), pDL->getBits(), 0);
|
||||
const U32 mipLevels = texture->getMipLevels();
|
||||
const bool isCubemap = (target == GL_TEXTURE_CUBE_MAP) && pDL->getNumFaces() > 1;
|
||||
U32 faceCount = isCubemap ? 6 : 1;
|
||||
|
||||
if(!ImageUtil::isCompressedFormat(pDL->getFormat()))
|
||||
glGenerateMipmap(texture->getBinding());
|
||||
|
||||
for (U32 mip = 0; mip < mipLevels; mip++)
|
||||
{
|
||||
const GLsizei width = getMax(1u, pDL->getWidth(mip));
|
||||
const GLsizei height = getMax(1u, pDL->getHeight(mip));
|
||||
for (U32 face = 0; face < faceCount; ++face)
|
||||
{
|
||||
_textureUpload(width, height, pDL->getBytesPerPixel(), texture, pDL->getFormat(), pDL->getBits(mip,face), mip, face);
|
||||
}
|
||||
}
|
||||
|
||||
if(!ImageUtil::isCompressedFormat(pDL->getFormat()))
|
||||
glGenerateMipmap(texture->getBinding());
|
||||
|
||||
glBindTexture(target, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
|
||||
{
|
||||
PROFILE_SCOPE(GFXGLTextureManager_loadTextureDDS);
|
||||
GFXGLTextureObject* texture = static_cast<GFXGLTextureObject*>(aTexture);
|
||||
|
||||
AssertFatal(texture->getBinding() == GL_TEXTURE_2D,
|
||||
"GFXGLTextureManager::_loadTexture(DDSFile) - This method can only be used with 2D textures");
|
||||
|
||||
if(texture->getBinding() != GL_TEXTURE_2D)
|
||||
return false;
|
||||
|
||||
PRESERVE_TEXTURE(texture->getBinding());
|
||||
glBindTexture(texture->getBinding(), texture->getHandle());
|
||||
U32 numMips = dds->mSurfaces[0]->mMips.size();
|
||||
|
||||
const GLenum target = texture->getBinding();
|
||||
|
||||
const bool isCube = texture->getBinding() == GL_TEXTURE_CUBE_MAP && dds->isCubemap();
|
||||
const bool isCompressed = ImageUtil::isCompressedFormat(texture->mFormat);
|
||||
|
||||
AssertFatal(target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP,
|
||||
"GFXGLTextureManager::_loadTexture(DDS) - This method can only be used with 1D/2D and CubeMap textures");
|
||||
|
||||
if (texture->getBinding() == GL_TEXTURE_3D)
|
||||
return false;
|
||||
|
||||
PRESERVE_TEXTURE(target);
|
||||
glBindTexture(target, texture->getHandle());
|
||||
|
||||
const U32 numFaces = isCube ? 6 : 1;
|
||||
const U32 numMips = dds->mSurfaces[0]->mMips.size();
|
||||
const GFXFormat fmt = texture->mFormat;
|
||||
|
||||
for(U32 i = 0; i < numMips; i++)
|
||||
for (U32 face = 0; face < numFaces; ++face)
|
||||
{
|
||||
PROFILE_SCOPE(GFXGLTexMan_loadSurface);
|
||||
// Skip empty surfaces
|
||||
if (!dds->mSurfaces[face])
|
||||
continue;
|
||||
|
||||
if(ImageUtil::isCompressedFormat(texture->mFormat))
|
||||
for (U32 mip = 0; mip < numMips; ++mip)
|
||||
{
|
||||
if((!isPow2(dds->getWidth()) || !isPow2(dds->getHeight())) && GFX->getCardProfiler()->queryProfile("GL::Workaround::noCompressedNPoTTextures"))
|
||||
const U32 mipWidth = getMax(1u, dds->getWidth(mip));
|
||||
const U32 mipHeight = getMax(1u, dds->getHeight(mip));
|
||||
|
||||
GLenum uploadTarget = target;
|
||||
if (isCube)
|
||||
uploadTarget = GFXGLFaceType[face];
|
||||
|
||||
if (isCompressed)
|
||||
{
|
||||
U8* uncompressedTex = new U8[dds->getWidth(i) * dds->getHeight(i) * 4];
|
||||
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;
|
||||
// Handle NPOT workaround
|
||||
if ((!isPow2(mipWidth) || !isPow2(mipHeight)) && GFX->getCardProfiler()->queryProfile("GL::Workaround::noCompressedNPoTTextures"))
|
||||
{
|
||||
U8* uncompressedTex = new U8[mipWidth * mipHeight * 4];
|
||||
ImageUtil::decompress(dds->mSurfaces[face]->mMips[mip], uncompressedTex, mipWidth, mipHeight, fmt);
|
||||
glTexSubImage2D(uploadTarget,
|
||||
mip, 0, 0, mipWidth, mipHeight, GL_RGBA, GL_UNSIGNED_BYTE, uncompressedTex
|
||||
);
|
||||
delete[] uncompressedTex;
|
||||
}
|
||||
else
|
||||
{
|
||||
glCompressedTexImage2D(uploadTarget,
|
||||
mip, GFXGLTextureInternalFormat[fmt], mipWidth, mipHeight, 0,
|
||||
dds->getSurfaceSize(mip), dds->mSurfaces[face]->mMips[mip]
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
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
|
||||
{
|
||||
Swizzle<U8, 4> *pSwizzle = NULL;
|
||||
if (fmt == GFXFormatR8G8B8A8 || fmt == GFXFormatR8G8B8X8 || fmt == GFXFormatR8G8B8A8_SRGB || fmt == GFXFormatR8G8B8A8_LINEAR_FORCE || fmt == GFXFormatB8G8R8A8)
|
||||
pSwizzle = &Swizzles::bgra;
|
||||
{
|
||||
Swizzle<U8, 4>* pSwizzle = nullptr;
|
||||
if (fmt == GFXFormatR8G8B8A8 || fmt == GFXFormatR8G8B8X8 || fmt == GFXFormatR8G8B8A8_SRGB ||
|
||||
fmt == GFXFormatR8G8B8A8_LINEAR_FORCE || fmt == GFXFormatB8G8R8A8)
|
||||
pSwizzle = &Swizzles::bgra;
|
||||
|
||||
_textureUpload(
|
||||
mipWidth, mipHeight, dds->mBytesPerPixel, texture, fmt,
|
||||
dds->mSurfaces[face]->mMips[mip], mip, face, pSwizzle);
|
||||
}
|
||||
|
||||
_textureUpload(dds->getWidth(i), dds->getHeight(i),dds->mBytesPerPixel, texture, fmt, dds->mSurfaces[0]->mMips[i],i, pSwizzle);
|
||||
}
|
||||
}
|
||||
|
||||
if(numMips !=1 && !ImageUtil::isCompressedFormat(texture->mFormat))
|
||||
if (numMips != 1 && !isCompressed)
|
||||
glGenerateMipmap(texture->getBinding());
|
||||
|
||||
|
||||
glBindTexture(target, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ protected:
|
|||
U32 numMipLevels,
|
||||
bool forceMips = false,
|
||||
S32 antialiasLevel = 0,
|
||||
U32 arraySize = 1,
|
||||
GFXTextureObject *inTex = NULL ) override;
|
||||
bool _loadTexture(GFXTextureObject *texture, DDSFile *dds) override;
|
||||
bool _loadTexture(GFXTextureObject *texture, GBitmap *bmp) override;
|
||||
|
|
@ -56,7 +57,7 @@ private:
|
|||
friend class GFXGLTextureObject;
|
||||
|
||||
/// Creates internal GL texture
|
||||
void innerCreateTexture(GFXGLTextureObject *obj, U32 height, U32 width, U32 depth, GFXFormat format, GFXTextureProfile *profile, U32 numMipLevels, bool forceMips = false);
|
||||
void innerCreateTexture(GFXGLTextureObject *obj, U32 height, U32 width, U32 depth, GFXFormat format, GFXTextureProfile *profile, U32 numMipLevels, bool forceMips = false, U32 arraySize = 1);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ GFXGLTextureObject::~GFXGLTextureObject()
|
|||
kill();
|
||||
}
|
||||
|
||||
GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel, RectI *inRect)
|
||||
GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel /*= 0*/, RectI* inRect /*= NULL*/, U32 faceIndex /*= 0*/)
|
||||
{
|
||||
//AssertFatal(mBinding != GL_TEXTURE_3D, "GFXGLTextureObject::lock - We don't support locking 3D textures yet");
|
||||
U32 width = mTextureSize.x >> mipLevel;
|
||||
|
|
@ -100,7 +100,7 @@ GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel, RectI *inRect)
|
|||
return &mLockedRect;
|
||||
}
|
||||
|
||||
void GFXGLTextureObject::unlock(U32 mipLevel)
|
||||
void GFXGLTextureObject::unlock(U32 mipLevel /*= 0*/, U32 faceIndex /*= 0*/)
|
||||
{
|
||||
if(!mLockedRect.bits)
|
||||
return;
|
||||
|
|
@ -175,38 +175,231 @@ bool GFXGLTextureObject::copyToBmp(GBitmap * bmp)
|
|||
|
||||
FrameAllocatorMarker mem;
|
||||
|
||||
const bool isCubemap = (mBinding == GL_TEXTURE_CUBE_MAP);
|
||||
const U32 numFaces = isCubemap ? 6 : 1;
|
||||
|
||||
U32 mipLevels = getMipLevels();
|
||||
for (U32 mip = 0; mip < mipLevels; mip++)
|
||||
for (U32 mip = 0; mip < getMipLevels(); mip++)
|
||||
{
|
||||
U32 srcPixelCount = bmp->getSurfaceSize(mip)/ srcBytesPerPixel;
|
||||
U32 width = getWidth() >> mip;
|
||||
U32 height = getHeight() >> mip;
|
||||
if (width == 0) width = 1;
|
||||
if (height == 0) height = 1;
|
||||
|
||||
U8* dest = bmp->getWritableBits(mip);
|
||||
U8* orig = (U8*)mem.alloc(srcPixelCount * srcBytesPerPixel);
|
||||
// Check if multisampled
|
||||
GLint samples = 0;
|
||||
GLenum target = mBinding;
|
||||
if (mBinding == GL_TEXTURE_CUBE_MAP)
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
|
||||
glGetTexImage(mBinding, mip, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], orig);
|
||||
if (mFormat == GFXFormatR16G16B16A16F)
|
||||
glGetTexLevelParameteriv(target, mip, GL_TEXTURE_SAMPLES, &samples);
|
||||
if (samples > 0)
|
||||
{
|
||||
dMemcpy(dest, orig, srcPixelCount * srcBytesPerPixel);
|
||||
Con::warnf("GFXGLTextureObject::copyToBmp - Texture is multisampled (%d samples) at mip %d; resolve first.", samples, mip);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < srcPixelCount; ++i)
|
||||
{
|
||||
dest[0] = orig[0];
|
||||
dest[1] = orig[1];
|
||||
dest[2] = orig[2];
|
||||
if (dstBytesPerPixel == 4)
|
||||
dest[3] = orig[3];
|
||||
|
||||
orig += srcBytesPerPixel;
|
||||
dest += dstBytesPerPixel;
|
||||
for (U32 face = 0; face < numFaces; face++)
|
||||
{
|
||||
GLenum faceTarget = isCubemap ? GFXGLFaceType[face] : mBinding;
|
||||
|
||||
U32 pixelCount = width * height;
|
||||
U8* srcPixels = (U8*)mem.alloc(pixelCount * srcBytesPerPixel);
|
||||
U8* dest = bmp->getWritableBits(mip, face);
|
||||
|
||||
if (!dest)
|
||||
{
|
||||
Con::errorf("GFXGLTextureObject::copyToBmp - No destination bits for mip=%u face=%u", mip, face);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read texture data
|
||||
glGetTexImage(faceTarget, mip, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], srcPixels);
|
||||
|
||||
if (mFormat == GFXFormatR16G16B16A16F)
|
||||
{
|
||||
dMemcpy(dest, srcPixels, pixelCount * srcBytesPerPixel);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple 8-bit per channel copy (RGBA)
|
||||
U8* src = srcPixels;
|
||||
for (U32 i = 0; i < pixelCount; ++i)
|
||||
{
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
if (dstBytesPerPixel == 4)
|
||||
dest[3] = src[3];
|
||||
|
||||
src += srcBytesPerPixel;
|
||||
dest += dstBytesPerPixel;
|
||||
}
|
||||
}
|
||||
} // face
|
||||
} // mip
|
||||
|
||||
glBindTexture(mBinding, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GFXGLTextureObject::updateTextureSlot(const GFXTexHandle& texHandle, const U32 slot, const S32 face)
|
||||
{
|
||||
if (!texHandle.isValid())
|
||||
return;
|
||||
|
||||
GFXGLTextureObject* srcTex = static_cast<GFXGLTextureObject*>(texHandle.getPointer());
|
||||
if (!srcTex || srcTex->getHandle() == 0)
|
||||
return;
|
||||
|
||||
const GLenum dstTarget = mBinding; // destination binding (this)
|
||||
const GLenum srcTarget = srcTex->getBinding(); // source binding
|
||||
const bool srcIsCube = (srcTarget == GL_TEXTURE_CUBE_MAP || srcTarget == GL_TEXTURE_CUBE_MAP_ARRAY);
|
||||
|
||||
// Determine list of faces to copy from source
|
||||
U32 firstFace = 0;
|
||||
U32 faceCount = 1;
|
||||
if (face >= 0)
|
||||
{
|
||||
firstFace = (U32)face;
|
||||
faceCount = 1;
|
||||
}
|
||||
else if (srcIsCube)
|
||||
{
|
||||
firstFace = 0;
|
||||
faceCount = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
firstFace = 0;
|
||||
faceCount = 1;
|
||||
}
|
||||
|
||||
// Ensure textures are valid
|
||||
if (!glIsTexture(mHandle) || !glIsTexture(srcTex->getHandle()))
|
||||
{
|
||||
Con::errorf("updateTextureSlot: invalid GL texture handle src=%u dst=%u", srcTex->getHandle(), mHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
// If copyImage supported, prefer that. We'll copy face-by-face (one-layer depth = 1)
|
||||
if (GFXGL->mCapabilities.copyImage)
|
||||
{
|
||||
for (U32 mip = 0; mip < getMipLevels(); ++mip)
|
||||
{
|
||||
const GLsizei mipW = getMax(1u, srcTex->getWidth() >> mip);
|
||||
const GLsizei mipH = getMax(1u, srcTex->getHeight() >> mip);
|
||||
|
||||
for (U32 f = firstFace; f < firstFace + faceCount; ++f)
|
||||
{
|
||||
// Compute source z offset (for cube arrays it's layer index; for cubemap it's face index)
|
||||
GLint srcZ = 0;
|
||||
if (srcTarget == GL_TEXTURE_CUBE_MAP_ARRAY)
|
||||
{
|
||||
srcZ = f;
|
||||
}
|
||||
else if (srcTarget == GL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
srcZ = f;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcZ = 0; // 2D source
|
||||
}
|
||||
|
||||
// Compute destination layer (z offset) depending on destination type
|
||||
GLint dstZ = 0;
|
||||
if (dstTarget == GL_TEXTURE_CUBE_MAP_ARRAY)
|
||||
{
|
||||
// each slot is a whole cubemap => slot * 6 + faceIndex
|
||||
dstZ = (GLint)(slot * 6 + f);
|
||||
}
|
||||
else if (dstTarget == GL_TEXTURE_2D_ARRAY)
|
||||
{
|
||||
dstZ = (GLint)slot; // each slot is a single layer
|
||||
}
|
||||
else if (dstTarget == GL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
dstZ = (GLint)f;
|
||||
}
|
||||
else
|
||||
{
|
||||
dstZ = 0; // 2D texture target
|
||||
}
|
||||
|
||||
// Copy single layer/face at this mip
|
||||
glCopyImageSubData(
|
||||
srcTex->getHandle(), srcTarget, mip, 0, 0, srcZ,
|
||||
mHandle, dstTarget, mip, 0, 0, dstZ,
|
||||
mipW, mipH, 1
|
||||
);
|
||||
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR)
|
||||
Con::errorf("glCopyImageSubData failed with 0x%X (mip=%u face=%u)", err, mip, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
glBindTexture(mBinding, 0);
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: CPU-side copy using glGetTexImage + glTexSubImage
|
||||
for (U32 mip = 0; mip < getMipLevels() && mip < srcTex->getMipLevels(); ++mip)
|
||||
{
|
||||
const GLsizei mipW = getMax(1u, srcTex->getWidth() >> mip);
|
||||
const GLsizei mipH = getMax(1u, srcTex->getHeight() >> mip);
|
||||
const U32 pixelSize = GFXFormat_getByteSize(mFormat); // assuming same fmt for src/dst
|
||||
const U32 dataSize = mipW * mipH * pixelSize;
|
||||
|
||||
FrameAllocatorMarker mem;
|
||||
U8* buffer = (U8*)mem.alloc(dataSize);
|
||||
|
||||
glBindTexture(srcTarget, srcTex->getHandle());
|
||||
glBindTexture(dstTarget, mHandle);
|
||||
|
||||
for (U32 f = firstFace; f < firstFace + faceCount; ++f)
|
||||
{
|
||||
GLenum srcFaceTarget = srcTarget;
|
||||
if (srcTarget == GL_TEXTURE_CUBE_MAP)
|
||||
srcFaceTarget = GFXGLFaceType[f];
|
||||
|
||||
// read pixels from source
|
||||
glGetTexImage(srcFaceTarget, mip, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], buffer);
|
||||
|
||||
GLint dstLayer = 0;
|
||||
if (dstTarget == GL_TEXTURE_CUBE_MAP_ARRAY)
|
||||
dstLayer = (GLint)(slot * 6 + f);
|
||||
else if (dstTarget == GL_TEXTURE_2D_ARRAY)
|
||||
dstLayer = (GLint)slot;
|
||||
else if (dstTarget == GL_TEXTURE_CUBE_MAP)
|
||||
dstLayer = (GLint)f;
|
||||
else
|
||||
dstLayer = 0;
|
||||
|
||||
if (dstTarget == GL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
GLenum dstFaceTarget = GFXGLFaceType[f];
|
||||
glTexSubImage2D(dstFaceTarget, mip, 0, 0, mipW, mipH,
|
||||
GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], buffer);
|
||||
}
|
||||
else if (dstTarget == GL_TEXTURE_2D)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, mipW, mipH,
|
||||
GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], buffer);
|
||||
}
|
||||
else if (dstTarget == GL_TEXTURE_2D_ARRAY || dstTarget == GL_TEXTURE_CUBE_MAP_ARRAY)
|
||||
{
|
||||
glTexSubImage3D(dstTarget, mip, 0, 0, dstLayer, mipW, mipH, 1,
|
||||
GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], buffer);
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture(dstTarget, 0);
|
||||
glBindTexture(srcTarget, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GFXGLTextureObject::copyTo(GFXTextureObject* dstTex)
|
||||
{
|
||||
}
|
||||
|
||||
void GFXGLTextureObject::initSamplerState(const GFXSamplerStateDesc &ssd)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@
|
|||
#include "gfx/gfxTextureObject.h"
|
||||
#include "gfx/gl/tGL/tGL.h"
|
||||
#include "gfx/gfxStateBlock.h"
|
||||
|
||||
#ifndef _MRECT_H_
|
||||
#include "math/mRect.h"
|
||||
#endif
|
||||
class GFXGLDevice;
|
||||
|
||||
class GFXGLTextureObject : public GFXTextureObject
|
||||
|
|
@ -64,11 +66,13 @@ public:
|
|||
|
||||
/// Get/set data from texture (for dynamic textures and render targets)
|
||||
/// @attention DO NOT READ FROM THE RETURNED RECT! It is not guaranteed to work and may incur significant performance penalties.
|
||||
GFXLockedRect* lock(U32 mipLevel = 0, RectI *inRect = NULL) override;
|
||||
void unlock(U32 mipLevel = 0 ) override;
|
||||
GFXLockedRect* lock(U32 mipLevel = 0, RectI *inRect = NULL, U32 faceIndex = 0) override;
|
||||
void unlock(U32 mipLevel = 0, U32 faceIndex = 0) override;
|
||||
|
||||
bool copyToBmp(GBitmap *) override; ///< Not implemented
|
||||
|
||||
void updateTextureSlot(const GFXTexHandle& texHandle, const U32 slot, const S32 face = -1) override;
|
||||
void copyTo(GFXTextureObject* dstTex) override;
|
||||
void generateMipMaps() override {};
|
||||
bool mIsNPoT2;
|
||||
|
||||
// GFXResource interface
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ public:
|
|||
mipLevel(_mipLevel), zOffset(_zOffset)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~_GFXGLTargetDesc() {}
|
||||
|
||||
|
||||
virtual U32 getHandle() = 0;
|
||||
virtual U32 getWidth() = 0;
|
||||
virtual U32 getHeight() = 0;
|
||||
|
|
@ -49,10 +49,10 @@ public:
|
|||
virtual GLenum getBinding() = 0;
|
||||
virtual GFXFormat getFormat() = 0;
|
||||
virtual bool isCompatible(const GFXGLTextureObject* tex) = 0;
|
||||
|
||||
|
||||
U32 getMipLevel() { return mipLevel; }
|
||||
U32 getZOffset() { return zOffset; }
|
||||
|
||||
|
||||
private:
|
||||
U32 mipLevel;
|
||||
U32 zOffset;
|
||||
|
|
@ -62,19 +62,21 @@ private:
|
|||
class _GFXGLTextureTargetDesc : public _GFXGLTargetDesc
|
||||
{
|
||||
public:
|
||||
_GFXGLTextureTargetDesc(GFXGLTextureObject* tex, U32 _mipLevel, U32 _zOffset)
|
||||
: _GFXGLTargetDesc(_mipLevel, _zOffset), mTex(tex)
|
||||
|
||||
_GFXGLTextureTargetDesc(GFXGLTextureObject* tex, U32 _mipLevel, U32 _zOffset, U32 _face = 0, bool isCube = false)
|
||||
: _GFXGLTargetDesc(_mipLevel, _zOffset), mTex(tex), mFace(_face), mIsCube(isCube)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~_GFXGLTextureTargetDesc() {}
|
||||
|
||||
|
||||
U32 getHandle() override { return mTex->getHandle(); }
|
||||
U32 getWidth() override { return mTex->getWidth(); }
|
||||
U32 getHeight() override { return mTex->getHeight(); }
|
||||
U32 getDepth() override { return mTex->getDepth(); }
|
||||
U32 getFace() { return mFace; }
|
||||
bool hasMips() override { return mTex->mMipLevels != 1; }
|
||||
GLenum getBinding() override { return mTex->getBinding(); }
|
||||
GLenum getBinding() override { return mIsCube ? GFXGLFaceType[mFace] : mTex->getBinding(); }
|
||||
GFXFormat getFormat() override { return mTex->getFormat(); }
|
||||
bool isCompatible(const GFXGLTextureObject* tex) override
|
||||
{
|
||||
|
|
@ -82,40 +84,12 @@ public:
|
|||
&& mTex->getWidth() == tex->getWidth()
|
||||
&& mTex->getHeight() == tex->getHeight();
|
||||
}
|
||||
GFXGLTextureObject* getTextureObject() const {return mTex; }
|
||||
|
||||
GFXGLTextureObject* getTextureObject() const { return mTex; }
|
||||
|
||||
private:
|
||||
StrongRefPtr<GFXGLTextureObject> mTex;
|
||||
};
|
||||
|
||||
/// Internal struct used to track Cubemap texture information for FBO attachment
|
||||
class _GFXGLCubemapTargetDesc : public _GFXGLTargetDesc
|
||||
{
|
||||
public:
|
||||
_GFXGLCubemapTargetDesc(GFXGLCubemap* tex, U32 _face, U32 _mipLevel, U32 _zOffset)
|
||||
: _GFXGLTargetDesc(_mipLevel, _zOffset), mTex(tex), mFace(_face)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~_GFXGLCubemapTargetDesc() {}
|
||||
|
||||
U32 getHandle() override { return mTex->getHandle(); }
|
||||
U32 getWidth() override { return mTex->getWidth(); }
|
||||
U32 getHeight() override { return mTex->getHeight(); }
|
||||
U32 getDepth() override { return 0; }
|
||||
bool hasMips() override { return mTex->getMipMapLevels() != 1; }
|
||||
GLenum getBinding() override { return GFXGLCubemap::getEnumForFaceNumber(mFace); }
|
||||
GFXFormat getFormat() override { return mTex->getFormat(); }
|
||||
bool isCompatible(const GFXGLTextureObject* tex) override
|
||||
{
|
||||
return mTex->getFormat() == tex->getFormat()
|
||||
&& mTex->getWidth() == tex->getWidth()
|
||||
&& mTex->getHeight() == tex->getHeight();
|
||||
}
|
||||
|
||||
private:
|
||||
StrongRefPtr<GFXGLCubemap> mTex;
|
||||
U32 mFace;
|
||||
bool mIsCube;
|
||||
};
|
||||
|
||||
// Internal implementations
|
||||
|
|
@ -123,9 +97,9 @@ class _GFXGLTextureTargetImpl // TODO OPENGL remove and implement on GFXGLTextur
|
|||
{
|
||||
public:
|
||||
GFXGLTextureTarget* mTarget;
|
||||
|
||||
|
||||
virtual ~_GFXGLTextureTargetImpl() {}
|
||||
|
||||
|
||||
virtual void applyState() = 0;
|
||||
virtual void makeActive() = 0;
|
||||
virtual void finish() = 0;
|
||||
|
|
@ -137,10 +111,10 @@ class _GFXGLTextureTargetFBOImpl : public _GFXGLTextureTargetImpl
|
|||
public:
|
||||
GLuint mFramebuffer;
|
||||
bool mGenMips;
|
||||
|
||||
|
||||
_GFXGLTextureTargetFBOImpl(GFXGLTextureTarget* target);
|
||||
virtual ~_GFXGLTextureTargetFBOImpl();
|
||||
|
||||
|
||||
void applyState() override;
|
||||
void makeActive() override;
|
||||
void finish() override;
|
||||
|
|
@ -159,42 +133,42 @@ _GFXGLTextureTargetFBOImpl::~_GFXGLTextureTargetFBOImpl()
|
|||
}
|
||||
|
||||
void _GFXGLTextureTargetFBOImpl::applyState()
|
||||
{
|
||||
{
|
||||
// REMINDER: When we implement MRT support, check against GFXGLDevice::getNumRenderTargets()
|
||||
|
||||
|
||||
PRESERVE_FRAMEBUFFER();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
bool drawbufs[16];
|
||||
int bufsize = 0;
|
||||
for (int i = 0; i < 16; i++)
|
||||
drawbufs[i] = false;
|
||||
drawbufs[i] = false;
|
||||
bool hasColor = false;
|
||||
for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ));
|
||||
if(color)
|
||||
for (int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc(static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0 + i));
|
||||
if (color)
|
||||
{
|
||||
hasColor = true;
|
||||
const GLenum binding = color->getBinding();
|
||||
if( binding == GL_TEXTURE_2D || (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) )
|
||||
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ) );
|
||||
else if( binding == GL_TEXTURE_1D )
|
||||
glFramebufferTexture1D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ) );
|
||||
else if( binding == GL_TEXTURE_3D )
|
||||
glFramebufferTexture3D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ), color->getZOffset( ) );
|
||||
if (binding == GL_TEXTURE_2D || (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding(), color->getHandle(), color->getMipLevel());
|
||||
else if (binding == GL_TEXTURE_1D)
|
||||
glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding(), color->getHandle(), color->getMipLevel());
|
||||
else if (binding == GL_TEXTURE_3D)
|
||||
glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding(), color->getHandle(), color->getMipLevel(), color->getZOffset());
|
||||
else
|
||||
Con::errorf("_GFXGLTextureTargetFBOImpl::applyState - Bad binding");
|
||||
Con::errorf("_GFXGLTextureTargetFBOImpl::applyState - Bad binding");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clears the texture (note that the binding is irrelevent)
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, 0, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_GFXGLTargetDesc* depthStecil = mTarget->getTargetDesc(GFXTextureTarget::DepthStencil);
|
||||
if(depthStecil)
|
||||
if (depthStecil)
|
||||
{
|
||||
// Certain drivers have issues with depth only FBOs. That and the next two asserts assume we have a color target.
|
||||
AssertFatal(hasColor, "GFXGLTextureTarget::applyState() - Cannot set DepthStencil target without Color0 target!");
|
||||
|
|
@ -206,40 +180,40 @@ void _GFXGLTextureTargetFBOImpl::applyState()
|
|||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
|
||||
GLenum *buf = new GLenum[bufsize];
|
||||
GLenum* buf = new GLenum[bufsize];
|
||||
int count = 0;
|
||||
for (int i = 0; i < bufsize; i++)
|
||||
{
|
||||
if (drawbufs[i])
|
||||
{
|
||||
buf[count] = GL_COLOR_ATTACHMENT0 + i;
|
||||
count++;
|
||||
}
|
||||
if (drawbufs[i])
|
||||
{
|
||||
buf[count] = GL_COLOR_ATTACHMENT0 + i;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
glDrawBuffers(bufsize, buf);
|
||||
|
||||
|
||||
delete[] buf;
|
||||
CHECK_FRAMEBUFFER_STATUS();
|
||||
}
|
||||
|
||||
void _GFXGLTextureTargetFBOImpl::makeActive()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mFramebuffer);
|
||||
|
||||
int i = 0;
|
||||
GLenum draws[16];
|
||||
for( i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ));
|
||||
if(color)
|
||||
draws[i] = GL_COLOR_ATTACHMENT0 + i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
int i = 0;
|
||||
GLenum draws[16];
|
||||
for (i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc(static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0 + i));
|
||||
if (color)
|
||||
draws[i] = GL_COLOR_ATTACHMENT0 + i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
glDrawBuffers( i, draws );
|
||||
glDrawBuffers(i, draws);
|
||||
}
|
||||
|
||||
void _GFXGLTextureTargetFBOImpl::finish()
|
||||
|
|
@ -250,20 +224,20 @@ void _GFXGLTextureTargetFBOImpl::finish()
|
|||
if (!mGenMips)
|
||||
return;
|
||||
|
||||
for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ) );
|
||||
if(!color || !(color->hasMips()))
|
||||
for (int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc(static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0 + i));
|
||||
if (!color || !(color->hasMips()))
|
||||
continue;
|
||||
|
||||
|
||||
// Generate mips if necessary
|
||||
// Assumes a 2D texture.
|
||||
GLenum binding = color->getBinding();
|
||||
binding = (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ? GL_TEXTURE_CUBE_MAP : binding;
|
||||
|
||||
PRESERVE_TEXTURE( binding );
|
||||
glBindTexture( binding, color->getHandle() );
|
||||
glGenerateMipmap( binding );
|
||||
PRESERVE_TEXTURE(binding);
|
||||
glBindTexture(binding, color->getHandle());
|
||||
glGenerateMipmap(binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,13 +245,13 @@ void _GFXGLTextureTargetFBOImpl::finish()
|
|||
GFXGLTextureTarget::GFXGLTextureTarget(bool genMips) : mCopyFboSrc(0), mCopyFboDst(0)
|
||||
{
|
||||
mGenMips = genMips;
|
||||
for(U32 i=0; i<MaxRenderSlotId; i++)
|
||||
for (U32 i = 0; i < MaxRenderSlotId; i++)
|
||||
mTargets[i] = NULL;
|
||||
|
||||
GFXTextureManager::addEventDelegate( this, &GFXGLTextureTarget::_onTextureEvent );
|
||||
|
||||
GFXTextureManager::addEventDelegate(this, &GFXGLTextureTarget::_onTextureEvent);
|
||||
|
||||
_impl = new _GFXGLTextureTargetFBOImpl(this);
|
||||
|
||||
|
||||
glGenFramebuffers(1, &mCopyFboSrc);
|
||||
glGenFramebuffers(1, &mCopyFboDst);
|
||||
}
|
||||
|
|
@ -292,7 +266,7 @@ GFXGLTextureTarget::~GFXGLTextureTarget()
|
|||
|
||||
const Point2I GFXGLTextureTarget::getSize()
|
||||
{
|
||||
if(mTargets[Color0].isValid())
|
||||
if (mTargets[Color0].isValid())
|
||||
return Point2I(mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight());
|
||||
|
||||
return Point2I(0, 0);
|
||||
|
|
@ -300,61 +274,50 @@ const Point2I GFXGLTextureTarget::getSize()
|
|||
|
||||
GFXFormat GFXGLTextureTarget::getFormat()
|
||||
{
|
||||
if(mTargets[Color0].isValid())
|
||||
if (mTargets[Color0].isValid())
|
||||
return mTargets[Color0]->getFormat();
|
||||
|
||||
return GFXFormatR8G8B8A8;
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/ )
|
||||
void GFXGLTextureTarget::attachTexture(RenderSlot slot, GFXTextureObject* tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/, U32 face /*= 0*/)
|
||||
{
|
||||
if( tex == GFXTextureTarget::sDefaultDepthStencil )
|
||||
if (tex == GFXTextureTarget::sDefaultDepthStencil)
|
||||
tex = GFXGL->getDefaultDepthTex();
|
||||
|
||||
// are we readding the same thing, face and all?
|
||||
_GFXGLTextureTargetDesc* mTex = static_cast<_GFXGLTextureTargetDesc*>(mTargets[slot].ptr());
|
||||
if( (!tex && !mTex) || (mTex && mTex->getTextureObject() == tex) )
|
||||
if ((!tex && !mTex) || (mTex && mTex->getTextureObject() == tex && mTex->getFace() == face))
|
||||
return;
|
||||
|
||||
|
||||
// Triggers an update when we next render
|
||||
invalidateState();
|
||||
|
||||
// We stash the texture and info into an internal struct.
|
||||
GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(tex);
|
||||
if(tex && tex != GFXTextureTarget::sDefaultDepthStencil)
|
||||
mTargets[slot] = new _GFXGLTextureTargetDesc(glTexture, mipLevel, zOffset);
|
||||
if (tex && tex != GFXTextureTarget::sDefaultDepthStencil)
|
||||
{
|
||||
mTargets[slot] = new _GFXGLTextureTargetDesc(glTexture, mipLevel, zOffset, face, glTexture->isCubeMap());
|
||||
}
|
||||
else
|
||||
mTargets[slot] = NULL;
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel/*=0*/ )
|
||||
void GFXGLTextureTarget::attachTexture(RenderSlot slot, GFXCubemap* tex, U32 face, U32 mipLevel/*=0*/)
|
||||
{
|
||||
// No depth cubemaps, sorry
|
||||
AssertFatal(slot != DepthStencil, "GFXGLTextureTarget::attachTexture (cube) - Cube depth textures not supported!");
|
||||
if(slot == DepthStencil)
|
||||
return;
|
||||
|
||||
// Triggers an update when we next render
|
||||
invalidateState();
|
||||
|
||||
// We stash the texture and info into an internal struct.
|
||||
GFXGLCubemap* glTexture = static_cast<GFXGLCubemap*>(tex);
|
||||
if(tex)
|
||||
mTargets[slot] = new _GFXGLCubemapTargetDesc(glTexture, face, mipLevel, 0);
|
||||
else
|
||||
mTargets[slot] = NULL;
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::clearAttachments()
|
||||
{
|
||||
deactivate();
|
||||
for(S32 i=1; i<MaxRenderSlotId; i++)
|
||||
for (S32 i = 1; i < MaxRenderSlotId; i++)
|
||||
attachTexture((RenderSlot)i, NULL);
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::zombify()
|
||||
{
|
||||
invalidateState();
|
||||
|
||||
|
||||
// Will be recreated in applyState
|
||||
_impl = NULL;
|
||||
}
|
||||
|
|
@ -376,15 +339,15 @@ void GFXGLTextureTarget::deactivate()
|
|||
|
||||
void GFXGLTextureTarget::applyState()
|
||||
{
|
||||
if(!isPendingState())
|
||||
if (!isPendingState())
|
||||
return;
|
||||
|
||||
// So we don't do this over and over again
|
||||
stateApplied();
|
||||
|
||||
if(_impl.isNull())
|
||||
|
||||
if (_impl.isNull())
|
||||
_impl = new _GFXGLTextureTargetFBOImpl(this);
|
||||
|
||||
|
||||
_impl->applyState();
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +357,7 @@ _GFXGLTargetDesc* GFXGLTextureTarget::getTargetDesc(RenderSlot slot) const
|
|||
return mTargets[slot].ptr();
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::_onTextureEvent( GFXTexCallbackCode code )
|
||||
void GFXGLTextureTarget::_onTextureEvent(GFXTexCallbackCode code)
|
||||
{
|
||||
invalidateState();
|
||||
}
|
||||
|
|
@ -403,7 +366,7 @@ const String GFXGLTextureTarget::describeSelf() const
|
|||
{
|
||||
String ret = String::ToString(" Color0 Attachment: %i", mTargets[Color0].isValid() ? mTargets[Color0]->getHandle() : 0);
|
||||
ret += String::ToString(" Depth Attachment: %i", mTargets[DepthStencil].isValid() ? mTargets[DepthStencil]->getHandle() : 0);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -416,27 +379,27 @@ void GFXGLTextureTarget::resolveTo(GFXTextureObject* obj)
|
|||
AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
|
||||
GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);
|
||||
|
||||
if( GFXGL->mCapabilities.copyImage && mTargets[Color0]->isCompatible(glTexture) )
|
||||
if (GFXGL->mCapabilities.copyImage && mTargets[Color0]->isCompatible(glTexture))
|
||||
{
|
||||
GLenum binding = mTargets[Color0]->getBinding();
|
||||
GLenum binding = mTargets[Color0]->getBinding();
|
||||
binding = (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ? GL_TEXTURE_CUBE_MAP : binding;
|
||||
U32 srcStartDepth = binding == GL_TEXTURE_CUBE_MAP ? mTargets[Color0]->getBinding() - GL_TEXTURE_CUBE_MAP_POSITIVE_X : 0;
|
||||
glCopyImageSubData(
|
||||
mTargets[Color0]->getHandle(), binding, 0, 0, 0, srcStartDepth,
|
||||
glTexture->getHandle(), glTexture->getBinding(), 0, 0, 0, 0,
|
||||
mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(), 1);
|
||||
mTargets[Color0]->getHandle(), binding, 0, 0, 0, srcStartDepth,
|
||||
glTexture->getHandle(), glTexture->getBinding(), 0, 0, 0, 0,
|
||||
mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(), 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PRESERVE_FRAMEBUFFER();
|
||||
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mCopyFboDst);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glTexture->getBinding(), glTexture->getHandle(), 0);
|
||||
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mCopyFboSrc);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTargets[Color0]->getBinding(), mTargets[Color0]->getHandle(), 0);
|
||||
|
||||
|
||||
glBlitFramebuffer(0, 0, mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(),
|
||||
0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,35 +50,35 @@ public:
|
|||
|
||||
const Point2I getSize() override;
|
||||
GFXFormat getFormat() override;
|
||||
void attachTexture(RenderSlot slot, GFXTextureObject *tex, U32 mipLevel=0, U32 zOffset = 0) override;
|
||||
void attachTexture(RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel=0) override;
|
||||
void attachTexture(RenderSlot slot, GFXTextureObject* tex, U32 mipLevel = 0, U32 zOffset = 0, U32 face = 0) override;
|
||||
void attachTexture(RenderSlot slot, GFXCubemap* tex, U32 face, U32 mipLevel = 0) override;
|
||||
virtual void clearAttachments();
|
||||
|
||||
/// Functions to query internal state
|
||||
/// @{
|
||||
|
||||
|
||||
/// Returns the internal structure for the given slot. This should only be called by our internal implementations.
|
||||
_GFXGLTargetDesc* getTargetDesc(RenderSlot slot) const;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
void deactivate() override;
|
||||
void zombify() override;
|
||||
void resurrect() override;
|
||||
const String describeSelf() const override;
|
||||
|
||||
|
||||
void resolve() override;
|
||||
|
||||
|
||||
void resolveTo(GFXTextureObject* obj) override;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
friend class GFXGLDevice;
|
||||
|
||||
/// The callback used to get texture events.
|
||||
/// @see GFXTextureManager::addEventDelegate
|
||||
void _onTextureEvent( GFXTexCallbackCode code );
|
||||
|
||||
void _onTextureEvent(GFXTexCallbackCode code);
|
||||
|
||||
/// Pointer to our internal implementation
|
||||
AutoPtr<_GFXGLTextureTargetImpl> _impl;
|
||||
|
||||
|
|
@ -87,10 +87,10 @@ protected:
|
|||
|
||||
/// These redirect to our internal implementation
|
||||
/// @{
|
||||
|
||||
|
||||
void applyState();
|
||||
void makeActive();
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
//copy FBO
|
||||
|
|
|
|||
|
|
@ -103,8 +103,6 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
|
|||
}
|
||||
|
||||
SDL_ClearError();
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
|
||||
|
||||
|
|
@ -140,6 +138,10 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
|
|||
return;
|
||||
}
|
||||
|
||||
// Set our sdl attribute to use this version.
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
|
||||
|
||||
//check for required extensions
|
||||
if (!gglHasExtension(ARB_texture_cube_map_array))
|
||||
{
|
||||
|
|
@ -168,7 +170,24 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
|
|||
dStrcpy(toAdd->mName, "OpenGL", GFXAdapter::MaxAdapterNameLen);
|
||||
|
||||
toAdd->mType = OpenGL;
|
||||
toAdd->mShaderModel = 0.f;
|
||||
F32 shaderModel = 3.3f;
|
||||
if (major == 4)
|
||||
{
|
||||
if (minor == 0)
|
||||
shaderModel = 4.00f; // GLSL 4.00
|
||||
else if (minor == 1)
|
||||
shaderModel = 4.10f; // GLSL 4.10
|
||||
else if (minor == 2)
|
||||
shaderModel = 4.20f; // GLSL 4.20
|
||||
else if (minor == 3)
|
||||
shaderModel = 4.30f; // GLSL 4.30
|
||||
else if (minor == 4)
|
||||
shaderModel = 4.40f; // GLSL 4.40
|
||||
else if (minor == 5)
|
||||
shaderModel = 4.50f; // GLSL 4.50
|
||||
else if (minor == 6)
|
||||
shaderModel = 4.60f; // GLSL 4.60
|
||||
}
|
||||
toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance;
|
||||
|
||||
// Enumerate all available resolutions:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue