- Added initial version of shared OpenGL texture. In upcoming commits existing issues will be fixed.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5172 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
016c81a9f3
commit
1553bef11f
|
@ -113,8 +113,8 @@ class ITexture : public virtual IReferenceCounted
|
|||
public:
|
||||
|
||||
//! constructor
|
||||
ITexture(const io::path& name) : NamedPath(name), DriverType(EDT_NULL), ColorFormat(ECF_UNKNOWN),
|
||||
Pitch(0), HasMipMaps(false), IsRenderTarget(false), Source(ETS_UNKNOWN)
|
||||
ITexture(const io::path& name) : NamedPath(name), DriverType(EDT_NULL), OriginalColorFormat(ECF_UNKNOWN),
|
||||
ColorFormat(ECF_UNKNOWN), Pitch(0), HasMipMaps(false), IsRenderTarget(false), Source(ETS_UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -252,6 +252,7 @@ protected:
|
|||
core::dimension2d<u32> OriginalSize;
|
||||
core::dimension2d<u32> Size;
|
||||
E_DRIVER_TYPE DriverType;
|
||||
ECOLOR_FORMAT OriginalColorFormat;
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
u32 Pitch;
|
||||
bool HasMipMaps;
|
||||
|
|
|
@ -1309,6 +1309,39 @@ bool CNullDriver::checkPrimitiveCount(u32 prmCount) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CNullDriver::checkColorFormat(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) const
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case ECF_DXT1:
|
||||
case ECF_DXT2:
|
||||
case ECF_DXT3:
|
||||
case ECF_DXT4:
|
||||
case ECF_DXT5:
|
||||
{
|
||||
core::dimension2d<u32> sizePOT = size.getOptimalSize(true, false);
|
||||
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
|
||||
{
|
||||
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
else if (sizePOT != size)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for DXT texture, size of image must be power of two.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//! Enables or disables a texture creation flag.
|
||||
void CNullDriver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled)
|
||||
{
|
||||
|
|
|
@ -690,6 +690,8 @@ namespace video
|
|||
//! checks triangle count and print warning if wrong
|
||||
bool checkPrimitiveCount(u32 prmcnt) const;
|
||||
|
||||
bool checkColorFormat(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) const;
|
||||
|
||||
// adds a material renderer and drops it afterwards. To be used for internal creation
|
||||
s32 addAndDropMaterialRenderer(IMaterialRenderer* m);
|
||||
|
||||
|
|
|
@ -0,0 +1,417 @@
|
|||
// Copyright (C) 2015 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_OGLCORE_TEXTURE_H_INCLUDED__
|
||||
#define __C_OGLCORE_TEXTURE_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_OPENGL_) || defined(_IRR_COMPILE_WITH_OGLES1_) || defined(_IRR_COMPILE_WITH_OGLES2_)
|
||||
|
||||
#include "irrArray.h"
|
||||
#include "SMaterialLayer.h"
|
||||
#include "ITexture.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
template <class TOGLDriver>
|
||||
class COGLCoreTexture : public ITexture
|
||||
{
|
||||
public:
|
||||
struct SStatesCache
|
||||
{
|
||||
SStatesCache() : WrapU(ETC_REPEAT), WrapV(ETC_REPEAT),
|
||||
LODBias(0), AnisotropicFilter(0),
|
||||
BilinearFilter(false), TrilinearFilter(false),
|
||||
MipMapStatus(false), IsCached(false)
|
||||
{
|
||||
}
|
||||
|
||||
u8 WrapU;
|
||||
u8 WrapV;
|
||||
s8 LODBias;
|
||||
u8 AnisotropicFilter;
|
||||
bool BilinearFilter;
|
||||
bool TrilinearFilter;
|
||||
bool MipMapStatus;
|
||||
bool IsCached;
|
||||
};
|
||||
|
||||
COGLCoreTexture(const io::path& name, const core::array<IImage*>& image, TOGLDriver* driver) : ITexture(name), Driver(driver), TextureType(GL_TEXTURE_2D),
|
||||
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA), PixelType(GL_UNSIGNED_BYTE), LockReadOnly(false), LockImage(0), LockLevel(0), KeepImage(true),
|
||||
AutoGenerateMipMaps(false)
|
||||
{
|
||||
_IRR_DEBUG_BREAK_IF(image.size() == 0)
|
||||
|
||||
DriverType = Driver->getDriverType();
|
||||
HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
|
||||
AutoGenerateMipMaps = Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE);
|
||||
|
||||
getImageValues(image[0]);
|
||||
|
||||
const core::array<IImage*>* tmpImage = ℑ
|
||||
|
||||
if (KeepImage || OriginalSize != Size || OriginalColorFormat != ColorFormat)
|
||||
{
|
||||
Image.set_used(image.size());
|
||||
|
||||
for (u32 i = 0; i < image.size(); ++i)
|
||||
{
|
||||
Image[i] = Driver->createImage(ColorFormat, Size);
|
||||
|
||||
if (image[i]->getDimension() == Size)
|
||||
image[i]->copyTo(Image[i]);
|
||||
else
|
||||
image[i]->copyToScaling(Image[i]);
|
||||
}
|
||||
|
||||
tmpImage = &Image;
|
||||
}
|
||||
|
||||
Pitch = (*tmpImage)[0]->getPitch();
|
||||
|
||||
glGenTextures(1, &TextureName);
|
||||
|
||||
const COGLCoreTexture* prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
|
||||
Driver->getCacheHandler()->getTextureCache().set(0, this);
|
||||
|
||||
if (HasMipMaps && AutoGenerateMipMaps)
|
||||
{
|
||||
if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
|
||||
else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
|
||||
glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||
else
|
||||
glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);
|
||||
}
|
||||
|
||||
#if defined(IRR_OPENGL_VERSION) && IRR_OPENGL_VERSION < 20
|
||||
if (HasMipMaps)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, (AutoGenerateMipMaps) ? GL_TRUE : GL_FALSE);
|
||||
#endif
|
||||
|
||||
uploadTexture(true, 0, (*tmpImage)[0]->getData());
|
||||
|
||||
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
|
||||
|
||||
regenerateMipMapLevels((*tmpImage)[0]->getMipMapsData());
|
||||
|
||||
if (!KeepImage)
|
||||
{
|
||||
for (u32 i = 0; i < Image.size(); ++i)
|
||||
Image[i]->drop();
|
||||
|
||||
Image.clear();
|
||||
}
|
||||
}
|
||||
|
||||
COGLCoreTexture(const io::path& name, const core::dimension2d<u32>& size, ECOLOR_FORMAT format, TOGLDriver* driver) : ITexture(name), Driver(driver), TextureType(GL_TEXTURE_2D),
|
||||
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA), PixelType(GL_UNSIGNED_BYTE), LockReadOnly(false), LockImage(0), LockLevel(0), KeepImage(false),
|
||||
AutoGenerateMipMaps(false)
|
||||
{
|
||||
DriverType = Driver->getDriverType();
|
||||
HasMipMaps = false;
|
||||
IsRenderTarget = true;
|
||||
|
||||
OriginalColorFormat = format;
|
||||
|
||||
if (ECF_UNKNOWN == OriginalColorFormat)
|
||||
ColorFormat = getBestColorFormat(Driver->getColorFormat());
|
||||
else
|
||||
ColorFormat = OriginalColorFormat;
|
||||
|
||||
OriginalSize = size;
|
||||
Size = OriginalSize;
|
||||
|
||||
void(*converter)(const void*, s32, void*) = 0;
|
||||
|
||||
Driver->getColorFormatParameters(ColorFormat, InternalFormat, PixelFormat, PixelType, &converter);
|
||||
|
||||
glGenTextures(1, &TextureName);
|
||||
|
||||
const COGLCoreTexture* prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
|
||||
Driver->getCacheHandler()->getTextureCache().set(0, this);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
StatesCache.WrapU = ETC_CLAMP_TO_EDGE;
|
||||
StatesCache.WrapV = ETC_CLAMP_TO_EDGE;
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Size.Width, Size.Height, 0, PixelFormat, PixelType, 0);
|
||||
|
||||
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
|
||||
}
|
||||
|
||||
virtual ~COGLCoreTexture()
|
||||
{
|
||||
Driver->getCacheHandler()->getTextureCache().remove(this);
|
||||
|
||||
if (TextureName)
|
||||
glDeleteTextures(1, &TextureName);
|
||||
|
||||
for (u32 i = 0; i < Image.size(); ++i)
|
||||
Image[i]->drop();
|
||||
|
||||
if (LockImage)
|
||||
LockImage->drop();
|
||||
}
|
||||
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode = ETLM_READ_WRITE, u32 mipmapLevel = 0) _IRR_OVERRIDE_
|
||||
{
|
||||
// TO-DO - this method will be improved.
|
||||
|
||||
if (IImage::isCompressedFormat(ColorFormat) || IsRenderTarget || mipmapLevel > 0) // TO-DO
|
||||
return 0;
|
||||
|
||||
LockReadOnly |= (mode == ETLM_READ_ONLY);
|
||||
LockLevel = mipmapLevel;
|
||||
|
||||
LockImage = Image[0];
|
||||
|
||||
return LockImage->getData();
|
||||
}
|
||||
|
||||
virtual void unlock() _IRR_OVERRIDE_
|
||||
{
|
||||
if (!LockImage)
|
||||
return;
|
||||
|
||||
if (!LockReadOnly)
|
||||
{
|
||||
const COGLCoreTexture* prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
|
||||
Driver->getCacheHandler()->getTextureCache().set(0, this);
|
||||
|
||||
uploadTexture(false, LockLevel, LockImage->getData());
|
||||
|
||||
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
|
||||
|
||||
if (LockLevel == 0)
|
||||
regenerateMipMapLevels(LockImage->getMipMapsData());
|
||||
}
|
||||
|
||||
if (!KeepImage || LockLevel != 0)
|
||||
LockImage->drop();
|
||||
|
||||
LockReadOnly = false;
|
||||
LockImage = 0;
|
||||
LockLevel = 0;
|
||||
}
|
||||
|
||||
virtual void regenerateMipMapLevels(void* mipMapsData = 0) _IRR_OVERRIDE_
|
||||
{
|
||||
if (!HasMipMaps || (!mipMapsData && !AutoGenerateMipMaps) || (Size.Width <= 1 && Size.Height <= 1))
|
||||
return;
|
||||
|
||||
const COGLCoreTexture* prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
|
||||
Driver->getCacheHandler()->getTextureCache().set(0, this);
|
||||
|
||||
if (mipMapsData)
|
||||
{
|
||||
u32 width = Size.Width;
|
||||
u32 height = Size.Height;
|
||||
u8* data = static_cast<u8*>(mipMapsData);
|
||||
u32 dataSize = 0;
|
||||
u32 level = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (width > 1)
|
||||
width >>= 1;
|
||||
|
||||
if (height > 1)
|
||||
height >>= 1;
|
||||
|
||||
dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
|
||||
++level;
|
||||
|
||||
if (!IImage::isCompressedFormat(ColorFormat))
|
||||
glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, width, height, 0, PixelFormat, PixelType, data);
|
||||
else
|
||||
Driver->irrGlCompressedTexImage2D(GL_TEXTURE_2D, level, InternalFormat, width, height, 0, dataSize, data);
|
||||
|
||||
data += dataSize;
|
||||
}
|
||||
while (width != 1 || height != 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(IRR_OPENGL_VERSION) && IRR_OPENGL_VERSION >= 20
|
||||
Driver->irrGlGenerateMipmap(GL_TEXTURE_2D);
|
||||
#endif
|
||||
}
|
||||
|
||||
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
|
||||
}
|
||||
|
||||
GLenum getOpenGLTextureType() const
|
||||
{
|
||||
return TextureType;
|
||||
}
|
||||
|
||||
GLuint getOpenGLTextureName() const
|
||||
{
|
||||
return TextureName;
|
||||
}
|
||||
|
||||
SStatesCache& getStatesCache() const
|
||||
{
|
||||
return StatesCache;
|
||||
}
|
||||
|
||||
protected:
|
||||
ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format)
|
||||
{
|
||||
ECOLOR_FORMAT destFormat = (!IImage::isCompressedFormat(format)) ? ECF_A8R8G8B8 : format;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
|
||||
Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL))
|
||||
{
|
||||
switch (destFormat)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
destFormat = ECF_R5G6B5;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
destFormat = ECF_R8G8B8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return destFormat;
|
||||
}
|
||||
|
||||
void getImageValues(const IImage* image)
|
||||
{
|
||||
OriginalColorFormat = image->getColorFormat();
|
||||
ColorFormat = getBestColorFormat(OriginalColorFormat);
|
||||
|
||||
void(*converter)(const void*, s32, void*) = 0;
|
||||
|
||||
Driver->getColorFormatParameters(ColorFormat, InternalFormat, PixelFormat, PixelType, &converter);
|
||||
|
||||
if (IImage::isCompressedFormat(image->getColorFormat()))
|
||||
{
|
||||
KeepImage = false;
|
||||
AutoGenerateMipMaps = false;
|
||||
}
|
||||
|
||||
OriginalSize = image->getDimension();
|
||||
Size = OriginalSize;
|
||||
|
||||
if (Size.Width == 0 || Size.Height == 0)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for texture.", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
const f32 ratio = (f32)Size.Width / (f32)Size.Height;
|
||||
|
||||
if ((Size.Width > Driver->MaxTextureSize) && (ratio >= 1.f))
|
||||
{
|
||||
Size.Width = Driver->MaxTextureSize;
|
||||
Size.Height = (u32)(Driver->MaxTextureSize / ratio);
|
||||
}
|
||||
else if (Size.Height > Driver->MaxTextureSize)
|
||||
{
|
||||
Size.Height = Driver->MaxTextureSize;
|
||||
Size.Width = (u32)(Driver->MaxTextureSize * ratio);
|
||||
}
|
||||
|
||||
Size = Size.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT));
|
||||
}
|
||||
|
||||
void uploadTexture(bool initTexture, u32 level, const void* data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (initTexture)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
u32 width = Size.Width >> level;
|
||||
u32 height = Size.Height >> level;
|
||||
|
||||
if (!IImage::isCompressedFormat(ColorFormat))
|
||||
{
|
||||
if (initTexture)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, width, height, 0, PixelFormat, PixelType, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, PixelFormat, PixelType, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 dataSize = IImage::getDataSizeFromFormat(ColorFormat, Size.Width, height);
|
||||
|
||||
if (initTexture)
|
||||
{
|
||||
Driver->irrGlCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, width, height, 0, dataSize, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
Driver->irrGlCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, PixelFormat, dataSize, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TOGLDriver* Driver;
|
||||
|
||||
GLenum TextureType;
|
||||
GLuint TextureName;
|
||||
GLint InternalFormat;
|
||||
GLenum PixelFormat;
|
||||
GLenum PixelType;
|
||||
|
||||
bool LockReadOnly;
|
||||
IImage* LockImage;
|
||||
u32 LockLevel;
|
||||
|
||||
bool KeepImage;
|
||||
core::array<IImage*> Image;
|
||||
|
||||
bool AutoGenerateMipMaps;
|
||||
|
||||
mutable SStatesCache StatesCache;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -7,7 +7,6 @@
|
|||
#ifdef _IRR_COMPILE_WITH_OPENGL_
|
||||
|
||||
#include "COpenGLDriver.h"
|
||||
#include "COpenGLTexture.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
|
|
@ -9,15 +9,14 @@
|
|||
|
||||
#ifdef _IRR_COMPILE_WITH_OPENGL_
|
||||
|
||||
#include "COpenGLExtensionHandler.h"
|
||||
#include "COpenGLCommon.h"
|
||||
#include "COGLCoreTexture.h"
|
||||
#include "COGLCoreCacheHandler.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class COpenGLTexture;
|
||||
class COpenGLDriver;
|
||||
|
||||
class COpenGLCacheHandler : public COGLCoreCacheHandler<COpenGLDriver, COpenGLTexture>
|
||||
{
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
#ifdef _IRR_COMPILE_WITH_OPENGL_
|
||||
|
||||
#include "COGLCoreTexture.h"
|
||||
#include "COGLCoreRenderTarget.h"
|
||||
|
||||
#include "COpenGLCacheHandler.h"
|
||||
#include "COpenGLTexture.h"
|
||||
#include "COpenGLMaterialRenderer.h"
|
||||
#include "COpenGLShaderMaterialRenderer.h"
|
||||
#include "COpenGLSLMaterialRenderer.h"
|
||||
|
@ -2523,7 +2523,17 @@ inline void COpenGLDriver::getGLTextureMatrix(GLfloat *o, const core::matrix4& m
|
|||
//! returns a device dependent texture from a software surface (IImage)
|
||||
video::ITexture* COpenGLDriver::createDeviceDependentTexture(IImage* surface, const io::path& name)
|
||||
{
|
||||
return new COpenGLTexture(surface, name, this);
|
||||
COpenGLTexture* texture = 0;
|
||||
|
||||
if (surface && checkColorFormat(surface->getColorFormat(), surface->getDimension()))
|
||||
{
|
||||
core::array<IImage*> imageArray(1);
|
||||
imageArray.push_back(surface);
|
||||
|
||||
texture = new COpenGLTexture(name, imageArray, this);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3192,7 +3202,7 @@ void COpenGLDriver::setTextureRenderStates(const SMaterial& material, bool reset
|
|||
if (FixedPipelineState == EOFPS_ENABLE || FixedPipelineState == EOFPS_DISABLE_TO_ENABLE)
|
||||
fixedPipeline = true;
|
||||
|
||||
const COpenGLTexture* tmpTexture = CacheHandler->getTextureCache()[i];
|
||||
const COpenGLTexture* tmpTexture = CacheHandler->getTextureCache().get(i);
|
||||
|
||||
if (!tmpTexture)
|
||||
continue;
|
||||
|
@ -3218,13 +3228,15 @@ void COpenGLDriver::setTextureRenderStates(const SMaterial& material, bool reset
|
|||
}
|
||||
}
|
||||
|
||||
if(resetAllRenderstates)
|
||||
tmpTexture->getStatesCache().IsCached = false;
|
||||
COpenGLTexture::SStatesCache& statesCache = tmpTexture->getStatesCache();
|
||||
|
||||
if (resetAllRenderstates)
|
||||
statesCache.IsCached = false;
|
||||
|
||||
#ifdef GL_VERSION_2_1
|
||||
if (Version>=210)
|
||||
{
|
||||
if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].LODBias != tmpTexture->getStatesCache().LODBias)
|
||||
if(!statesCache.IsCached || material.TextureLayer[i].LODBias != statesCache.LODBias)
|
||||
{
|
||||
if (material.TextureLayer[i].LODBias)
|
||||
{
|
||||
|
@ -3234,7 +3246,7 @@ void COpenGLDriver::setTextureRenderStates(const SMaterial& material, bool reset
|
|||
else
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.f);
|
||||
|
||||
tmpTexture->getStatesCache().LODBias = material.TextureLayer[i].LODBias;
|
||||
statesCache.LODBias = material.TextureLayer[i].LODBias;
|
||||
}
|
||||
}
|
||||
else if (FeatureAvailable[IRR_EXT_texture_lod_bias])
|
||||
|
@ -3260,69 +3272,69 @@ void COpenGLDriver::setTextureRenderStates(const SMaterial& material, bool reset
|
|||
}
|
||||
#endif
|
||||
|
||||
if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
|
||||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter)
|
||||
if(!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
|
||||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
|
||||
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
|
||||
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
|
||||
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
|
||||
}
|
||||
|
||||
if (material.UseMipMaps && tmpTexture->hasMipMaps())
|
||||
{
|
||||
if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
|
||||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || !tmpTexture->getStatesCache().MipMapStatus)
|
||||
if(!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
|
||||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || !statesCache.MipMapStatus)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
|
||||
material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
|
||||
GL_NEAREST_MIPMAP_NEAREST);
|
||||
|
||||
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
|
||||
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
|
||||
tmpTexture->getStatesCache().MipMapStatus = true;
|
||||
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
|
||||
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
|
||||
statesCache.MipMapStatus = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
|
||||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || tmpTexture->getStatesCache().MipMapStatus)
|
||||
if(!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
|
||||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || statesCache.MipMapStatus)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
|
||||
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
|
||||
tmpTexture->getStatesCache().MipMapStatus = false;
|
||||
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
|
||||
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
|
||||
statesCache.MipMapStatus = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GL_EXT_texture_filter_anisotropic
|
||||
if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic] &&
|
||||
(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].AnisotropicFilter != tmpTexture->getStatesCache().AnisotropicFilter))
|
||||
(!statesCache.IsCached || material.TextureLayer[i].AnisotropicFilter != statesCache.AnisotropicFilter))
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1);
|
||||
|
||||
tmpTexture->getStatesCache().AnisotropicFilter = material.TextureLayer[i].AnisotropicFilter;
|
||||
statesCache.AnisotropicFilter = material.TextureLayer[i].AnisotropicFilter;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapU != tmpTexture->getStatesCache().WrapU)
|
||||
if(!statesCache.IsCached || material.TextureLayer[i].TextureWrapU != statesCache.WrapU)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[i].TextureWrapU));
|
||||
tmpTexture->getStatesCache().WrapU = material.TextureLayer[i].TextureWrapU;
|
||||
statesCache.WrapU = material.TextureLayer[i].TextureWrapU;
|
||||
}
|
||||
|
||||
if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapV != tmpTexture->getStatesCache().WrapV)
|
||||
if(!statesCache.IsCached || material.TextureLayer[i].TextureWrapV != statesCache.WrapV)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[i].TextureWrapV));
|
||||
tmpTexture->getStatesCache().WrapV = material.TextureLayer[i].TextureWrapV;
|
||||
statesCache.WrapV = material.TextureLayer[i].TextureWrapV;
|
||||
}
|
||||
|
||||
tmpTexture->getStatesCache().IsCached = true;
|
||||
statesCache.IsCached = true;
|
||||
}
|
||||
|
||||
// be sure to leave in texture stage 0
|
||||
|
@ -3368,7 +3380,6 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
|
|||
|
||||
CacheHandler->setMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.375f, 0.375f, 0.0f);
|
||||
|
||||
// Make sure we set first texture matrix
|
||||
CacheHandler->setActiveTexture(GL_TEXTURE0);
|
||||
|
@ -4589,6 +4600,206 @@ GLenum COpenGLDriver::getZBufferBits() const
|
|||
return bits;
|
||||
}
|
||||
|
||||
void COpenGLDriver::getColorFormatParameters(ECOLOR_FORMAT format, GLint& internalFormat, GLenum& pixelFormat,
|
||||
GLenum& pixelType, void(**converter)(const void*, s32, void*))
|
||||
{
|
||||
internalFormat = GL_RGBA;
|
||||
pixelFormat = GL_RGBA;
|
||||
pixelType = GL_UNSIGNED_BYTE;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
internalFormat = GL_RGBA;
|
||||
pixelFormat = GL_BGRA_EXT;
|
||||
pixelType = GL_UNSIGNED_SHORT_1_5_5_5_REV;
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
internalFormat = GL_RGB;
|
||||
pixelFormat = GL_RGB;
|
||||
pixelType = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
internalFormat = GL_RGB;
|
||||
pixelFormat = GL_BGR;
|
||||
pixelType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
internalFormat = GL_RGBA;
|
||||
pixelFormat = GL_BGRA_EXT;
|
||||
if (Version > 101)
|
||||
pixelType = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
break;
|
||||
case ECF_DXT1:
|
||||
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
pixelFormat = GL_BGRA_EXT;
|
||||
pixelType = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
break;
|
||||
case ECF_DXT2:
|
||||
case ECF_DXT3:
|
||||
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
pixelFormat = GL_BGRA_EXT;
|
||||
pixelType = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
break;
|
||||
case ECF_DXT4:
|
||||
case ECF_DXT5:
|
||||
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
pixelFormat = GL_BGRA_EXT;
|
||||
pixelType = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
break;
|
||||
case ECF_D16:
|
||||
internalFormat = GL_DEPTH_COMPONENT16;
|
||||
pixelFormat = GL_DEPTH_COMPONENT;
|
||||
pixelType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case ECF_D32:
|
||||
internalFormat = GL_DEPTH_COMPONENT32;
|
||||
pixelFormat = GL_DEPTH_COMPONENT;
|
||||
pixelType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case ECF_D24S8:
|
||||
#ifdef GL_EXT_packed_depth_stencil
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil))
|
||||
{
|
||||
internalFormat = GL_DEPTH_STENCIL_EXT;
|
||||
pixelFormat = GL_DEPTH_STENCIL_EXT;
|
||||
pixelType = GL_UNSIGNED_INT_24_8_EXT;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
os::Printer::log("ECF_D24S8 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R8:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
internalFormat = GL_R8;
|
||||
pixelFormat = GL_RED;
|
||||
pixelType = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R8 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R8G8:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
internalFormat = GL_RG8;
|
||||
pixelFormat = GL_RG;
|
||||
pixelType = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R8G8 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R16:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
internalFormat = GL_R16;
|
||||
pixelFormat = GL_RED;
|
||||
pixelType = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R16 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R16G16:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
internalFormat = GL_RG16;
|
||||
pixelFormat = GL_RG;
|
||||
pixelType = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R16G16 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R16F:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
internalFormat = GL_R16F;
|
||||
pixelFormat = GL_RED;
|
||||
#ifdef GL_ARB_half_float_pixel
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
|
||||
pixelType = GL_HALF_FLOAT_ARB;
|
||||
else
|
||||
#endif
|
||||
pixelType = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R16F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_G16R16F:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
internalFormat = GL_RG16F;
|
||||
pixelFormat = GL_RG;
|
||||
#ifdef GL_ARB_half_float_pixel
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
|
||||
pixelType = GL_HALF_FLOAT_ARB;
|
||||
else
|
||||
#endif
|
||||
pixelType = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_G16R16F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_A16B16G16R16F:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_float))
|
||||
{
|
||||
internalFormat = GL_RGBA16F_ARB;
|
||||
pixelFormat = GL_RGBA;
|
||||
#ifdef GL_ARB_half_float_pixel
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
|
||||
pixelType = GL_HALF_FLOAT_ARB;
|
||||
else
|
||||
#endif
|
||||
pixelType = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_A16B16G16R16F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R32F:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
internalFormat = GL_R32F;
|
||||
pixelFormat = GL_RED;
|
||||
pixelType = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R32F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_G32R32F:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
internalFormat = GL_RG32F;
|
||||
pixelFormat = GL_RG;
|
||||
pixelType = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_G32R32F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_A32B32G32R32F:
|
||||
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_float))
|
||||
{
|
||||
internalFormat = GL_RGBA32F_ARB;
|
||||
pixelFormat = GL_RGBA;
|
||||
pixelType = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_A32B32G32R32F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
default:
|
||||
os::Printer::log("Unsupported texture format", ELL_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB)
|
||||
if (Params.HandleSRGB)
|
||||
{
|
||||
if (internalFormat == GL_RGBA)
|
||||
internalFormat = GL_SRGB_ALPHA_EXT;
|
||||
else if (internalFormat == GL_RGB)
|
||||
internalFormat = GL_SRGB_EXT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COpenGLDriver::E_OPENGL_FIXED_PIPELINE_STATE COpenGLDriver::getFixedPipelineState() const
|
||||
{
|
||||
return FixedPipelineState;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace irr
|
|||
|
||||
#include "CNullDriver.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
// also includes the OpenGL stuff
|
||||
#include "COpenGLCommon.h"
|
||||
#include "COpenGLExtensionHandler.h"
|
||||
|
||||
namespace irr
|
||||
|
@ -29,19 +29,10 @@ namespace irr
|
|||
|
||||
namespace video
|
||||
{
|
||||
template <class TOGLDriver, class TOGLTexture>
|
||||
class COGLCoreRenderTarget;
|
||||
|
||||
class COpenGLCacheHandler;
|
||||
class COpenGLTexture;
|
||||
class COpenGLDriver;
|
||||
|
||||
typedef COGLCoreRenderTarget<COpenGLDriver, COpenGLTexture> COpenGLRenderTarget;
|
||||
|
||||
class COpenGLDriver : public CNullDriver, public IMaterialRendererServices, public COpenGLExtensionHandler
|
||||
{
|
||||
friend class COpenGLCacheHandler;
|
||||
friend class COpenGLTexture;
|
||||
friend COpenGLCacheHandler;
|
||||
friend COpenGLTexture;
|
||||
public:
|
||||
// Information about state of fixed pipeline activity.
|
||||
enum E_OPENGL_FIXED_PIPELINE_STATE
|
||||
|
@ -406,6 +397,9 @@ namespace video
|
|||
//! Get ZBuffer bits.
|
||||
GLenum getZBufferBits() const;
|
||||
|
||||
void getColorFormatParameters(ECOLOR_FORMAT format, GLint& internalFormat, GLenum& pixelFormat,
|
||||
GLenum& pixelType, void(**converter)(const void*, s32, void*));
|
||||
|
||||
//! Return info about fixed pipeline state.
|
||||
E_OPENGL_FIXED_PIPELINE_STATE getFixedPipelineState() const;
|
||||
|
||||
|
|
|
@ -6,139 +6,13 @@
|
|||
#define __C_OPEN_GL_FEATURE_MAP_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_OPENGL_
|
||||
|
||||
#include "EDriverFeatures.h"
|
||||
#include "irrTypes.h"
|
||||
#include "os.h"
|
||||
|
||||
#if defined(_IRR_WINDOWS_API_)
|
||||
// include windows headers for HWND
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#define GL_GLEXT_LEGACY 1
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#include "glext.h"
|
||||
#endif
|
||||
#include "wglext.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "OpenGL32.lib")
|
||||
#endif
|
||||
|
||||
#elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_)
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#define GL_GLEXT_LEGACY 1
|
||||
#endif
|
||||
#include <OpenGL/gl.h>
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#include "glext.h"
|
||||
#endif
|
||||
#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) && !defined(_IRR_COMPILE_WITH_X11_DEVICE_)
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#define GL_GLEXT_LEGACY 1
|
||||
#define GLX_GLXEXT_LEGACY 1
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#define GLX_GLXEXT_PROTOTYPES 1
|
||||
#endif
|
||||
#define NO_SDL_GLEXT
|
||||
#include <SDL/SDL_video.h>
|
||||
#include <SDL/SDL_opengl.h>
|
||||
#include "glext.h"
|
||||
#else
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#define GL_GLEXT_LEGACY 1
|
||||
#define GLX_GLXEXT_LEGACY 1
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#define GLX_GLXEXT_PROTOTYPES 1
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#include "glext.h"
|
||||
#undef GLX_ARB_get_proc_address // avoid problems with local glxext.h
|
||||
#include "glxext.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GL_ARB_shader_objects
|
||||
/* GL types for program/shader text and shader object handles */
|
||||
typedef char GLcharARB;
|
||||
typedef unsigned int GLhandleARB;
|
||||
#endif
|
||||
|
||||
#ifndef GL_VERSION_2_0
|
||||
/* GL type for program/shader text */
|
||||
typedef char GLchar;
|
||||
#endif
|
||||
|
||||
// Blending definitions.
|
||||
|
||||
#if !defined(GL_VERSION_1_4)
|
||||
#if defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op)
|
||||
#define GL_FUNC_ADD GL_FUNC_ADD_EXT
|
||||
#else
|
||||
#define GL_FUNC_ADD 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// FBO definitions.
|
||||
|
||||
#if !defined(GL_VERSION_3_0) && !defined(GL_ARB_framebuffer_object)
|
||||
#ifdef GL_EXT_framebuffer_object
|
||||
#define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
|
||||
#define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
|
||||
#define GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
|
||||
#define GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT
|
||||
#define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED GL_FRAMEBUFFER_UNSUPPORTED_EXT
|
||||
#else
|
||||
#define GL_FRAMEBUFFER 0
|
||||
#define GL_COLOR_ATTACHMENT0 0
|
||||
#define GL_DEPTH_ATTACHMENT 0
|
||||
#define GL_STENCIL_ATTACHMENT 0
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 1
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 2
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 3
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 4
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED 5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GL_EXT_framebuffer_object
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
|
||||
#else
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS 6
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 7
|
||||
#endif
|
||||
|
||||
// Texture definitions.
|
||||
|
||||
#if !defined(GL_VERSION_1_3)
|
||||
#ifdef GL_ARB_multitexture
|
||||
#define GL_TEXTURE0 GL_TEXTURE0_ARB
|
||||
#else
|
||||
#define GL_TEXTURE0 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Irrlicht's OpenGL version.
|
||||
|
||||
#define IRR_OPENGL_VERSION 14
|
||||
|
||||
#include "COpenGLCommon.h"
|
||||
#include "COGLCoreFeature.h"
|
||||
|
||||
namespace irr
|
||||
|
@ -1182,10 +1056,10 @@ class COpenGLExtensionHandler
|
|||
void extGlPointParameterfv(GLint loc, const GLfloat *v);
|
||||
void extGlStencilFuncSeparate (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
|
||||
void extGlStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
|
||||
void extGlCompressedTexImage2D(GLenum target, GLint level,
|
||||
void irrGlCompressedTexImage2D(GLenum target, GLint level,
|
||||
GLenum internalformat, GLsizei width, GLsizei height,
|
||||
GLint border, GLsizei imageSize, const void* data);
|
||||
void extGlCompressedTexSubImage2D(GLenum target, GLint level,
|
||||
void irrGlCompressedTexSubImage2D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
||||
GLenum format, GLsizei imageSize, const void* data);
|
||||
|
||||
|
@ -2133,7 +2007,7 @@ inline void COpenGLExtensionHandler::extGlStencilOpSeparate (GLenum face, GLenum
|
|||
#endif
|
||||
}
|
||||
|
||||
inline void COpenGLExtensionHandler::extGlCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width,
|
||||
inline void COpenGLExtensionHandler::irrGlCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width,
|
||||
GLsizei height, GLint border, GLsizei imageSize, const void* data)
|
||||
{
|
||||
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
|
||||
|
@ -2146,7 +2020,7 @@ inline void COpenGLExtensionHandler::extGlCompressedTexImage2D (GLenum target, G
|
|||
#endif
|
||||
}
|
||||
|
||||
inline void COpenGLExtensionHandler::extGlCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
inline void COpenGLExtensionHandler::irrGlCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
|
||||
{
|
||||
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "COpenGLDriver.h"
|
||||
#include "COpenGLTexture.h"
|
||||
#include "COpenGLCacheHandler.h"
|
||||
#include "COpenGLMaterialRenderer.h"
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "COpenGLDriver.h"
|
||||
#include "COpenGLTexture.h"
|
||||
#include "COpenGLCacheHandler.h"
|
||||
#include "COpenGLMaterialRenderer.h"
|
||||
|
||||
|
|
|
@ -1,838 +0,0 @@
|
|||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_OPENGL_
|
||||
|
||||
#include "irrTypes.h"
|
||||
#include "COpenGLTexture.h"
|
||||
#include "COpenGLDriver.h"
|
||||
#include "COpenGLCacheHandler.h"
|
||||
#include "os.h"
|
||||
#include "CColorConverter.h"
|
||||
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! constructor for a standard textures
|
||||
COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, COpenGLDriver* driver)
|
||||
: ITexture(name), Driver(driver), Image(0), MipImage(0), TextureName(0), InternalFormat(GL_RGBA),
|
||||
PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true),
|
||||
IsCompressed(false), AutomaticMipmapUpdate(false), ReadOnlyLock(false), KeepImage(true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("COpenGLTexture");
|
||||
#endif
|
||||
|
||||
DriverType = EDT_OPENGL;
|
||||
ColorFormat = ECF_A8R8G8B8;
|
||||
HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
|
||||
IsRenderTarget = false;
|
||||
|
||||
getImageValues(origImage);
|
||||
|
||||
if (IImage::isCompressedFormat(ColorFormat))
|
||||
{
|
||||
if (!Driver->queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
|
||||
{
|
||||
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (OriginalSize != Size)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for compressed texture, size of image must be POT.", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsCompressed = true;
|
||||
Image = origImage;
|
||||
Image->grab();
|
||||
KeepImage = false;
|
||||
}
|
||||
}
|
||||
else if (OriginalSize == Size)
|
||||
{
|
||||
Image = Driver->createImage(ColorFormat, OriginalSize);
|
||||
origImage->copyTo(Image);
|
||||
}
|
||||
else
|
||||
{
|
||||
Image = Driver->createImage(ColorFormat, Size);
|
||||
// scale texture
|
||||
origImage->copyToScaling(Image);
|
||||
}
|
||||
|
||||
Pitch = Image->getPitch();
|
||||
|
||||
glGenTextures(1, &TextureName);
|
||||
uploadTexture(true, origImage->getMipMapsData());
|
||||
if (!KeepImage)
|
||||
{
|
||||
Image->drop();
|
||||
Image=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! constructor for a render target textures
|
||||
COpenGLTexture::COpenGLTexture(const io::path& name, const core::dimension2d<u32>& size, ECOLOR_FORMAT format, COpenGLDriver* driver)
|
||||
: ITexture(name), Driver(driver), Image(0), MipImage(0), TextureName(0), InternalFormat(GL_RGBA),
|
||||
PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(false),
|
||||
IsCompressed(false), AutomaticMipmapUpdate(false), ReadOnlyLock(false), KeepImage(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("COpenGLTexture");
|
||||
#endif
|
||||
|
||||
COpenGLCacheHandler* cacheHandler = Driver->getCacheHandler();
|
||||
const COpenGLTexture* prevTexture = cacheHandler->getTextureCache()[0];
|
||||
|
||||
DriverType = EDT_OPENGL;
|
||||
|
||||
if (ECF_UNKNOWN == format)
|
||||
format = getBestColorFormat(driver->getColorFormat());
|
||||
|
||||
OriginalSize = size;
|
||||
Size = size;
|
||||
ColorFormat = format;
|
||||
|
||||
GLint FilteringType = 0;
|
||||
InternalFormat = getOpenGLFormatAndParametersFromColorFormat(format, FilteringType, PixelFormat, PixelType);
|
||||
|
||||
HasMipMaps = false;
|
||||
IsRenderTarget = true;
|
||||
|
||||
glGenTextures(1, &TextureName);
|
||||
|
||||
cacheHandler->getTextureCache().set(0, this);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilteringType);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (FilteringType == GL_NEAREST)
|
||||
StatesCache.BilinearFilter = false;
|
||||
else
|
||||
StatesCache.BilinearFilter = true;
|
||||
|
||||
StatesCache.WrapU = ETC_CLAMP_TO_EDGE;
|
||||
StatesCache.WrapV = ETC_CLAMP_TO_EDGE;
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, OriginalSize.Width, OriginalSize.Height, 0, PixelFormat, PixelType, 0);
|
||||
|
||||
cacheHandler->getTextureCache().set(0, prevTexture);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
COpenGLTexture::~COpenGLTexture()
|
||||
{
|
||||
Driver->getCacheHandler()->getTextureCache().remove(this);
|
||||
|
||||
if (TextureName)
|
||||
glDeleteTextures(1, &TextureName);
|
||||
if (Image)
|
||||
Image->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Choose best matching color format, based on texture creation flags
|
||||
ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format)
|
||||
{
|
||||
ECOLOR_FORMAT destFormat = ECF_A8R8G8B8;
|
||||
switch (format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
|
||||
Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
|
||||
Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL))
|
||||
{
|
||||
switch (destFormat)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
destFormat = ECF_R5G6B5;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
destFormat = ECF_R8G8B8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return destFormat;
|
||||
}
|
||||
|
||||
|
||||
//! Get opengl values for the GPU texture storage
|
||||
GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format,
|
||||
GLint& filtering,
|
||||
GLenum& colorformat,
|
||||
GLenum& type)
|
||||
{
|
||||
// default
|
||||
filtering = GL_LINEAR;
|
||||
colorformat = GL_RGBA;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
GLenum internalformat = GL_RGBA;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
colorformat=GL_BGRA_EXT;
|
||||
type=GL_UNSIGNED_SHORT_1_5_5_5_REV;
|
||||
internalformat = GL_RGBA;
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
colorformat=GL_RGB;
|
||||
type=GL_UNSIGNED_SHORT_5_6_5;
|
||||
internalformat = GL_RGB;
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
colorformat=GL_BGR;
|
||||
type=GL_UNSIGNED_BYTE;
|
||||
internalformat = GL_RGB;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
colorformat=GL_BGRA_EXT;
|
||||
if (Driver->Version > 101)
|
||||
type=GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
internalformat = GL_RGBA;
|
||||
break;
|
||||
case ECF_DXT1:
|
||||
colorformat = GL_BGRA_EXT;
|
||||
type = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
internalformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
break;
|
||||
case ECF_DXT2:
|
||||
case ECF_DXT3:
|
||||
colorformat = GL_BGRA_EXT;
|
||||
type = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
internalformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
break;
|
||||
case ECF_DXT4:
|
||||
case ECF_DXT5:
|
||||
colorformat = GL_BGRA_EXT;
|
||||
type = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
internalformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
break;
|
||||
case ECF_D16:
|
||||
colorformat = GL_DEPTH_COMPONENT;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
internalformat = GL_DEPTH_COMPONENT16;
|
||||
break;
|
||||
case ECF_D32:
|
||||
colorformat = GL_DEPTH_COMPONENT;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
internalformat = GL_DEPTH_COMPONENT32;
|
||||
break;
|
||||
case ECF_D24S8:
|
||||
#ifdef GL_EXT_packed_depth_stencil
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil))
|
||||
{
|
||||
colorformat = GL_DEPTH_STENCIL_EXT;
|
||||
type = GL_UNSIGNED_INT_24_8_EXT;
|
||||
internalformat = GL_DEPTH_STENCIL_EXT;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
os::Printer::log("ECF_D24S8 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R8:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
colorformat = GL_RED;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
internalformat = GL_R8;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R8 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R8G8:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
colorformat = GL_RG;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
internalformat = GL_RG8;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R8G8 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R16:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
colorformat = GL_RED;
|
||||
type = GL_UNSIGNED_SHORT;
|
||||
internalformat = GL_R16;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R16 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R16G16:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
colorformat = GL_RG;
|
||||
type = GL_UNSIGNED_SHORT;
|
||||
internalformat = GL_RG16;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R16G16 color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R16F:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
filtering = GL_NEAREST;
|
||||
colorformat = GL_RED;
|
||||
internalformat = GL_R16F;
|
||||
#ifdef GL_ARB_half_float_pixel
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
|
||||
type = GL_HALF_FLOAT_ARB;
|
||||
else
|
||||
#endif
|
||||
type = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R16F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_G16R16F:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
filtering = GL_NEAREST;
|
||||
colorformat = GL_RG;
|
||||
internalformat = GL_RG16F;
|
||||
#ifdef GL_ARB_half_float_pixel
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
|
||||
type = GL_HALF_FLOAT_ARB;
|
||||
else
|
||||
#endif
|
||||
type = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_G16R16F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_A16B16G16R16F:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_float))
|
||||
{
|
||||
filtering = GL_NEAREST;
|
||||
colorformat = GL_RGBA;
|
||||
internalformat = GL_RGBA16F_ARB;
|
||||
#ifdef GL_ARB_half_float_pixel
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
|
||||
type = GL_HALF_FLOAT_ARB;
|
||||
else
|
||||
#endif
|
||||
type = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_A16B16G16R16F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_R32F:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
filtering = GL_NEAREST;
|
||||
colorformat = GL_RED;
|
||||
internalformat = GL_R32F;
|
||||
type = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_R32F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_G32R32F:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
|
||||
{
|
||||
filtering = GL_NEAREST;
|
||||
colorformat = GL_RG;
|
||||
internalformat = GL_RG32F;
|
||||
type = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_G32R32F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
case ECF_A32B32G32R32F:
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_float))
|
||||
{
|
||||
filtering = GL_NEAREST;
|
||||
colorformat = GL_RGBA;
|
||||
internalformat = GL_RGBA32F_ARB;
|
||||
type = GL_FLOAT;
|
||||
}
|
||||
else
|
||||
os::Printer::log("ECF_A32B32G32R32F color format is not supported", ELL_ERROR);
|
||||
break;
|
||||
default:
|
||||
os::Printer::log("Unsupported texture format", ELL_ERROR);
|
||||
break;
|
||||
}
|
||||
#if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB)
|
||||
if (Driver->Params.HandleSRGB)
|
||||
{
|
||||
if (internalformat==GL_RGBA)
|
||||
internalformat=GL_SRGB_ALPHA_EXT;
|
||||
else if (internalformat==GL_RGB)
|
||||
internalformat=GL_SRGB_EXT;
|
||||
}
|
||||
#endif
|
||||
return internalformat;
|
||||
}
|
||||
|
||||
|
||||
// prepare values ImageSize, TextureSize, and ColorFormat based on image
|
||||
void COpenGLTexture::getImageValues(IImage* image)
|
||||
{
|
||||
if (!image)
|
||||
{
|
||||
os::Printer::log("No image for OpenGL texture.", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
OriginalSize = image->getDimension();
|
||||
|
||||
if (!OriginalSize.Width || !OriginalSize.Height)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for OpenGL Texture.", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
const f32 ratio = (f32)OriginalSize.Width / (f32)OriginalSize.Height;
|
||||
|
||||
if ((OriginalSize.Width>Driver->MaxTextureSize) && (ratio >= 1.0f))
|
||||
{
|
||||
OriginalSize.Width = Driver->MaxTextureSize;
|
||||
OriginalSize.Height = (u32)(Driver->MaxTextureSize / ratio);
|
||||
}
|
||||
else if (OriginalSize.Height>Driver->MaxTextureSize)
|
||||
{
|
||||
OriginalSize.Height = Driver->MaxTextureSize;
|
||||
OriginalSize.Width = (u32)(Driver->MaxTextureSize*ratio);
|
||||
}
|
||||
|
||||
Size = OriginalSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT));
|
||||
|
||||
if (IImage::isCompressedFormat(image->getColorFormat()))
|
||||
ColorFormat = image->getColorFormat();
|
||||
else
|
||||
ColorFormat = getBestColorFormat(image->getColorFormat());
|
||||
}
|
||||
|
||||
|
||||
//! copies the the texture into an open gl texture.
|
||||
void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
|
||||
{
|
||||
// check which image needs to be uploaded
|
||||
IImage* image = level?MipImage:Image;
|
||||
if (!image)
|
||||
{
|
||||
os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
COpenGLCacheHandler* cacheHandler = Driver->getCacheHandler();
|
||||
const COpenGLTexture* prevTexture = cacheHandler->getTextureCache()[0];
|
||||
|
||||
// get correct opengl color data values
|
||||
GLenum oldInternalFormat = InternalFormat;
|
||||
GLint filtering;
|
||||
InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType);
|
||||
// make sure we don't change the internal format of existing images
|
||||
if (!newTexture)
|
||||
InternalFormat=oldInternalFormat;
|
||||
|
||||
cacheHandler->getTextureCache().set(0, this);
|
||||
|
||||
if (Driver->testGLError())
|
||||
os::Printer::log("Could not bind Texture", ELL_ERROR);
|
||||
|
||||
// mipmap handling for main texture
|
||||
if (!level && newTexture)
|
||||
{
|
||||
// auto generate if possible and no mipmap data is given
|
||||
if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
|
||||
{
|
||||
if (!Driver->queryFeature(EVDF_FRAMEBUFFER_OBJECT))
|
||||
{
|
||||
#ifdef GL_SGIS_generate_mipmap
|
||||
if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST);
|
||||
else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
|
||||
glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
|
||||
else
|
||||
glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE);
|
||||
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
|
||||
MipmapLegacyMode=true;
|
||||
AutomaticMipmapUpdate=true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
|
||||
else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
|
||||
glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||
else
|
||||
glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);
|
||||
|
||||
MipmapLegacyMode=false;
|
||||
AutomaticMipmapUpdate=true;
|
||||
}
|
||||
}
|
||||
|
||||
// enable bilinear filter without mipmaps
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
StatesCache.BilinearFilter = true;
|
||||
StatesCache.TrilinearFilter = false;
|
||||
StatesCache.MipMapStatus = false;
|
||||
}
|
||||
|
||||
// now get image data and upload to GPU
|
||||
u32 compressedDataSize = 0;
|
||||
|
||||
void* source = image->lock();
|
||||
if (newTexture)
|
||||
{
|
||||
if (IsCompressed)
|
||||
{
|
||||
if(ColorFormat == ECF_DXT1)
|
||||
compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 8;
|
||||
else if (ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
|
||||
compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 16;
|
||||
|
||||
Driver->extGlCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width,
|
||||
image->getDimension().Height, 0, compressedDataSize, source);
|
||||
}
|
||||
else
|
||||
glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width,
|
||||
image->getDimension().Height, 0, PixelFormat, PixelType, source);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsCompressed)
|
||||
{
|
||||
if(ColorFormat == ECF_DXT1)
|
||||
compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 8;
|
||||
else if (ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
|
||||
compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 16;
|
||||
|
||||
Driver->extGlCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
|
||||
image->getDimension().Height, PixelFormat, compressedDataSize, source);
|
||||
}
|
||||
else
|
||||
glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
|
||||
image->getDimension().Height, PixelFormat, PixelType, source);
|
||||
}
|
||||
image->unlock();
|
||||
|
||||
if (!level && newTexture)
|
||||
{
|
||||
if (IsCompressed && !mipmapData)
|
||||
HasMipMaps = false;
|
||||
|
||||
regenerateMipMapLevels(mipmapData);
|
||||
|
||||
if (HasMipMaps) // might have changed in regenerateMipMapLevels
|
||||
{
|
||||
// enable bilinear mipmap filter
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
StatesCache.BilinearFilter = true;
|
||||
StatesCache.TrilinearFilter = false;
|
||||
StatesCache.MipMapStatus = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Driver->testGLError())
|
||||
os::Printer::log("Could not glTexImage2D", ELL_ERROR);
|
||||
|
||||
cacheHandler->getTextureCache().set(0, prevTexture);
|
||||
}
|
||||
|
||||
|
||||
//! lock function
|
||||
void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
if (IsCompressed) // TO-DO
|
||||
return 0;
|
||||
|
||||
COpenGLCacheHandler* cacheHandler = Driver->getCacheHandler();
|
||||
const COpenGLTexture* prevTexture = cacheHandler->getTextureCache()[0];
|
||||
|
||||
cacheHandler->getTextureCache().set(0, this);
|
||||
|
||||
// store info about which image is locked
|
||||
IImage* image = (mipmapLevel==0)?Image:MipImage;
|
||||
ReadOnlyLock |= (mode==ETLM_READ_ONLY);
|
||||
MipLevelStored = mipmapLevel;
|
||||
if (!ReadOnlyLock && mipmapLevel)
|
||||
{
|
||||
#ifdef GL_SGIS_generate_mipmap
|
||||
if (Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
|
||||
{
|
||||
// do not automatically generate and update mipmaps
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
|
||||
}
|
||||
#endif
|
||||
AutomaticMipmapUpdate=false;
|
||||
}
|
||||
|
||||
// if data not available or might have changed on GPU download it
|
||||
if (!image || IsRenderTarget)
|
||||
{
|
||||
// prepare the data storage if necessary
|
||||
if (!image)
|
||||
{
|
||||
if (mipmapLevel)
|
||||
{
|
||||
u32 i=0;
|
||||
u32 width = Size.Width;
|
||||
u32 height = Size.Height;
|
||||
do
|
||||
{
|
||||
if (width>1)
|
||||
width>>=1;
|
||||
if (height>1)
|
||||
height>>=1;
|
||||
++i;
|
||||
}
|
||||
while (i != mipmapLevel);
|
||||
MipImage = image = Driver->createImage(ECF_A8R8G8B8, core::dimension2du(width,height));
|
||||
}
|
||||
else
|
||||
Image = image = Driver->createImage(ECF_A8R8G8B8, OriginalSize);
|
||||
ColorFormat = ECF_A8R8G8B8;
|
||||
}
|
||||
if (!image)
|
||||
{
|
||||
cacheHandler->getTextureCache().set(0, prevTexture);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode != ETLM_WRITE_ONLY)
|
||||
{
|
||||
u8* pixels = static_cast<u8*>(image->lock());
|
||||
if (!pixels)
|
||||
{
|
||||
cacheHandler->getTextureCache().set(0, prevTexture);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// we need to flip textures vertical
|
||||
// however, it seems that this does not hold for mipmap
|
||||
// textures, for unknown reasons.
|
||||
|
||||
// allows to read pixels in top-to-bottom order
|
||||
#ifdef GL_MESA_pack_invert
|
||||
if (!mipmapLevel && Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
|
||||
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
|
||||
#endif
|
||||
|
||||
// download GPU data as ARGB8 to pixels;
|
||||
glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
if (!mipmapLevel)
|
||||
{
|
||||
#ifdef GL_MESA_pack_invert
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
|
||||
glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// opengl images are horizontally flipped, so we have to fix that here.
|
||||
const s32 pitch=image->getPitch();
|
||||
u8* p2 = pixels + (image->getDimension().Height - 1) * pitch;
|
||||
u8* tmpBuffer = new u8[pitch];
|
||||
for (u32 i=0; i < image->getDimension().Height; i += 2)
|
||||
{
|
||||
memcpy(tmpBuffer, pixels, pitch);
|
||||
memcpy(pixels, p2, pitch);
|
||||
memcpy(p2, tmpBuffer, pitch);
|
||||
pixels += pitch;
|
||||
p2 -= pitch;
|
||||
}
|
||||
delete [] tmpBuffer;
|
||||
}
|
||||
}
|
||||
image->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
cacheHandler->getTextureCache().set(0, prevTexture);
|
||||
|
||||
return image->lock();
|
||||
}
|
||||
|
||||
|
||||
//! unlock function
|
||||
void COpenGLTexture::unlock()
|
||||
{
|
||||
if (IsCompressed) // TO-DO
|
||||
return;
|
||||
|
||||
// test if miplevel or main texture was locked
|
||||
IImage* image = MipImage?MipImage:Image;
|
||||
if (!image)
|
||||
return;
|
||||
// unlock image to see changes
|
||||
image->unlock();
|
||||
// copy texture data to GPU
|
||||
if (!ReadOnlyLock)
|
||||
uploadTexture(false, 0, MipLevelStored);
|
||||
ReadOnlyLock = false;
|
||||
// cleanup local image
|
||||
if (MipImage)
|
||||
{
|
||||
MipImage->drop();
|
||||
MipImage=0;
|
||||
}
|
||||
else if (!KeepImage)
|
||||
{
|
||||
Image->drop();
|
||||
Image=0;
|
||||
}
|
||||
// update information
|
||||
if (Image)
|
||||
ColorFormat=Image->getColorFormat();
|
||||
else
|
||||
ColorFormat=ECF_A8R8G8B8;
|
||||
}
|
||||
|
||||
|
||||
//! return open gl texture name
|
||||
GLuint COpenGLTexture::getOpenGLTextureName() const
|
||||
{
|
||||
return TextureName;
|
||||
}
|
||||
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
void COpenGLTexture::regenerateMipMapLevels(void* mipmapData)
|
||||
{
|
||||
// texture require mipmaps?
|
||||
if (!HasMipMaps)
|
||||
return;
|
||||
|
||||
// we don't use custom data for mipmaps.
|
||||
if (!mipmapData)
|
||||
{
|
||||
// compressed textures require custom data for prepare mipmaps.
|
||||
if (IsCompressed)
|
||||
return;
|
||||
|
||||
// texture use legacy method for generate mipmaps?
|
||||
if (AutomaticMipmapUpdate && MipmapLegacyMode)
|
||||
return;
|
||||
|
||||
// hardware doesn't support generate mipmaps for certain texture but image data doesn't exist or is wrong.
|
||||
if (!AutomaticMipmapUpdate && (!Image || (Image && ((Image->getDimension().Width==1) && (Image->getDimension().Height==1)))))
|
||||
return;
|
||||
}
|
||||
|
||||
COpenGLCacheHandler* cacheHandler = Driver->getCacheHandler();
|
||||
const COpenGLTexture* prevTexture = cacheHandler->getTextureCache()[0];
|
||||
|
||||
cacheHandler->getTextureCache().set(0, this);
|
||||
|
||||
// hardware moethods for generate mipmaps.
|
||||
if (!mipmapData && AutomaticMipmapUpdate && !MipmapLegacyMode)
|
||||
{
|
||||
Driver->irrGlGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
cacheHandler->getTextureCache().set(0, prevTexture);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Manually create mipmaps or use prepared version
|
||||
u32 compressedDataSize = 0;
|
||||
u32 width=Image->getDimension().Width;
|
||||
u32 height=Image->getDimension().Height;
|
||||
u32 i=0;
|
||||
u8* target = static_cast<u8*>(mipmapData);
|
||||
do
|
||||
{
|
||||
if (width>1)
|
||||
width>>=1;
|
||||
if (height>1)
|
||||
height>>=1;
|
||||
|
||||
++i;
|
||||
|
||||
if (!target)
|
||||
target = new u8[width*height*Image->getBytesPerPixel()];
|
||||
|
||||
// create scaled version if no mipdata available
|
||||
if (!mipmapData)
|
||||
Image->copyToScaling(target, width, height, Image->getColorFormat());
|
||||
|
||||
if (IsCompressed)
|
||||
{
|
||||
if(ColorFormat == ECF_DXT1)
|
||||
compressedDataSize = ((width + 3) / 4) * ((height + 3) / 4) * 8;
|
||||
else if (ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
|
||||
compressedDataSize = ((width + 3) / 4) * ((height + 3) / 4) * 16;
|
||||
|
||||
Driver->extGlCompressedTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width,
|
||||
height, 0, compressedDataSize, target);
|
||||
}
|
||||
else
|
||||
glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height,
|
||||
0, PixelFormat, PixelType, target);
|
||||
|
||||
// get next prepared mipmap data if available
|
||||
if (mipmapData)
|
||||
{
|
||||
if (IsCompressed)
|
||||
mipmapData = static_cast<u8*>(mipmapData)+compressedDataSize;
|
||||
else
|
||||
mipmapData = static_cast<u8*>(mipmapData)+width*height*Image->getBytesPerPixel();
|
||||
|
||||
target = static_cast<u8*>(mipmapData);
|
||||
}
|
||||
}
|
||||
while (width!=1 || height!=1);
|
||||
// cleanup
|
||||
if (!mipmapData)
|
||||
delete [] target;
|
||||
|
||||
cacheHandler->getTextureCache().set(0, prevTexture);
|
||||
}
|
||||
|
||||
COpenGLTexture::SStatesCache& COpenGLTexture::getStatesCache() const
|
||||
{
|
||||
return StatesCache;
|
||||
}
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_OPENGL_
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_OPEN_GL_TEXTURE_H_INCLUDED__
|
||||
#define __C_OPEN_GL_TEXTURE_H_INCLUDED__
|
||||
|
||||
#include "ITexture.h"
|
||||
#include "IImage.h"
|
||||
#include "SMaterialLayer.h"
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_OPENGL_
|
||||
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#define GL_GLEXT_LEGACY 1
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#endif
|
||||
#ifdef _IRR_WINDOWS_API_
|
||||
// include windows headers for HWND
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "OpenGL32.lib")
|
||||
#endif
|
||||
#elif defined(_IRR_OSX_PLATFORM_)
|
||||
#include <OpenGL/gl.h>
|
||||
#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
|
||||
#define NO_SDL_GLEXT
|
||||
#include <SDL/SDL_video.h>
|
||||
#include <SDL/SDL_opengl.h>
|
||||
#else
|
||||
#if defined(_IRR_OSX_PLATFORM_)
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class COpenGLDriver;
|
||||
|
||||
//! OpenGL texture.
|
||||
class COpenGLTexture : public ITexture
|
||||
{
|
||||
public:
|
||||
|
||||
//! Cache structure.
|
||||
struct SStatesCache
|
||||
{
|
||||
SStatesCache() : WrapU(ETC_REPEAT), WrapV(ETC_REPEAT),
|
||||
LODBias(0), AnisotropicFilter(0),
|
||||
BilinearFilter(false), TrilinearFilter(false),
|
||||
MipMapStatus(false), IsCached(false)
|
||||
{
|
||||
}
|
||||
|
||||
u8 WrapU;
|
||||
u8 WrapV;
|
||||
s8 LODBias;
|
||||
u8 AnisotropicFilter;
|
||||
bool BilinearFilter;
|
||||
bool TrilinearFilter;
|
||||
bool MipMapStatus;
|
||||
bool IsCached;
|
||||
};
|
||||
|
||||
//! constructor for a standard textures
|
||||
COpenGLTexture(IImage* surface, const io::path& name, COpenGLDriver* driver);
|
||||
|
||||
//! constructor for a render target textures
|
||||
COpenGLTexture(const io::path& name, const core::dimension2d<u32>& size, ECOLOR_FORMAT format, COpenGLDriver* driver);
|
||||
|
||||
//! destructor
|
||||
virtual ~COpenGLTexture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock() _IRR_OVERRIDE_;
|
||||
|
||||
//! Regenerates the mip map levels of the texture.
|
||||
/** Useful after locking and modifying the texture
|
||||
\param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image. If not set the mipmaps are derived from the main image. */
|
||||
virtual void regenerateMipMapLevels(void* mipmapData = 0) _IRR_OVERRIDE_;
|
||||
|
||||
//! return open gl texture name
|
||||
GLuint getOpenGLTextureName() const;
|
||||
|
||||
//! Get an access to texture states cache.
|
||||
SStatesCache& getStatesCache() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! protected constructor with basic setup, no GL texture name created, for derived classes
|
||||
COpenGLTexture(const io::path& name, COpenGLDriver* driver);
|
||||
|
||||
//! get the desired color format based on texture creation flags and the input format.
|
||||
ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format);
|
||||
|
||||
//! Get the OpenGL color format parameters based on the given Irrlicht color format
|
||||
GLint getOpenGLFormatAndParametersFromColorFormat(
|
||||
ECOLOR_FORMAT format, GLint& filtering, GLenum& colorformat, GLenum& type);
|
||||
|
||||
//! get important numbers of the image and hw texture
|
||||
void getImageValues(IImage* image);
|
||||
|
||||
//! copies the texture into an OpenGL texture.
|
||||
/** \param newTexture True if method is called for a newly created texture for the first time. Otherwise call with false to improve memory handling.
|
||||
\param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image.
|
||||
\param mipLevel If set to non-zero, only that specific miplevel is updated, using the MipImage member. */
|
||||
void uploadTexture(bool newTexture=false, void* mipmapData=0, u32 mipLevel=0);
|
||||
|
||||
COpenGLDriver* Driver;
|
||||
IImage* Image;
|
||||
IImage* MipImage;
|
||||
|
||||
GLuint TextureName;
|
||||
GLint InternalFormat;
|
||||
GLenum PixelFormat;
|
||||
GLenum PixelType;
|
||||
|
||||
u8 MipLevelStored;
|
||||
bool MipmapLegacyMode;
|
||||
bool IsCompressed;
|
||||
bool AutomaticMipmapUpdate;
|
||||
bool ReadOnlyLock;
|
||||
bool KeepImage;
|
||||
|
||||
mutable SStatesCache StatesCache;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif // _IRR_COMPILE_WITH_OPENGL_
|
||||
|
|
@ -845,8 +845,6 @@
|
|||
<Unit filename="COpenGLSLMaterialRenderer.h" />
|
||||
<Unit filename="COpenGLShaderMaterialRenderer.cpp" />
|
||||
<Unit filename="COpenGLShaderMaterialRenderer.h" />
|
||||
<Unit filename="COpenGLTexture.cpp" />
|
||||
<Unit filename="COpenGLTexture.h" />
|
||||
<Unit filename="CPLYMeshFileLoader.cpp" />
|
||||
<Unit filename="CPLYMeshFileLoader.h" />
|
||||
<Unit filename="CPLYMeshWriter.cpp" />
|
||||
|
|
|
@ -1011,7 +1011,9 @@
|
|||
<ClInclude Include="COGLCoreCacheHandler.h" />
|
||||
<ClInclude Include="COGLCoreFeature.h" />
|
||||
<ClInclude Include="COGLCoreRenderTarget.h" />
|
||||
<ClInclude Include="COGLCoreTexture.h" />
|
||||
<ClInclude Include="COpenGLCacheHandler.h" />
|
||||
<ClInclude Include="COpenGLCommon.h" />
|
||||
<ClInclude Include="COpenGLDriver.h" />
|
||||
<ClInclude Include="COpenGLExtensionHandler.h" />
|
||||
<ClInclude Include="COpenGLMaterialRenderer.h" />
|
||||
|
@ -1019,7 +1021,6 @@
|
|||
<ClInclude Include="COpenGLParallaxMapRenderer.h" />
|
||||
<ClInclude Include="COpenGLShaderMaterialRenderer.h" />
|
||||
<ClInclude Include="COpenGLSLMaterialRenderer.h" />
|
||||
<ClInclude Include="COpenGLTexture.h" />
|
||||
<ClInclude Include="CProfiler.h" />
|
||||
<ClInclude Include="CSceneManager.h" />
|
||||
<ClInclude Include="Octree.h" />
|
||||
|
@ -1264,7 +1265,6 @@
|
|||
<ClCompile Include="COpenGLParallaxMapRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLShaderMaterialRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLSLMaterialRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLTexture.cpp" />
|
||||
<ClCompile Include="CSceneManager.cpp" />
|
||||
<ClCompile Include="C3DSMeshFileLoader.cpp" />
|
||||
<ClCompile Include="CSMFMeshFileLoader.cpp" />
|
||||
|
|
|
@ -1288,6 +1288,9 @@
|
|||
<ClInclude Include="COpenGLCacheHandler.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLCommon.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLDriver.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1309,9 +1312,6 @@
|
|||
<ClInclude Include="COpenGLSLMaterialRenderer.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLTexture.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COGLCoreCacheHandler.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1321,6 +1321,9 @@
|
|||
<ClInclude Include="COGLCoreRenderTarget.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COGLCoreTexture.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\changes.txt">
|
||||
|
@ -2249,9 +2252,6 @@
|
|||
<ClCompile Include="COpenGLSLMaterialRenderer.cpp">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="COpenGLTexture.cpp">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Irrlicht.rc" />
|
||||
|
|
|
@ -1011,7 +1011,9 @@
|
|||
<ClInclude Include="COGLCoreCacheHandler.h" />
|
||||
<ClInclude Include="COGLCoreFeature.h" />
|
||||
<ClInclude Include="COGLCoreRenderTarget.h" />
|
||||
<ClInclude Include="COGLCoreTexture.h" />
|
||||
<ClInclude Include="COpenGLCacheHandler.h" />
|
||||
<ClInclude Include="COpenGLCommon.h" />
|
||||
<ClInclude Include="COpenGLDriver.h" />
|
||||
<ClInclude Include="COpenGLExtensionHandler.h" />
|
||||
<ClInclude Include="COpenGLMaterialRenderer.h" />
|
||||
|
@ -1019,7 +1021,6 @@
|
|||
<ClInclude Include="COpenGLParallaxMapRenderer.h" />
|
||||
<ClInclude Include="COpenGLShaderMaterialRenderer.h" />
|
||||
<ClInclude Include="COpenGLSLMaterialRenderer.h" />
|
||||
<ClInclude Include="COpenGLTexture.h" />
|
||||
<ClInclude Include="CSceneManager.h" />
|
||||
<ClInclude Include="Octree.h" />
|
||||
<ClInclude Include="CSMFMeshFileLoader.h" />
|
||||
|
@ -1264,7 +1265,6 @@
|
|||
<ClCompile Include="COpenGLParallaxMapRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLShaderMaterialRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLSLMaterialRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLTexture.cpp" />
|
||||
<ClCompile Include="CSceneManager.cpp" />
|
||||
<ClCompile Include="C3DSMeshFileLoader.cpp" />
|
||||
<ClCompile Include="CSMFMeshFileLoader.cpp" />
|
||||
|
|
|
@ -1288,6 +1288,9 @@
|
|||
<ClInclude Include="COpenGLCacheHandler.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLCommon.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLDriver.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1309,9 +1312,6 @@
|
|||
<ClInclude Include="COpenGLSLMaterialRenderer.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLTexture.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COGLCoreCacheHandler.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1321,6 +1321,9 @@
|
|||
<ClInclude Include="COGLCoreRenderTarget.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COGLCoreTexture.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\changes.txt">
|
||||
|
@ -2249,9 +2252,6 @@
|
|||
<ClCompile Include="COpenGLSLMaterialRenderer.cpp">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="COpenGLTexture.cpp">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Irrlicht.rc" />
|
||||
|
|
|
@ -1011,7 +1011,9 @@
|
|||
<ClInclude Include="COGLCoreCacheHandler.h" />
|
||||
<ClInclude Include="COGLCoreFeature.h" />
|
||||
<ClInclude Include="COGLCoreRenderTarget.h" />
|
||||
<ClInclude Include="COGLCoreTexture.h" />
|
||||
<ClInclude Include="COpenGLCacheHandler.h" />
|
||||
<ClInclude Include="COpenGLCommon.h" />
|
||||
<ClInclude Include="COpenGLDriver.h" />
|
||||
<ClInclude Include="COpenGLExtensionHandler.h" />
|
||||
<ClInclude Include="COpenGLMaterialRenderer.h" />
|
||||
|
@ -1019,7 +1021,6 @@
|
|||
<ClInclude Include="COpenGLParallaxMapRenderer.h" />
|
||||
<ClInclude Include="COpenGLShaderMaterialRenderer.h" />
|
||||
<ClInclude Include="COpenGLSLMaterialRenderer.h" />
|
||||
<ClInclude Include="COpenGLTexture.h" />
|
||||
<ClInclude Include="CSceneManager.h" />
|
||||
<ClInclude Include="Octree.h" />
|
||||
<ClInclude Include="CSMFMeshFileLoader.h" />
|
||||
|
@ -1264,7 +1265,6 @@
|
|||
<ClCompile Include="COpenGLParallaxMapRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLShaderMaterialRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLSLMaterialRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLTexture.cpp" />
|
||||
<ClCompile Include="CSceneManager.cpp" />
|
||||
<ClCompile Include="C3DSMeshFileLoader.cpp" />
|
||||
<ClCompile Include="CSMFMeshFileLoader.cpp" />
|
||||
|
|
|
@ -1288,6 +1288,9 @@
|
|||
<ClInclude Include="COpenGLCacheHandler.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLCommon.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLDriver.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1309,9 +1312,6 @@
|
|||
<ClInclude Include="COpenGLSLMaterialRenderer.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLTexture.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COGLCoreCacheHandler.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1321,6 +1321,9 @@
|
|||
<ClInclude Include="COGLCoreRenderTarget.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COGLCoreTexture.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\changes.txt">
|
||||
|
@ -2249,9 +2252,6 @@
|
|||
<ClCompile Include="COpenGLSLMaterialRenderer.cpp">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="COpenGLTexture.cpp">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Irrlicht.rc" />
|
||||
|
|
|
@ -1021,7 +1021,9 @@
|
|||
<ClInclude Include="COGLCoreCacheHandler.h" />
|
||||
<ClInclude Include="COGLCoreFeature.h" />
|
||||
<ClInclude Include="COGLCoreRenderTarget.h" />
|
||||
<ClInclude Include="COGLCoreTexture.h" />
|
||||
<ClInclude Include="COpenGLCacheHandler.h" />
|
||||
<ClInclude Include="COpenGLCommon.h" />
|
||||
<ClInclude Include="COpenGLDriver.h" />
|
||||
<ClInclude Include="COpenGLExtensionHandler.h" />
|
||||
<ClInclude Include="COpenGLMaterialRenderer.h" />
|
||||
|
@ -1029,7 +1031,6 @@
|
|||
<ClInclude Include="COpenGLParallaxMapRenderer.h" />
|
||||
<ClInclude Include="COpenGLShaderMaterialRenderer.h" />
|
||||
<ClInclude Include="COpenGLSLMaterialRenderer.h" />
|
||||
<ClInclude Include="COpenGLTexture.h" />
|
||||
<ClInclude Include="CSceneManager.h" />
|
||||
<ClInclude Include="Octree.h" />
|
||||
<ClInclude Include="CSMFMeshFileLoader.h" />
|
||||
|
@ -1274,7 +1275,6 @@
|
|||
<ClCompile Include="COpenGLParallaxMapRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLShaderMaterialRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLSLMaterialRenderer.cpp" />
|
||||
<ClCompile Include="COpenGLTexture.cpp" />
|
||||
<ClCompile Include="CSceneManager.cpp" />
|
||||
<ClCompile Include="C3DSMeshFileLoader.cpp" />
|
||||
<ClCompile Include="CSMFMeshFileLoader.cpp" />
|
||||
|
|
|
@ -1288,6 +1288,9 @@
|
|||
<ClInclude Include="COpenGLCacheHandler.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLCommon.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLDriver.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1309,9 +1312,6 @@
|
|||
<ClInclude Include="COpenGLSLMaterialRenderer.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COpenGLTexture.h">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COGLCoreCacheHandler.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1321,6 +1321,9 @@
|
|||
<ClInclude Include="COGLCoreRenderTarget.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COGLCoreTexture.h">
|
||||
<Filter>Irrlicht\video\OpenGL Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\changes.txt">
|
||||
|
@ -2249,9 +2252,6 @@
|
|||
<ClCompile Include="COpenGLSLMaterialRenderer.cpp">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="COpenGLTexture.cpp">
|
||||
<Filter>Irrlicht\video\OpenGL</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Irrlicht.rc" />
|
||||
|
|
|
@ -38,7 +38,7 @@ IRRMESHOBJ = $(IRRMESHLOADER) $(IRRMESHWRITER) \
|
|||
IRROBJ = CBillboardSceneNode.o CCameraSceneNode.o CDummyTransformationSceneNode.o CEmptySceneNode.o CGeometryCreator.o CLightSceneNode.o CMeshManipulator.o CMetaTriangleSelector.o COctreeSceneNode.o COctreeTriangleSelector.o CSceneCollisionManager.o CSceneManager.o CShadowVolumeSceneNode.o CSkyBoxSceneNode.o CSkyDomeSceneNode.o CTerrainSceneNode.o CTerrainTriangleSelector.o CVolumeLightSceneNode.o CCubeSceneNode.o CSphereSceneNode.o CTextSceneNode.o CTriangleBBSelector.o CTriangleSelector.o CWaterSurfaceSceneNode.o CMeshCache.o CDefaultSceneNodeAnimatorFactory.o CDefaultSceneNodeFactory.o CSceneLoaderIrr.o
|
||||
IRRPARTICLEOBJ = CParticleAnimatedMeshSceneNodeEmitter.o CParticleBoxEmitter.o CParticleCylinderEmitter.o CParticleMeshEmitter.o CParticlePointEmitter.o CParticleRingEmitter.o CParticleSphereEmitter.o CParticleAttractionAffector.o CParticleFadeOutAffector.o CParticleGravityAffector.o CParticleRotationAffector.o CParticleSystemSceneNode.o CParticleScaleAffector.o
|
||||
IRRANIMOBJ = CSceneNodeAnimatorCameraFPS.o CSceneNodeAnimatorCameraMaya.o CSceneNodeAnimatorCollisionResponse.o CSceneNodeAnimatorDelete.o CSceneNodeAnimatorFlyCircle.o CSceneNodeAnimatorFlyStraight.o CSceneNodeAnimatorFollowSpline.o CSceneNodeAnimatorRotation.o CSceneNodeAnimatorTexture.o
|
||||
IRRDRVROBJ = CNullDriver.o COpenGLCacheHandler.o COpenGLDriver.o COpenGLNormalMapRenderer.o COpenGLParallaxMapRenderer.o COpenGLShaderMaterialRenderer.o COpenGLTexture.o COpenGLSLMaterialRenderer.o COpenGLExtensionHandler.o CD3D9Driver.o CD3D9HLSLMaterialRenderer.o CD3D9NormalMapRenderer.o CD3D9ParallaxMapRenderer.o CD3D9ShaderMaterialRenderer.o CD3D9Texture.o
|
||||
IRRDRVROBJ = CNullDriver.o COpenGLCacheHandler.o COpenGLDriver.o COpenGLNormalMapRenderer.o COpenGLParallaxMapRenderer.o COpenGLShaderMaterialRenderer.o COpenGLSLMaterialRenderer.o COpenGLExtensionHandler.o CD3D9Driver.o CD3D9HLSLMaterialRenderer.o CD3D9NormalMapRenderer.o CD3D9ParallaxMapRenderer.o CD3D9ShaderMaterialRenderer.o CD3D9Texture.o
|
||||
IRRIMAGEOBJ = CColorConverter.o CImage.o CImageLoaderBMP.o CImageLoaderDDS.o CImageLoaderJPG.o CImageLoaderPCX.o CImageLoaderPNG.o CImageLoaderPSD.o CImageLoaderTGA.o CImageLoaderPPM.o CImageLoaderWAL.o CImageLoaderRGB.o \
|
||||
CImageWriterBMP.o CImageWriterJPG.o CImageWriterPCX.o CImageWriterPNG.o CImageWriterPPM.o CImageWriterPSD.o CImageWriterTGA.o
|
||||
IRRVIDEOOBJ = CVideoModeList.o CFPSCounter.o $(IRRDRVROBJ) $(IRRIMAGEOBJ)
|
||||
|
|
Loading…
Reference in New Issue