MegaGlest/source/shared_lib/sources/graphics/gl/texture_gl.cpp

1295 lines
43 KiB
C++

// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "texture_gl.h"
#include <stdexcept>
#include "opengl.h"
#include <iostream>
#include <vector>
#include "conversion.h"
#include <algorithm>
#include "util.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared { namespace Graphics { namespace Gl {
using namespace Platform;
using namespace Shared::Util;
bool TextureGl::enableATIHacks = false;
static void setupGLExtensionMethods() {
#ifdef WIN32
static bool setupExtensions=true;
if(setupExtensions == true) {
setupExtensions = false;
if(isGlExtensionSupported("GL_EXT_framebuffer_object")) {
//glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)wglGetProcAddress("glIsRenderbufferEXT");
glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
//glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)wglGetProcAddress("glGetRenderbufferParameterivEXT");
//glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)wglGetProcAddress("glIsFramebufferEXT");
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
//glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)wglGetProcAddress("glFramebufferTexture1DEXT");
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
//glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)wglGetProcAddress("glFramebufferTexture3DEXT");
glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
//glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)wglGetProcAddress("glGetFramebufferAttachmentParameterivEXT");
//glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)wglGetProcAddress("glGenerateMipmapEXT");
if(!glBindRenderbufferEXT || !glDeleteRenderbuffersEXT || !glGenRenderbuffersEXT ||
!glRenderbufferStorageEXT || !glBindFramebufferEXT || !glDeleteFramebuffersEXT ||
!glGenFramebuffersEXT || !glCheckFramebufferStatusEXT || !glFramebufferTexture2DEXT ||
!glFramebufferRenderbufferEXT) {
glGenFramebuffersEXT = NULL;
}
}
}
#endif
}
/* gets next power of two */
int pot(int x) {
int val = 1;
while (val < x) {
val *= 2;
}
return val;
}
const std::size_t MIN_BYTES_TO_COMPRESS = 12;
static std::string getSupportCompressedTextureFormatString(int format) {
std::string result = intToStr(format) + "[" + intToHex(format) + "]";
switch(format) {
case GL_COMPRESSED_ALPHA:
result = "GL_COMPRESSED_ALPHA";
break;
case GL_COMPRESSED_LUMINANCE:
result = "GL_COMPRESSED_LUMINANCE";
break;
case GL_COMPRESSED_LUMINANCE_ALPHA:
result = "GL_COMPRESSED_LUMINANCE_ALPHA";
break;
case GL_COMPRESSED_INTENSITY:
result = "GL_COMPRESSED_INTENSITY";
break;
case GL_COMPRESSED_RGB:
result = "GL_COMPRESSED_RGB";
break;
case GL_COMPRESSED_RGBA:
result = "GL_COMPRESSED_RGBA";
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
result = "GL_COMPRESSED_RGB_S3TC_DXT1_EXT";
break;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
result = "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT";
break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
result = "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT";
break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
result = "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT";
break;
/*
case GL_COMPRESSED_SRGB:
result = "GL_COMPRESSED_SRGB";
break;
case GL_COMPRESSED_SRGB_ALPHA:
result = "GL_COMPRESSED_SRGB_ALPHA";
break;
case GL_COMPRESSED_SLUMINANCE:
result = "GL_COMPRESSED_SLUMINANCE";
break;
case GL_COMPRESSED_SLUMINANCE_ALPHA:
result = "GL_COMPRESSED_SLUMINANCE_ALPHA";
break;
case GL_COMPRESSED_RED:
result = "GL_COMPRESSED_RED";
break;
case GL_COMPRESSED_RG:
result = "GL_COMPRESSED_RG";
break;
case GL_COMPRESSED_RED_RGTC1:
result = "GL_COMPRESSED_RED_RGTC1";
break;
case GL_COMPRESSED_SIGNED_RED_RGTC1:
result = "GL_COMPRESSED_SIGNED_RED_RGTC1";
break;
case GL_COMPRESSED_RG_RGTC2:
result = "GL_COMPRESSED_RG_RGTC2";
break;
case GL_COMPRESSED_SIGNED_RG_RGTC2:
result = "GL_COMPRESSED_SIGNED_RG_RGTC2";
break;
case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
result = "GL_COMPRESSED_RGBA_BPTC_UNORM_ARB";
break;
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
result = "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB";
break;
case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
result = "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB";
break;
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
result = "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB";
break;
*/
case GL_COMPRESSED_RGB_FXT1_3DFX:
result = "GL_COMPRESSED_RGB_FXT1_3DFX";
break;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
result = "GL_COMPRESSED_RGBA_FXT1_3DFX";
break;
/*
case GL_COMPRESSED_SRGB_EXT:
result = "GL_COMPRESSED_SRGB_EXT";
break;
case GL_COMPRESSED_SRGB_ALPHA_EXT:
result = "GL_COMPRESSED_SRGB_ALPHA_EXT";
break;
case GL_COMPRESSED_SLUMINANCE_EXT:
result = "GL_COMPRESSED_SLUMINANCE_EXT";
break;
case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
result = "GL_COMPRESSED_SLUMINANCE_ALPHA_EXT";
break;
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
result = "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT";
break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
result = "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT";
break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
result = "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT";
break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
result = "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT";
break;
case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
result = "GL_COMPRESSED_LUMINANCE_LATC1_EXT";
break;
case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
result = "GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT";
break;
case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
result = "GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT";
break;
case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
result = "GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT";
break;
case GL_COMPRESSED_RED_RGTC1_EXT:
result = "GL_COMPRESSED_RED_RGTC1_EXT";
break;
case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
result = "GL_COMPRESSED_SIGNED_RED_RGTC1_EXT";
break;
case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
result = "GL_COMPRESSED_RED_GREEN_RGTC2_EXT";
break;
case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
result = "GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT";
break;
*/
/*
#define GL_COMPRESSED_SRGB 0x8C48
#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
#define GL_COMPRESSED_SLUMINANCE 0x8C4A
#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
#define GL_COMPRESSED_RED 0x8225
#define GL_COMPRESSED_RG 0x8226
#define GL_COMPRESSED_RED_RGTC1 0x8DBB
#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
#define GL_COMPRESSED_RG_RGTC2 0x8DBD
#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
#define GL_COMPRESSED_SRGB_EXT 0x8C48
#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
*/
}
return result;
}
static int getNumCompressedTextureFormats() {
int numCompressedTextureFormats = 0;
glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, (GLint*)&numCompressedTextureFormats);
return numCompressedTextureFormats;
}
static std::vector<int> getSupportCompressedTextureFormats() {
std::vector<int> result;
int count = getNumCompressedTextureFormats();
if(count > 0) {
int *formats = new int[count];
glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS,(GLint*)&formats[0]);
for(int i = 0; i < count; ++i) {
result.push_back(formats[i]);
}
delete [] formats;
}
if(Texture::useTextureCompression == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"------------------------------------------------\n");
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"**** getSupportCompressedTextureFormats() result.size() = %d, count = %d\n",(int)result.size(),count);
for(unsigned int i = 0; i < result.size(); ++i) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"Texture Compression #i = %d, result[i] = %d [%s]\n",i,result[i],getSupportCompressedTextureFormatString(result[i]).c_str());
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"------------------------------------------------\n");
}
return result;
}
GLint toCompressionFormatGl(GLint format) {
if(Texture::useTextureCompression == false) {
return format;
}
static std::vector<int> supportedCompressionFormats = getSupportCompressedTextureFormats();
if(supportedCompressionFormats.empty() == true) {
return format;
}
//GL_COMPRESSED_ALPHA <- white things but tile ok!
//GL_COMPRESSED_LUMINANCE <- black tiles
//GL_COMPRESSED_LUMINANCE_ALPHA <- black tiles
//GL_COMPRESSED_INTENSITY <- black tiles
//GL_COMPRESSED_RGB <- black tiles
//GL_COMPRESSED_RGBA <- black tiles
// With the following extension (GL_EXT_texture_compression_s3tc)
//GL_COMPRESSED_RGB_S3TC_DXT1_EXT
//GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
//GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
//GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
//#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
//#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
switch(format) {
case GL_LUMINANCE:
case GL_LUMINANCE8:
return GL_COMPRESSED_LUMINANCE;
case GL_RGB:
case GL_RGB8:
if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_RGB_S3TC_DXT1_EXT) != supportedCompressionFormats.end()) {
return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
}
else if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_RGB) != supportedCompressionFormats.end()) {
return GL_COMPRESSED_RGB;
}
//else if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_SRGB_S3TC_DXT1_EXT) != supportedCompressionFormats.end()) {
// return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
//}
else if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_RGB_FXT1_3DFX) != supportedCompressionFormats.end()) {
return GL_COMPRESSED_RGB_FXT1_3DFX;
}
break;
case GL_RGBA:
case GL_RGBA8:
if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) != supportedCompressionFormats.end()) {
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
else if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_RGBA) != supportedCompressionFormats.end()) {
return GL_COMPRESSED_RGBA;
}
//else if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) != supportedCompressionFormats.end()) {
// return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
//}
//else if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_SRGB_S3TC_DXT1_EXT) != supportedCompressionFormats.end()) {
// return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
//}
else if(std::find(supportedCompressionFormats.begin(),supportedCompressionFormats.end(),GL_COMPRESSED_RGBA_FXT1_3DFX) != supportedCompressionFormats.end()) {
return GL_COMPRESSED_RGBA_FXT1_3DFX;
}
break;
case GL_ALPHA:
case GL_ALPHA8:
//return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
//return GL_COMPRESSED_ALPHA_ARB;
return GL_COMPRESSED_ALPHA;
//return GL_COMPRESSED_RGBA;
default:
return format;
}
return format;
}
GLint toWrapModeGl(Texture::WrapMode wrapMode){
switch(wrapMode){
case Texture::wmClamp:
return GL_CLAMP;
case Texture::wmRepeat:
return GL_REPEAT;
case Texture::wmClampToEdge:
return GL_CLAMP_TO_EDGE;
default:
assert(false);
return GL_CLAMP;
}
}
GLint toFormatGl(Texture::Format format, int components){
switch(format){
case Texture::fAuto:
switch(components){
case 1:
return GL_LUMINANCE;
case 3:
return GL_RGB;
case 4:
return GL_RGBA;
default:
std::cerr << "Components = " << (components) << std::endl;
assert(false);
return GL_RGBA;
}
break;
case Texture::fLuminance:
return GL_LUMINANCE;
case Texture::fAlpha:
return GL_ALPHA;
case Texture::fRgb:
return GL_RGB;
case Texture::fRgba:
return GL_RGBA;
default:
assert(false);
return GL_RGB;
}
}
GLint toInternalFormatGl(Texture::Format format, int components){
switch(format){
case Texture::fAuto:
switch(components){
case 1:
return GL_LUMINANCE8;
case 3:
return GL_RGB8;
case 4:
return GL_RGBA8;
default:
assert(false);
return GL_RGBA8;
}
break;
case Texture::fLuminance:
return GL_LUMINANCE8;
case Texture::fAlpha:
return GL_ALPHA8;
case Texture::fRgb:
return GL_RGB8;
case Texture::fRgba:
return GL_RGBA8;
default:
assert(false);
return GL_RGB8;
}
}
TextureGl::TextureGl() {
handle = 0;
renderBufferId = 0;
frameBufferId = 0;
setupGLExtensionMethods();
}
bool TextureGl::supports_FBO_RBO() {
return (glGenFramebuffersEXT != NULL);
}
void TextureGl::setup_FBO_RBO() {
if(getTextureWidth() < 0 || getTextureHeight() < 0) {
throw megaglest_runtime_error("getTextureWidth() < 0 || getTextureHeight() < 0");
}
// Need some work to get extensions properly working in Windows (use Glew lib)
// Did we successfully setup FBO's?
if(glGenFramebuffersEXT) {
GLint width=0;
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width);
GLint height=0;
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height);
//-------------------------
glGenFramebuffersEXT(1, &frameBufferId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferId);
//Attach 2D texture to this FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, handle, 0);
//-------------------------
glGenRenderbuffersEXT(1, &renderBufferId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBufferId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, getTextureWidth(), getTextureHeight());
//-------------------------
//Attach depth buffer to FBO
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferId);
//-------------------------
//Does the GPU support current FBO configuration?
GLenum status;
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status)
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"FBO attachment OK!\n");
break;
default:
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"FBO attachment BAD!\n");
break;
}
//-------------------------
//and now you can render to GL_TEXTURE_2D
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferId);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
}
void TextureGl::teardown_FBO_RBO() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
//----------------
//Bind 0, which means render to back buffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
//And in the end, cleanup
//Delete resources
//glDeleteTextures(1, &handle);
glDeleteRenderbuffersEXT(1, &frameBufferId);
//Bind 0, which means render to back buffer, as a result, fb is unbound
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(1, &frameBufferId);
}
}
void TextureGl::initRenderBuffer() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
// create a renderbuffer object to store depth info
glGenRenderbuffersEXT(1, &renderBufferId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBufferId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,getTextureWidth(), getTextureHeight());
//glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
}
void TextureGl::initFrameBuffer() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
// create a framebuffer object
glGenFramebuffersEXT(1, &frameBufferId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferId);
}
}
void TextureGl::attachRenderBuffer() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
// attach the renderbuffer to depth attachment point
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT, renderBufferId);
}
}
void TextureGl::attachFrameBufferToTexture() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, handle, 0);
}
}
bool TextureGl::checkFrameBufferStatus() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
// check FBO status
// Does the GPU support current FBO configuration?
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"checkFrameBufferStatus() status = %d [%X]\n",status,status);
return false;
}
return true;
}
return false;
}
void TextureGl::dettachFrameBufferFromTexture() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
// switch back to window-system-provided framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
}
void TextureGl::dettachRenderBufferFromTexture() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
}
TextureGl::~TextureGl() {
// Need some work to get extensions properly working in Windows (use Glew lib)
if(glGenFramebuffersEXT) {
if(renderBufferId != 0) {
glDeleteRenderbuffersEXT(1, &renderBufferId);
renderBufferId = 0;
}
if(frameBufferId != 0) {
glDeleteFramebuffersEXT(1, &frameBufferId);
frameBufferId = 0;
}
//glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
}
// =====================================================
// class Texture1DGl
// =====================================================
Texture1DGl::Texture1DGl() : Texture1D(), TextureGl() {}
Texture1DGl::~Texture1DGl() {
end();
}
void Texture1DGl::init(Filter filter, int maxAnisotropy) {
assertGl();
if(inited == false) {
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
GLint glCompressionFormat = toCompressionFormatGl(glInternalFormat);
if(forceCompressionDisabled == true || (pixmap.getPixelByteCount() > 0 && pixmap.getPixelByteCount() <= MIN_BYTES_TO_COMPRESS)) {
glCompressionFormat = glInternalFormat;
}
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_1D, handle);
//wrap params
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, wrap);
//maxAnisotropy
if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
}
if(mipmap) {
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
//build mipmaps
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int error= gluBuild1DMipmaps(
GL_TEXTURE_1D, glCompressionFormat, pixmap.getW(),
glFormat, GL_UNSIGNED_BYTE, pixels);
// Now try without compression if we tried compression
if(error != 0 && glCompressionFormat != glInternalFormat) {
int error2= gluBuild1DMipmaps(
GL_TEXTURE_1D, glInternalFormat, pixmap.getW(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error2 == 0) {
error = 0;
}
}
//
if(error != 0) {
//throw megaglest_runtime_error("Error building texture 1D mipmaps");
const char *errorString= reinterpret_cast<const char*>(gluErrorString(error));
char szBuf[8096]="";
snprintf(szBuf,8096,"Error building texture 1D mipmaps, returned: %d [%s] for [%s] w = %d, glCompressionFormat = %d",error,errorString,pixmap.getPath().c_str(),pixmap.getW(),glCompressionFormat);
throw megaglest_runtime_error(szBuf);
}
}
else {
//build single texture
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage1D(
GL_TEXTURE_1D, 0, glCompressionFormat, pixmap.getW(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error= glGetError();
// Now try without compression if we tried compression
if(error != GL_NO_ERROR && glCompressionFormat != glInternalFormat) {
glTexImage1D(
GL_TEXTURE_1D, 0, glInternalFormat, pixmap.getW(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error2= glGetError();
if(error2 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
//
if(error != GL_NO_ERROR) {
//throw megaglest_runtime_error("Error creating texture 1D");
const char *errorString= reinterpret_cast<const char*>(gluErrorString(error));
char szBuf[8096]="";
snprintf(szBuf,8096,"Error creating texture 1D, returned: %d [%s] (%X) [%s] w = %d, glCompressionFormat = %d",error,errorString,error,pixmap.getPath().c_str(),pixmap.getW(),glCompressionFormat);
throw megaglest_runtime_error(szBuf);
}
}
inited= true;
OutputTextureDebugInfo(format, pixmap.getComponents(),getPath(),pixmap.getPixelByteCount(),GL_TEXTURE_1D);
}
assertGl();
}
void Texture1DGl::end(bool deletePixelBuffer) {
if(inited == true) {
assertGl();
glDeleteTextures(1, &handle);
assertGl();
handle=0;
inited=false;
if(deletePixelBuffer == true) {
deletePixels();
}
}
}
// =====================================================
// class Texture2DGl
// =====================================================
Texture2DGl::Texture2DGl() : Texture2D(), TextureGl() {}
Texture2DGl::~Texture2DGl() {
end();
}
void Texture2DGl::init(Filter filter, int maxAnisotropy) {
assertGl();
if(inited == false) {
assertGl();
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
GLint glCompressionFormat = toCompressionFormatGl(glInternalFormat);
if(forceCompressionDisabled == true || (pixmap.getPixelByteCount() > 0 && pixmap.getPixelByteCount() <= MIN_BYTES_TO_COMPRESS)) {
glCompressionFormat = glInternalFormat;
}
assertGl();
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_2D, handle);
assertGl();
//wrap params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
assertGl();
//maxAnisotropy
if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
}
if(mipmap) {
GLuint glFilter= (filter == fTrilinear ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR_MIPMAP_NEAREST);
//build mipmaps
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/*
* Replaced this call due to: http://www.opengl.org/wiki/Common_Mistakes#gluBuild2DMipmaps
*
int error= gluBuild2DMipmaps(
GL_TEXTURE_2D, glCompressionFormat,
pixmap.getW(), pixmap.getH(),
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);
GLint error= glGetError();
// Now try without compression if we tried compression
if(error != GL_NO_ERROR && glCompressionFormat != glInternalFormat) {
glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat,
pixmap.getW(), pixmap.getH(), 0,
glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error2= glGetError();
if(error2 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
if(error != GL_NO_ERROR) {
int error3= gluBuild2DMipmaps(
GL_TEXTURE_2D, glCompressionFormat,
pixmap.getW(), pixmap.getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error3 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
if(error != GL_NO_ERROR) {
int error4= gluBuild2DMipmaps(
GL_TEXTURE_2D, glInternalFormat,
pixmap.getW(), pixmap.getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error4 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
//
if(error != GL_NO_ERROR) {
//throw megaglest_runtime_error("Error building texture 2D mipmaps");
const char *errorString= reinterpret_cast<const char*>(gluErrorString(error));
char szBuf[8096]="";
snprintf(szBuf,8096,"Error building texture 2D mipmaps [%s], returned: %d [%s] for [%s] w = %d, h = %d, glCompressionFormat = %d",this->path.c_str(),error,errorString,(pixmap.getPath() != "" ? pixmap.getPath().c_str() : this->path.c_str()),pixmap.getW(),pixmap.getH(),glCompressionFormat);
throw megaglest_runtime_error(szBuf);
}
}
else {
//build single texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
assertGl();
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);
GLint error= glGetError();
// Now try without compression if we tried compression
if(error != GL_NO_ERROR && glCompressionFormat != glInternalFormat) {
glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat,pixmap.getW(),
pixmap.getH(),0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error2= glGetError();
if(error2 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
else {
glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, pot(pixmap.getW()),
pot(pixmap.getH()), 0, glFormat, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixmap.getW(), pixmap.getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error3= glGetError();
if(error3 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
}
else if(error != GL_NO_ERROR) {
glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, pot(pixmap.getW()),
pot(pixmap.getH()), 0, glFormat, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixmap.getW(), pixmap.getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error3= glGetError();
if(error3 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
//
//throw megaglest_runtime_error("TEST!");
if(error != GL_NO_ERROR) {
const char *errorString= reinterpret_cast<const char*>(gluErrorString(error));
char szBuf[8096]="";
snprintf(szBuf,8096,"Error creating texture 2D path [%s], returned: %d [%s] (%X) [%s] w = %d, h = %d, glInternalFormat = %d, glFormat = %d, glCompressionFormat = %d",this->path.c_str(),error,errorString,error,pixmap.getPath().c_str(),pixmap.getW(),pixmap.getH(),glInternalFormat,glFormat,glCompressionFormat);
throw megaglest_runtime_error(szBuf);
}
}
inited= true;
OutputTextureDebugInfo(format, pixmap.getComponents(),getPath(),pixmap.getPixelByteCount(),GL_TEXTURE_2D);
}
assertGl();
}
void Texture2DGl::end(bool deletePixelBuffer) {
if(inited == true) {
//printf("==> Deleting GL Texture [%s] handle = %d\n",getPath().c_str(),handle);
assertGl();
glDeleteTextures(1, &handle);
assertGl();
handle=0;
inited=false;
if(deletePixelBuffer == true) {
deletePixels();
}
}
}
// =====================================================
// class Texture3DGl
// =====================================================
Texture3DGl::Texture3DGl() : Texture3D(), TextureGl() {}
Texture3DGl::~Texture3DGl() {
end();
}
void Texture3DGl::init(Filter filter, int maxAnisotropy) {
assertGl();
if(inited == false) {
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
GLint glCompressionFormat = toCompressionFormatGl(glInternalFormat);
if(forceCompressionDisabled == true || (pixmap.getPixelByteCount() > 0 && pixmap.getPixelByteCount() <= MIN_BYTES_TO_COMPRESS)) {
glCompressionFormat = glInternalFormat;
}
if(glCompressionFormat == GL_COMPRESSED_RGBA_FXT1_3DFX) {
glCompressionFormat = glInternalFormat;
}
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_3D, handle);
//wrap params
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrap);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrap);
//build single texture
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage3D(
GL_TEXTURE_3D, 0, glCompressionFormat,
pixmap.getW(), pixmap.getH(), pixmap.getD(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error= glGetError();
// Now try without compression if we tried compression
if(error != GL_NO_ERROR && glCompressionFormat != glInternalFormat) {
glTexImage3D(
GL_TEXTURE_3D, 0, glInternalFormat,
pixmap.getW(), pixmap.getH(), pixmap.getD(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error2= glGetError();
if(error2 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
else if(error != GL_NO_ERROR) {
glTexImage3D(
GL_TEXTURE_3D, 0, glInternalFormat,
pot(pixmap.getW()), pot(pixmap.getH()), pot(pixmap.getD()),
0, glFormat, GL_UNSIGNED_BYTE, NULL);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
pixmap.getW(), pixmap.getH(), pixmap.getD(),
glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error3= glGetError();
if(error3 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
//
if(error != GL_NO_ERROR) {
//throw megaglest_runtime_error("Error creating texture 3D");
const char *errorString= reinterpret_cast<const char*>(gluErrorString(error));
char szBuf[8096]="";
snprintf(szBuf,8096,"Error creating texture 3D, returned: %d [%s] (%X) [%s] w = %d, h = %d, d = %d, glCompressionFormat = %d",error,errorString,error,pixmap.getPath().c_str(),pixmap.getW(),pixmap.getH(),pixmap.getD(),glCompressionFormat);
throw megaglest_runtime_error(szBuf);
}
inited= true;
OutputTextureDebugInfo(format, pixmap.getComponents(),getPath(),pixmap.getPixelByteCount(),GL_TEXTURE_3D);
}
assertGl();
}
void Texture3DGl::end(bool deletePixelBuffer) {
if(inited == true) {
assertGl();
glDeleteTextures(1, &handle);
assertGl();
handle=0;
inited=false;
if(deletePixelBuffer == true) {
deletePixels();
}
}
}
// =====================================================
// class TextureCubeGl
// =====================================================
TextureCubeGl::TextureCubeGl() : TextureCube(), TextureGl() {}
TextureCubeGl::~TextureCubeGl() {
end();
}
void TextureCubeGl::init(Filter filter, int maxAnisotropy) {
assertGl();
if(inited == false) {
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_CUBE_MAP, handle);
//wrap
GLint wrap= toWrapModeGl(wrapMode);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrap);
//filter
if(mipmap) {
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
for(int i = 0; i < 6; ++i) {
//params
Pixmap2D *currentPixmap= pixmap.getFace(i);
GLint glFormat= toFormatGl(format, currentPixmap->getComponents());
GLint glInternalFormat= toInternalFormatGl(format, currentPixmap->getComponents());
GLint glCompressionFormat = toCompressionFormatGl(glInternalFormat);
if(forceCompressionDisabled == true || (currentPixmap->getPixelByteCount() > 0 && currentPixmap->getPixelByteCount() <= MIN_BYTES_TO_COMPRESS)) {
glCompressionFormat = glInternalFormat;
}
//pixel init var
const uint8* pixels= pixmapInit? currentPixmap->getPixels(): NULL;
GLenum target= GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
if(mipmap) {
/*
* Replaced this call due to: http://www.opengl.org/wiki/Common_Mistakes#gluBuild2DMipmaps
*
int error= gluBuild2DMipmaps(
target, glCompressionFormat,
currentPixmap->getW(), currentPixmap->getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
*/
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);
int error = glGetError();
// Now try without compression if we tried compression
if(error != GL_NO_ERROR && glCompressionFormat != glInternalFormat) {
glTexImage2D(target, 0, glInternalFormat,
currentPixmap->getW(), currentPixmap->getH(), 0,
glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error2= glGetError();
if(error2 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
if(error != GL_NO_ERROR) {
int error3= gluBuild2DMipmaps(
target, glCompressionFormat,
currentPixmap->getW(), currentPixmap->getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error3 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
if(error != GL_NO_ERROR) {
int error4= gluBuild2DMipmaps(
target, glInternalFormat,
currentPixmap->getW(), currentPixmap->getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error4 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
//
if(error != GL_NO_ERROR) {
//throw megaglest_runtime_error("Error building texture cube mipmaps");
const char *errorString= reinterpret_cast<const char*>(gluErrorString(error));
char szBuf[8096]="";
snprintf(szBuf,8096,"Error building texture cube mipmaps, returned: %d [%s] for [%s] w = %d, h = %d, glCompressionFormat = %d",error,errorString,currentPixmap->getPath().c_str(),currentPixmap->getW(),currentPixmap->getH(),glCompressionFormat);
throw megaglest_runtime_error(szBuf);
}
}
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(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
int error = glGetError();
// Now try without compression if we tried compression
if(error != GL_NO_ERROR && glCompressionFormat != glInternalFormat) {
glTexImage2D(
target, 0, glInternalFormat,
currentPixmap->getW(), currentPixmap->getH(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error2= glGetError();
if(error2 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
else {
glTexImage2D(target, 0, glInternalFormat, pot(currentPixmap->getW()),
pot(currentPixmap->getH()), 0, glFormat, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D(target, 0, 0, 0, currentPixmap->getW(), currentPixmap->getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error3= glGetError();
if(error3 == GL_NO_ERROR) {
error = GL_NO_ERROR;
}
}
}
//
if(error != GL_NO_ERROR) {
//throw megaglest_runtime_error("Error creating texture cube");
const char *errorString= reinterpret_cast<const char*>(gluErrorString(error));
char szBuf[8096]="";
snprintf(szBuf,8096,"Error creating texture cube, returned: %d [%s] (%X) [%s] w = %d, h = %d, glCompressionFormat = %d",error,errorString,error,currentPixmap->getPath().c_str(),currentPixmap->getW(),currentPixmap->getH(),glCompressionFormat);
throw megaglest_runtime_error(szBuf);
}
}
OutputTextureDebugInfo(format, currentPixmap->getComponents(),getPath(),currentPixmap->getPixelByteCount(),target);
}
inited= true;
}
assertGl();
}
void TextureCubeGl::end(bool deletePixelBuffer) {
if(inited == true) {
assertGl();
glDeleteTextures(1, &handle);
assertGl();
handle=0;
inited=false;
if(deletePixelBuffer == true) {
deletePixels();
}
}
}
void TextureGl::OutputTextureDebugInfo(Texture::Format format, int components,const string path,std::size_t rawSize,GLenum texType) {
if(Texture::useTextureCompression == true) {
GLint glFormat= toFormatGl(format, components);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"**** Texture filename: [%s] format = %d components = %d, glFormat = %d, rawSize = %llu\n",path.c_str(),format,components,glFormat,(long long unsigned int)rawSize);
GLint compressed=0;
glGetTexLevelParameteriv(texType, 0, GL_TEXTURE_COMPRESSED, &compressed);
int error = glGetError();
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"**** Texture compressed status: %d, error [%d] (%X)\n",compressed,error,error);
bool isCompressed = (compressed == 1);
compressed=0;
glGetTexLevelParameteriv(texType, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed);
error = glGetError();
double percent = 0;
if(isCompressed == true) {
percent = ((double)compressed / (double)rawSize) * (double)100.0;
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"**** Texture image size in video RAM: %d [%.2f%%], error [%d] (%X)\n",compressed,percent,error,error);
compressed=0;
glGetTexLevelParameteriv(texType, 0, GL_TEXTURE_INTERNAL_FORMAT, &compressed);
error = glGetError();
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"**** Texture image compression format used: %d, error [%d] (%X)\n",compressed,error,error);
}
}
}}}//end namespace