Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

GlTextures.cpp

00001 // Sh: A GPU metaprogramming language. 00002 // 00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory 00004 // Project administrator: Michael D. McCool 00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa, 00006 // Michael D. McCool 00007 // 00008 // This software is provided 'as-is', without any express or implied 00009 // warranty. In no event will the authors be held liable for any damages 00010 // arising from the use of this software. 00011 // 00012 // Permission is granted to anyone to use this software for any purpose, 00013 // including commercial applications, and to alter it and redistribute it 00014 // freely, subject to the following restrictions: 00015 // 00016 // 1. The origin of this software must not be misrepresented; you must 00017 // not claim that you wrote the original software. If you use this 00018 // software in a product, an acknowledgment in the product documentation 00019 // would be appreciated but is not required. 00020 // 00021 // 2. Altered source versions must be plainly marked as such, and must 00022 // not be misrepresented as being the original software. 00023 // 00024 // 3. This notice may not be removed or altered from any source 00025 // distribution. 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 // TODO: Warn or something 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 // TODO: Check for memories that are 0 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; // TODO: Check for errors 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 // Look for a cubemap that happens to have just the right storages 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 // If we got through the whole list, we've found a matching list. 00199 if (S == name->endStorages()) break; 00200 } 00201 00202 if (I == GlTextureName::endNames()) { 00203 // Need to allocate new storages 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 // Just synchronize the storages 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 }

Generated on Mon Oct 18 14:17:38 2004 for Sh by doxygen 1.3.7