00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00027 
#include "GlTextures.hpp"
00028 
#include <sstream>
00029 
#include "GlTextureName.hpp"
00030 
#include "GlTextureStorage.hpp"
00031 
00032 
namespace shgl {
00033 
00034 
using namespace SH;
00035 
00036 
const unsigned int shGlTargets[] = {
00037   GL_TEXTURE_1D,
00038   GL_TEXTURE_2D,
00039   GL_TEXTURE_RECTANGLE_NV,
00040   GL_TEXTURE_3D,
00041   GL_TEXTURE_CUBE_MAP,
00042 };
00043 
00044 
const unsigned int shGlCubeMapTargets[] = {
00045   GL_TEXTURE_CUBE_MAP_POSITIVE_X,
00046   GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
00047   GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
00048   GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
00049   GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
00050   GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
00051 };
00052 
00053 
ShCubeDirection glToShCubeDir(GLuint target)
00054 {
00055   
switch (target) {
00056   
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
00057     
return SH_CUBE_POS_X;
00058   
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
00059     
return SH_CUBE_NEG_X;
00060   
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
00061     
return SH_CUBE_POS_Y;
00062   
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
00063     
return SH_CUBE_NEG_Y;
00064   
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
00065     
return SH_CUBE_POS_Z;
00066   
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
00067     
return SH_CUBE_NEG_Z;
00068   }
00069   
return SH_CUBE_POS_X;
00070 }
00071 
00072 GLenum shGlInternalFormat(
const ShTextureNodePtr& node)
00073 {
00074   
if (node->size() < 0 || node->size() > 4) 
return 0;
00075   
if (node->traits().clamping() == SH::ShTextureTraits::SH_CLAMPED) {
00076     
return node->size();
00077   } 
else if (node->traits().clamping() == SH::ShTextureTraits::SH_UNCLAMPED) {
00078 
00079     std::string exts(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
00080     GLenum fpformats_nv[4] = {GL_FLOAT_R_NV, GL_FLOAT_RGBA_NV, GL_FLOAT_RGB_NV, GL_FLOAT_RGBA_NV};
00081     GLenum fpformats_ati[4] = {GL_LUMINANCE_FLOAT32_ATI,
00082                                GL_LUMINANCE_ALPHA_FLOAT32_ATI,
00083                                GL_RGB_FLOAT32_ATI,
00084                                GL_RGBA_FLOAT32_ATI};
00085     GLenum* fpformats = 0;
00086     
if (exts.find(
"NV_float_buffer") != std::string::npos) {
00087       fpformats = fpformats_nv;
00088     } 
else if (exts.find(
"ATI_texture_float") != std::string::npos) {
00089       fpformats = fpformats_ati;
00090     }
00091 
00092     
if (!fpformats) {
00093       SH_DEBUG_ERROR(
"Could not find appropriate floating-point format extension\n"
00094                      
"Using non-floating point texture instead!");
00095       
return node->size();
00096     }
00097     
00098     
return fpformats[node->size() - 1];
00099   }
00100   
return 0;
00101 }
00102 
00103 GLenum shGlFormat(
const ShTextureNodePtr& node)
00104 {
00105   
switch (node->size()) {
00106   
case 1:
00107     
return GL_LUMINANCE;
00108   
case 2:
00109     
return GL_LUMINANCE_ALPHA;
00110   
case 3:
00111     
return GL_RGB;
00112   
case 4:
00113     
return GL_RGBA;
00114   
default:
00115     
break;
00116   }
00117   
00118   
return 0;
00119 }
00120 
00121 
struct StorageFinder {
00122   StorageFinder(
const ShTextureNodePtr& node, 
int context,
00123                 
bool ignoreTarget = 
false)
00124     : node(node), context(context), ignoreTarget(ignoreTarget)
00125   {
00126   }
00127   
00128   
bool operator()(
const ShStoragePtr& storage)
 const
00129 
  {
00130     GlTextureStoragePtr t = shref_dynamic_cast<GlTextureStorage>(storage);
00131     
if (!t) {
00132       
return false;
00133     }
00134     
if (t->context() != context) {
00135       
return false;
00136     }
00137     
if (!ignoreTarget) {
00138       
if (t->texName()->params() != node->traits()) 
return false;
00139       
if (t->target() != shGlTargets[node->dims()]) 
return false;
00140     }
00141     
if (t->width() != node->width()) 
return false;
00142     
if (t->height() != node->height()) 
return false;
00143     
if (t->depth() != node->depth()) 
return false;
00144     
return true;
00145   }
00146   
00147   
const ShTextureNodePtr& node;
00148   
int context;
00149   
bool ignoreTarget;
00150 };
00151 
00152 GlTextures::GlTextures(
int context)
00153   : m_context(context)
00154 {
00155 }
00156 
00157 TextureStrategy* GlTextures::create(
int context)
00158 {
00159   
return new GlTextures(context);
00160 }
00161 
00162 
00163 
void GlTextures::bindTexture(
const ShTextureNodePtr& node,
00164                              GLenum target)
00165 {
00166   
if (!node) 
return;
00167 
00168   
00169   
00170   
if (!node->meta(
"opengl:preset").empty()) {
00171     SH_GL_CHECK_ERROR(glActiveTextureARB(target));
00172     GLuint name;
00173     std::istringstream is(node->meta(
"opengl:preset"));
00174     is >> name; 
00175     SH_GL_CHECK_ERROR(glBindTexture(shGlTargets[node->dims()], name));
00176     node->meta(
"opengl:texid", node->meta(
"opengl:preset"));
00177     
return;
00178   } 
00179   
00180   
if (node->dims() == SH_TEXTURE_CUBE) {
00181     
00182     
00183     
00184     GlTextureName::NameList::const_iterator I;
00185     
for (I = GlTextureName::beginNames(); I != GlTextureName::endNames(); ++I) {
00186       
const GlTextureName* name = *I;
00187       
if (name->target() != GL_TEXTURE_CUBE_MAP) 
continue;
00188       
if (name->params() != node->traits()) 
continue;
00189       
00190       GlTextureName::StorageList::const_iterator S;
00191       
for (S = name->beginStorages(); S != name->endStorages(); ++S) {
00192         GlTextureStorage* s = dynamic_cast<GlTextureStorage*>(*S);
00193         
if (!s) 
continue;
00194         
ShCubeDirection dir = glToShCubeDir(s->target());
00195         
if (s->memory() != node->memory(dir).object() || !StorageFinder(node, m_context, 
true)(s))
00196           
break;
00197       }
00198       
00199       
if (S == name->endStorages()) 
break;
00200     }
00201     
00202     
if (I == GlTextureName::endNames()) {
00203       
00204       GlTextureNamePtr texname = 
new GlTextureName(GL_TEXTURE_CUBE_MAP);
00205       texname->params(node->traits());
00206       
for (
int i = 0; i < 6; i++) {
00207         
ShCubeDirection dir = static_cast<ShCubeDirection>(i);
00208         GlTextureStoragePtr storage = 
new GlTextureStorage(m_context,
00209                                                            node->memory(dir).object(),
00210                                                            shGlCubeMapTargets[i],
00211                                                            shGlFormat(node),
00212                                                            shGlInternalFormat(node),
00213                                                            node->width(), node->height(),
00214                                                            node->depth(),
00215                                                            texname);
00216         storage->sync();
00217       }
00218       SH_GL_CHECK_ERROR(glActiveTextureARB(target));
00219       SH_GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_CUBE_MAP, texname->value()));
00220       std::ostringstream os;
00221       os << texname->value();
00222       node->meta(
"opengl:texid", os.str());
00223     } 
else {
00224       
00225       GlTextureName::StorageList::const_iterator S;
00226       
for (S = (*I)->beginStorages(); S != (*I)->endStorages(); ++S) {
00227         GlTextureStorage* s = dynamic_cast<GlTextureStorage*>(*S);
00228         
if (!s) 
continue;
00229         s->sync();
00230       }
00231       SH_GL_CHECK_ERROR(glActiveTextureARB(target));
00232       SH_GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_CUBE_MAP, (*I)->value()));
00233       std::ostringstream os;
00234       os << (*I)->value();
00235       node->meta(
"opengl:texid", os.str());
00236     }
00237   } 
else {
00238 
00239     StorageFinder finder(node, m_context);
00240     GlTextureStoragePtr storage =
00241       shref_dynamic_cast<GlTextureStorage>(node->memory()->findStorage(
"opengl:texture", finder));
00242     
if (!storage) {
00243       GlTextureNamePtr name = 
new GlTextureName(shGlTargets[node->dims()]);
00244       storage = 
new GlTextureStorage(m_context,
00245                                      node->memory().object(),
00246                                      shGlTargets[node->dims()],
00247                                      shGlFormat(node),
00248                                      shGlInternalFormat(node),
00249                                      node->width(), node->height(), node->depth(),
00250                                      name);
00251       name->params(node->traits());
00252     }
00253 
00254     SH_GL_CHECK_ERROR(glActiveTextureARB(target));
00255     storage->sync();
00256     SH_GL_CHECK_ERROR(glBindTexture(shGlTargets[node->dims()], storage->name()));
00257 
00258     std::ostringstream os;
00259     os << storage->name();
00260     node->meta(
"opengl:texid", os.str());
00261   }
00262 }
00263 
00264 
00265 }