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 "ShContext.hpp"
00028 #include "GlTextures.hpp"
00029 #include <sstream>
00030 #include "GlTextureName.hpp"
00031 #include "GlTextureStorage.hpp"
00032
00033 namespace shgl {
00034
00035 using namespace SH;
00036
00037 const unsigned int shGlTargets[] = {
00038 GL_TEXTURE_1D,
00039 GL_TEXTURE_2D,
00040 GL_TEXTURE_RECTANGLE_NV,
00041 GL_TEXTURE_3D,
00042 GL_TEXTURE_CUBE_MAP,
00043 };
00044
00045 const unsigned int shGlCubeMapTargets[] = {
00046 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
00047 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
00048 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
00049 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
00050 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
00051 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
00052 };
00053
00054 ShCubeDirection glToShCubeDir(GLuint target)
00055 {
00056 switch (target) {
00057 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
00058 return SH_CUBE_POS_X;
00059 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
00060 return SH_CUBE_NEG_X;
00061 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
00062 return SH_CUBE_POS_Y;
00063 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
00064 return SH_CUBE_NEG_Y;
00065 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
00066 return SH_CUBE_POS_Z;
00067 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
00068 return SH_CUBE_NEG_Z;
00069 }
00070 return SH_CUBE_POS_X;
00071 }
00072
00073 GLenum shGlInternalFormat(const ShTextureNodePtr& node)
00074 {
00075 GLenum byteformats[4] = {GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8};
00076 GLenum shortformats[4] = {GL_LUMINANCE16, GL_LUMINANCE16_ALPHA16, GL_RGB16, GL_RGBA16};
00077
00078 GLenum halfformats_nv[4] = {GL_FLOAT_R16_NV, GL_FLOAT_RGBA16_NV, GL_FLOAT_RGB16_NV, GL_FLOAT_RGBA16_NV};
00079 GLenum fpformats_nv[4] = {GL_FLOAT_R32_NV, GL_FLOAT_RGBA32_NV, GL_FLOAT_RGB32_NV, GL_FLOAT_RGBA32_NV};
00080
00081 GLenum halfformats_ati[4] = {GL_LUMINANCE_FLOAT16_ATI,
00082 GL_LUMINANCE_ALPHA_FLOAT16_ATI,
00083 GL_RGB_FLOAT16_ATI,
00084 GL_RGBA_FLOAT16_ATI};
00085
00086 GLenum fpformats_ati[4] = {GL_LUMINANCE_FLOAT32_ATI,
00087 GL_LUMINANCE_ALPHA_FLOAT32_ATI,
00088 GL_RGB_FLOAT32_ATI,
00089 GL_RGBA_FLOAT32_ATI};
00090 GLenum* formats = 0;
00091 bool clamped = (node->traits().clamping() == SH::ShTextureTraits::SH_CLAMPED);
00092
00093
00094
00095 std::string exts(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
00096 bool float_nv = (exts.find("NV_float_buffer") != std::string::npos);
00097 bool float_ati = (exts.find("ATI_texture_float") != std::string::npos);
00098
00099
00100 if (node->size() < 0 || node->size() > 4) return 0;
00101
00102
00103
00104
00105
00106
00107
00108
00109 if(clamped) {
00110 switch(node->valueType()) {
00111 case SH_DOUBLE:
00112 case SH_FLOAT:
00113 case SH_HALF:
00114 case SH_FINT:
00115 case SH_FSHORT:
00116 case SH_FUINT:
00117 case SH_FUSHORT:
00118 formats = shortformats;
00119 break;
00120
00121 case SH_FBYTE:
00122 case SH_FUBYTE:
00123 formats = byteformats;
00124 break;
00125
00126 case SH_INT:
00127 case SH_UINT:
00128 case SH_SHORT:
00129 case SH_USHORT:
00130 case SH_BYTE:
00131 case SH_UBYTE:
00132 SH_DEBUG_WARN("Using integer data type for a [0,1] clamped texture format is not advised.");
00133 formats = byteformats;
00134 break;
00135
00136 default:
00137 SH_DEBUG_ERROR("Could not find appropriate clamped texture format \n"
00138 "Using default instead!");
00139 return node->size();
00140 break;
00141 }
00142 } else {
00143 switch(node->valueType()) {
00144 case SH_DOUBLE:
00145 case SH_FLOAT:
00146 case SH_INT:
00147 case SH_UINT:
00148 if (float_nv) formats = fpformats_nv;
00149 else if (float_ati) formats = fpformats_ati;
00150 break;
00151
00152 case SH_HALF:
00153 case SH_SHORT:
00154 case SH_BYTE:
00155 case SH_USHORT:
00156 case SH_UBYTE:
00157 if (float_nv) formats = halfformats_nv;
00158 else if (float_ati) formats = halfformats_ati;
00159 break;
00160
00161 case SH_FINT:
00162 case SH_FSHORT:
00163 case SH_FUINT:
00164 case SH_FUSHORT:
00165 formats = shortformats;
00166 break;
00167
00168 case SH_FBYTE:
00169 case SH_FUBYTE:
00170 formats = byteformats;
00171 break;
00172 default:
00173 SH_DEBUG_ERROR("Could not find appropriate unclamped texture format \n"
00174 "Using default instead!");
00175 return node->size();
00176 break;
00177 }
00178 }
00179
00180 return formats[node->size() - 1];
00181 }
00182
00183 GLenum shGlFormat(const ShTextureNodePtr& node)
00184 {
00185 switch (node->size()) {
00186 case 1:
00187 return GL_LUMINANCE;
00188 case 2:
00189 return GL_LUMINANCE_ALPHA;
00190 case 3:
00191 return GL_RGB;
00192 case 4:
00193 return GL_RGBA;
00194 default:
00195 break;
00196 }
00197
00198 return 0;
00199 }
00200
00201
00202
00203
00204
00205 GLenum shGlType(ShValueType valueType, ShValueType &convertedType) {
00206 convertedType = SH_VALUETYPE_END;
00207 GLenum result = GL_NONE;
00208 switch(valueType) {
00209 case SH_I_DOUBLE:
00210 case SH_I_FLOAT:
00211 SH_DEBUG_ERROR("Interval types not supported in memory");
00212 result = GL_FLOAT;
00213 break;
00214
00215 case SH_DOUBLE:
00216 case SH_HALF:
00217 case SH_INT:
00218 case SH_SHORT:
00219 case SH_BYTE:
00220 case SH_UINT:
00221 case SH_USHORT:
00222 case SH_UBYTE:
00223 convertedType = SH_FLOAT;
00224 case SH_FLOAT: result = GL_FLOAT; break;
00225
00226
00227 case SH_FINT: result = GL_INT; break;
00228 case SH_FSHORT: result = GL_SHORT; break;
00229 case SH_FBYTE: result = GL_BYTE; break;
00230 case SH_FUINT: result = GL_UNSIGNED_INT; break;
00231 case SH_FUSHORT: result = GL_UNSIGNED_SHORT; break;
00232 case SH_FUBYTE: result = GL_UNSIGNED_BYTE; break;
00233
00234 default:
00235 SH_DEBUG_ERROR("Unsupported value type to glReadPixel type conversion");
00236 break;
00237 }
00238
00239 std::string exts(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
00240 if(valueType == SH_HALF) {
00241 if((exts.find("NV_half_float") != std::string::npos)) {
00242 convertedType = SH_VALUETYPE_END;
00243 result = GL_HALF_FLOAT_NV;
00244 } else if(exts.find("APPLE_float_pixels") != std::string::npos) {
00245 convertedType = SH_VALUETYPE_END;
00246
00247 }
00248 }
00249 SH_DEBUG_ASSERT(result != GL_NONE);
00250 return result;
00251 }
00252
00253 struct StorageFinder {
00254 StorageFinder(const ShTextureNodePtr& node, bool ignoreTarget = false)
00255 : node(node), ignoreTarget(ignoreTarget)
00256 {
00257 }
00258
00259 bool operator()(const ShStoragePtr& storage) const
00260 {
00261 GlTextureStoragePtr t = shref_dynamic_cast<GlTextureStorage>(storage);
00262 if (!t) {
00263 return false;
00264 }
00265 if (!ignoreTarget) {
00266 if (t->texName()->params() != node->traits()) return false;
00267 if (t->target() != shGlTargets[node->dims()]) return false;
00268 }
00269 if (t->width() != node->width()) return false;
00270 if (t->height() != node->height()) return false;
00271 if (t->depth() != node->depth()) return false;
00272 return true;
00273 }
00274
00275 const ShTextureNodePtr& node;
00276 bool ignoreTarget;
00277 };
00278
00279 GlTextures::GlTextures(void)
00280 {
00281 }
00282
00283 TextureStrategy* GlTextures::create(void)
00284 {
00285 return new GlTextures;
00286 }
00287
00288
00289 void GlTextures::bindTexture(const ShTextureNodePtr& node,
00290 GLenum target)
00291 {
00292 if (!node) return;
00293
00294
00295
00296 if (!node->meta("opengl:preset").empty()) {
00297 SH_GL_CHECK_ERROR(glActiveTextureARB(target));
00298 GLuint name;
00299 std::istringstream is(node->meta("opengl:preset"));
00300 is >> name;
00301 SH_GL_CHECK_ERROR(glBindTexture(shGlTargets[node->dims()], name));
00302 node->meta("opengl:texid", node->meta("opengl:preset"));
00303 return;
00304 }
00305
00306 if (node->dims() == SH_TEXTURE_CUBE) {
00307
00308
00309
00310 GlTextureName::NameList::const_iterator I;
00311 for (I = GlTextureName::beginNames(); I != GlTextureName::endNames(); ++I) {
00312 const GlTextureName* name = *I;
00313 if (name->target() != GL_TEXTURE_CUBE_MAP) continue;
00314 if (name->params() != node->traits()) continue;
00315
00316 GlTextureName::StorageList::const_iterator S;
00317 for (S = name->beginStorages(); S != name->endStorages(); ++S) {
00318 GlTextureStorage* s = dynamic_cast<GlTextureStorage*>(*S);
00319 if (!s) continue;
00320 ShCubeDirection dir = glToShCubeDir(s->target());
00321 if (s->memory() != node->memory(dir).object() || !StorageFinder(node, true)(s))
00322 break;
00323 }
00324
00325 if (S == name->endStorages()) break;
00326 }
00327
00328 if (I == GlTextureName::endNames()) {
00329
00330 GlTextureNamePtr texname = new GlTextureName(GL_TEXTURE_CUBE_MAP);
00331 texname->params(node->traits());
00332 for (int i = 0; i < 6; i++) {
00333 ShCubeDirection dir = static_cast<ShCubeDirection>(i);
00334 GlTextureStoragePtr storage = new GlTextureStorage(node->memory(dir).object(),
00335 shGlCubeMapTargets[i],
00336 shGlFormat(node),
00337 shGlInternalFormat(node),
00338 node->valueType(),
00339 node->width(), node->height(),
00340 node->depth(), node->size(),
00341 node->count(), texname);
00342 storage->sync();
00343 }
00344 SH_GL_CHECK_ERROR(glActiveTextureARB(target));
00345 SH_GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_CUBE_MAP, texname->value()));
00346 std::ostringstream os;
00347 os << texname->value();
00348 node->meta("opengl:texid", os.str());
00349 } else {
00350
00351 GlTextureName::StorageList::const_iterator S;
00352 for (S = (*I)->beginStorages(); S != (*I)->endStorages(); ++S) {
00353 GlTextureStorage* s = dynamic_cast<GlTextureStorage*>(*S);
00354 if (!s) continue;
00355 s->sync();
00356 }
00357 SH_GL_CHECK_ERROR(glActiveTextureARB(target));
00358 SH_GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_CUBE_MAP, (*I)->value()));
00359 std::ostringstream os;
00360 os << (*I)->value();
00361 node->meta("opengl:texid", os.str());
00362 }
00363 } else {
00364
00365 StorageFinder finder(node);
00366 GlTextureStoragePtr storage =
00367 shref_dynamic_cast<GlTextureStorage>(node->memory()->findStorage("opengl:texture", finder));
00368 if (!storage) {
00369 GlTextureNamePtr name = new GlTextureName(shGlTargets[node->dims()]);
00370 storage = new GlTextureStorage(node->memory().object(),
00371 shGlTargets[node->dims()],
00372 shGlFormat(node),
00373 shGlInternalFormat(node),
00374 node->valueType(),
00375 node->width(), node->height(),
00376 node->depth(), node->size(),
00377 node->count(), name);
00378 name->params(node->traits());
00379 }
00380
00381 SH_GL_CHECK_ERROR(glActiveTextureARB(target));
00382 storage->sync();
00383 SH_GL_CHECK_ERROR(glBindTexture(shGlTargets[node->dims()], storage->name()));
00384
00385 std::ostringstream os;
00386 os << storage->name();
00387 node->meta("opengl:texid", os.str());
00388 }
00389 }
00390
00391
00392 }