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 }