diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index 67600466..1f11155f 100644 --- a/source/glest_game/main/main.cpp +++ b/source/glest_game/main/main.cpp @@ -2115,6 +2115,12 @@ int glestMain(int argc, char** argv) { config.setString("FactorySound","None"); } + bool enableATIHacks = config.getBool("EnableATIHacks","false"); + if(enableATIHacks == true) { + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**WARNING** Enabling ATI video card hacks\n"); + TextureGl::setEnableATIHacks(enableATIHacks); + } + // Set some statics based on ini entries SystemFlags::ENABLE_THREADED_LOGGING = config.getBool("ThreadedLogging","true"); FontGl::setDefault_fontType(config.getString("DefaultFont",FontGl::getDefault_fontType().c_str())); diff --git a/source/shared_lib/include/graphics/gl/texture_gl.h b/source/shared_lib/include/graphics/gl/texture_gl.h index 1578be71..b8f6c838 100644 --- a/source/shared_lib/include/graphics/gl/texture_gl.h +++ b/source/shared_lib/include/graphics/gl/texture_gl.h @@ -28,6 +28,8 @@ protected: GLuint renderBufferId; GLuint frameBufferId; + static bool enableATIHacks; + void initRenderBuffer(); void initFrameBuffer(); void attachRenderBuffer(); @@ -36,6 +38,9 @@ public: TextureGl(); virtual ~TextureGl(); + static void setEnableATIHacks(bool value) { enableATIHacks = value; } + static bool getEnableATIHacks() { return enableATIHacks; } + GLuint getHandle() const {return handle;} GLuint getRenderBufferHandle() const {return renderBufferId;} GLuint getFrameBufferHandle() const {return frameBufferId;} diff --git a/source/shared_lib/include/graphics/pixmap.h b/source/shared_lib/include/graphics/pixmap.h index 6ecdc91f..49af8931 100644 --- a/source/shared_lib/include/graphics/pixmap.h +++ b/source/shared_lib/include/graphics/pixmap.h @@ -30,6 +30,51 @@ using Shared::Platform::float32; namespace Shared{ namespace Graphics{ +/** + * @brief Next power of 2 + * @param x The number to be rounded + * @return the rounded number + * + * Rounds an unsigned integer up to the + * next power of 2; i.e. 2, 4, 8, 16, etc. + */ +static inline unsigned int next_power_of_2(unsigned int x) +{ + x--; + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return ++x; +} + +/** + * @brief Count bits set + * @param w Number in which to count bits + * @return The number of bits set + * + * Counts the number of bits in an unsigned int + * that are set to 1. So, for example, in the + * number 5, hich is 101 in binary, there are + * two bits set to 1. + */ +static inline unsigned int count_bits_set(unsigned int w) +{ + /* + * This is faster, and runs in parallel + */ + const int S[] = {1, 2, 4, 8, 16}; + const int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF}; + int c = w; + c = ((c >> S[0]) & B[0]) + (c & B[0]); + c = ((c >> S[1]) & B[1]) + (c & B[1]); + c = ((c >> S[2]) & B[2]) + (c & B[2]); + c = ((c >> S[3]) & B[3]) + (c & B[3]); + c = ((c >> S[4]) & B[4]) + (c & B[4]); + return c; +} + // ===================================================== // class PixmapIo // ===================================================== @@ -187,6 +232,8 @@ public: void init(int w, int h, int components); ~Pixmap2D(); + void Scale(int format, int newW, int newH); + //load & save static Pixmap2D* loadPath(const string& path); void load(const string &path); diff --git a/source/shared_lib/sources/graphics/gl/texture_gl.cpp b/source/shared_lib/sources/graphics/gl/texture_gl.cpp index cf1b474b..d872ecc5 100644 --- a/source/shared_lib/sources/graphics/gl/texture_gl.cpp +++ b/source/shared_lib/sources/graphics/gl/texture_gl.cpp @@ -52,6 +52,8 @@ namespace Shared { namespace Graphics { namespace Gl { using namespace Platform; using namespace Shared::Util; +bool TextureGl::enableATIHacks = false; + static void setupGLExtensionMethods() { #ifdef WIN32 @@ -831,6 +833,16 @@ void Texture2DGl::init(Filter filter, int maxAnisotropy) { glFormat, GL_UNSIGNED_BYTE, pixels); */ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + + //! Note: NPOTs + nearest filtering seems broken on ATIs + if ( !(count_bits_set(pixmap.getW()) == 1 && count_bits_set(pixmap.getH()) == 1) && + TextureGl::enableATIHacks == true) { + // && (!GLEW_ARB_texture_non_power_of_two || (globalRendering->atiHacks && nearest)) ) { + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\n\n**WARNING** Enabling ATI video card hacks, resizing texture to power of two [%d x %d] to [%d x %d] components [%d] path [%s]\n",pixmap.getW(),pixmap.getH(),next_power_of_2(pixmap.getW()),next_power_of_2(pixmap.getH()),pixmap.getComponents(),pixmap.getPath().c_str()); + + pixmap.Scale(glFormat,next_power_of_2(pixmap.getW()),next_power_of_2(pixmap.getH())); + } + glTexImage2D(GL_TEXTURE_2D, 0, glCompressionFormat, pixmap.getW(), pixmap.getH(), 0, glFormat, GL_UNSIGNED_BYTE, pixels); @@ -883,6 +895,14 @@ void Texture2DGl::init(Filter filter, int maxAnisotropy) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if ( !(count_bits_set(pixmap.getW()) == 1 && count_bits_set(pixmap.getH()) == 1) && + TextureGl::enableATIHacks == true) { + // && (!GLEW_ARB_texture_non_power_of_two || (globalRendering->atiHacks && nearest)) ) { + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\n\n**WARNING** Enabling ATI video card hacks, resizing texture to power of two [%d x %d] to [%d x %d] components [%d] path [%s]\n",pixmap.getW(),pixmap.getH(),next_power_of_2(pixmap.getW()),next_power_of_2(pixmap.getH()),pixmap.getComponents(),pixmap.getPath().c_str()); + + pixmap.Scale(glFormat,next_power_of_2(pixmap.getW()),next_power_of_2(pixmap.getH())); + } + glTexImage2D(GL_TEXTURE_2D, 0, glCompressionFormat,pixmap.getW(), pixmap.getH(),0, glFormat, GL_UNSIGNED_BYTE, pixels); @@ -1072,7 +1092,7 @@ void TextureCubeGl::init(Filter filter, int maxAnisotropy) { for(int i = 0; i < 6; ++i) { //params - const Pixmap2D *currentPixmap= pixmap.getFace(i); + Pixmap2D *currentPixmap= pixmap.getFace(i); GLint glFormat= toFormatGl(format, currentPixmap->getComponents()); GLint glInternalFormat= toInternalFormatGl(format, currentPixmap->getComponents()); @@ -1098,6 +1118,14 @@ void TextureCubeGl::init(Filter filter, int maxAnisotropy) { */ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + if ( !(count_bits_set(currentPixmap->getW()) == 1 && count_bits_set(currentPixmap->getH()) == 1) && + TextureGl::enableATIHacks == true) { + // && (!GLEW_ARB_texture_non_power_of_two || (globalRendering->atiHacks && nearest)) ) { + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\n\n**WARNING** Enabling ATI video card hacks, resizing texture to power of two [%d x %d] to [%d x %d] components [%d] path [%s]\n",currentPixmap->getW(),currentPixmap->getH(),next_power_of_2(currentPixmap->getW()),next_power_of_2(currentPixmap->getH()),currentPixmap->getComponents(),currentPixmap->getPath().c_str()); + + currentPixmap->Scale(glFormat,next_power_of_2(currentPixmap->getW()),next_power_of_2(currentPixmap->getH())); + } + glTexImage2D(target, 0, glCompressionFormat, currentPixmap->getW(), currentPixmap->getH(), 0, glFormat, GL_UNSIGNED_BYTE, pixels); @@ -1150,6 +1178,15 @@ void TextureCubeGl::init(Filter filter, int maxAnisotropy) { } } else { + + if ( !(count_bits_set(currentPixmap->getW()) == 1 && count_bits_set(currentPixmap->getH()) == 1) && + TextureGl::enableATIHacks == true) { + // && (!GLEW_ARB_texture_non_power_of_two || (globalRendering->atiHacks && nearest)) ) { + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\n\n**WARNING** Enabling ATI video card hacks, resizing texture to power of two [%d x %d] to [%d x %d] components [%d] path [%s]\n",currentPixmap->getW(),currentPixmap->getH(),next_power_of_2(currentPixmap->getW()),next_power_of_2(currentPixmap->getH()),currentPixmap->getComponents(),currentPixmap->getPath().c_str()); + + currentPixmap->Scale(glFormat,next_power_of_2(currentPixmap->getW()),next_power_of_2(currentPixmap->getH())); + } + glTexImage2D( target, 0, glCompressionFormat, currentPixmap->getW(), currentPixmap->getH(), diff --git a/source/shared_lib/sources/graphics/pixmap.cpp b/source/shared_lib/sources/graphics/pixmap.cpp index 62bbe828..6b360ae7 100644 --- a/source/shared_lib/sources/graphics/pixmap.cpp +++ b/source/shared_lib/sources/graphics/pixmap.cpp @@ -25,11 +25,12 @@ #include #include #include - +#include "opengl.h" #include "leak_dumper.h" using namespace Shared::Util; using namespace std; +using namespace Shared::Graphics::Gl; namespace Shared{ namespace Graphics{ @@ -868,6 +869,24 @@ Pixmap2D::~Pixmap2D() { deletePixels(); } +void Pixmap2D::Scale(int format, int newW, int newH) { + int useComponents = this->getComponents(); + uint8 *newpixels= new uint8[newW * newH * useComponents]; + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + int error = gluScaleImage( format, + w, h, GL_UNSIGNED_BYTE, pixels, + newW, newH, GL_UNSIGNED_BYTE, newpixels); + if(error != GL_NO_ERROR) { + init(newW,newH,this->components); + pixels = newpixels; + } + else { + assertGl(); + } + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +} + Pixmap2D* Pixmap2D::loadPath(const string& path) { //printf("Loading Pixmap2D [%s]\n",path.c_str()); diff --git a/source/shared_lib/sources/platform/sdl/window.cpp b/source/shared_lib/sources/platform/sdl/window.cpp index 882e266c..4857b4b4 100644 --- a/source/shared_lib/sources/platform/sdl/window.cpp +++ b/source/shared_lib/sources/platform/sdl/window.cpp @@ -381,6 +381,7 @@ void Window::setupGraphicsScreen(int depthBits, int stencilBits, bool hardware_a // setup LOD bias factor //const float lodBias = std::max(std::min( configHandler->Get("TextureLODBias", 0.0f) , 4.0f), -4.0f); const float lodBias = max(min(0.0f,4.0f),-4.0f); + //if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("\n\n\n\n\n$$$$ In [%s::%s Line: %d] lodBias = %f\n\n",__FILE__,__FUNCTION__,__LINE__,lodBias); #ifdef USE_STREFLOP if (streflop::fabs(lodBias) > 0.01f) { #else