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 "GlTextureStorage.hpp"
00028 #include "ShTypeInfo.hpp"
00029 #include "ShVariantFactory.hpp"
00030
00031 namespace shgl {
00032
00033 using namespace SH;
00034
00035 GlTextureStorage::GlTextureStorage(ShMemory* memory, GLenum target,
00036 GLenum format, GLint internalFormat,
00037 ShValueType valueType,
00038 int width, int height, int depth, int tuplesize,
00039 int count, GlTextureNamePtr name)
00040 : ShStorage(memory),
00041 m_name(name), m_target(target), m_format(format),
00042 m_internalFormat(internalFormat),
00043 m_valueType(valueType),
00044 m_width(width), m_height(height), m_depth(depth), m_tuplesize(tuplesize), m_count(count)
00045 {
00046 m_name->addStorage(this);
00047 }
00048
00049 GlTextureStorage::~GlTextureStorage()
00050 {
00051 m_name->removeStorage(this);
00052 }
00053
00054
00055 class HostGlTextureTransfer : public ShTransfer {
00056 HostGlTextureTransfer()
00057 : ShTransfer("host", "opengl:texture")
00058 {
00059 }
00060
00061 bool transfer(const ShStorage* from, ShStorage* to)
00062 {
00063 const ShHostStorage* host = dynamic_cast<const ShHostStorage*>(from);
00064 GlTextureStorage* texture = dynamic_cast<GlTextureStorage*>(to);
00065
00066
00067 GlTextureName::Binding binding(texture->texName());
00068
00069
00070 ShValueType valueType = texture->valueType();
00071 int count = texture->count();
00072 int tuplesize = texture->tuplesize();
00073
00074 GLenum type;
00075 ShValueType convertedType;
00076 type = shGlType(valueType, convertedType);
00077
00078 ShVariantPtr dataVariant;
00079
00080 ShVariantPtr hostVariant = shVariantFactory(valueType, SH_MEM)->generate(
00081 const_cast<void *>(host->data()), count * tuplesize, false);
00082
00083 if(convertedType != SH_VALUETYPE_END) {
00084 SH_DEBUG_WARN("ARB backend does not handle " << shValueTypeName(valueType) << " natively. Converting to " << shValueTypeName(convertedType));
00085 dataVariant = shVariantFactory(convertedType, SH_MEM)->generate(count * tuplesize);
00086 dataVariant->set(hostVariant);
00087 } else {
00088 dataVariant = hostVariant;
00089 }
00090
00091 int width = texture->width();
00092 int height = texture->height();
00093 int depth = texture->depth();
00094
00095
00096 bool full_copy = (count == (width * height * depth));
00097
00098 switch(texture->target()) {
00099 case GL_TEXTURE_1D:
00100 if (full_copy) {
00101 SH_GL_CHECK_ERROR(glTexImage1D(texture->target(), 0,
00102 texture->internalFormat(),
00103 width, 0, texture->format(), type,
00104 dataVariant->array()));
00105 } else {
00106 SH_GL_CHECK_ERROR(glTexImage1D(texture->target(), 0,
00107 texture->internalFormat(),
00108 width, 0, texture->format(), type,
00109 NULL));
00110 SH_GL_CHECK_ERROR(glTexSubImage1D(texture->target(), 0, 0,
00111 count, texture->format(), type,
00112 dataVariant->array()));
00113 }
00114 break;
00115 case GL_TEXTURE_2D:
00116 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
00117 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
00118 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
00119 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
00120 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
00121 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
00122 case GL_TEXTURE_RECTANGLE_NV:
00123 if (full_copy) {
00124 SH_GL_CHECK_ERROR(glTexImage2D(texture->target(), 0,
00125 texture->internalFormat(),
00126 width, height, 0, texture->format(),
00127 type, dataVariant->array()));
00128 } else {
00129 SH_GL_CHECK_ERROR(glTexImage2D(texture->target(), 0,
00130 texture->internalFormat(),
00131 width, height, 0, texture->format(),
00132 type, NULL));
00133 int last_row_count = count % width;
00134 int full_rows_count = count - last_row_count;
00135 int full_rows_height = full_rows_count / width;
00136 SH_GL_CHECK_ERROR(glTexSubImage2D(texture->target(), 0, 0, 0,
00137 width, full_rows_height, texture->format(),
00138 type, dataVariant->array()));
00139 int array_offset = full_rows_height * width * dataVariant->datasize() * tuplesize;
00140 SH_GL_CHECK_ERROR(glTexSubImage2D(texture->target(), 0, 0, full_rows_height,
00141 last_row_count, 1, texture->format(),
00142 type, static_cast<char*>(dataVariant->array()) + array_offset));
00143 }
00144 break;
00145 case GL_TEXTURE_3D:
00146 if (full_copy) {
00147 SH_GL_CHECK_ERROR(glTexImage3D(texture->target(), 0,
00148 texture->internalFormat(),
00149 width, height,
00150 depth, 0, texture->format(),
00151 type, dataVariant->array()));
00152 } else {
00153 SH_GL_CHECK_ERROR(glTexImage3D(texture->target(), 0,
00154 texture->internalFormat(),
00155 width, height,
00156 depth, 0, texture->format(),
00157 type, NULL));
00158 int last_surface_count = count % (width * height);
00159 int last_row_count = last_surface_count % width;
00160 int full_rows_count = last_surface_count - last_row_count;
00161 int full_rows_height = full_rows_count / width;
00162 int full_surfaces_count = count - last_surface_count;
00163 int full_surfaces_depth = full_surfaces_count / (width * height);
00164 SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), 0, 0, 0,
00165 0, width, height,
00166 full_surfaces_depth, texture->format(),
00167 type, dataVariant->array()));
00168 int array_offset = full_surfaces_depth * width * height * dataVariant->datasize() * tuplesize;
00169 SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), 0, 0, 0,
00170 full_surfaces_depth, width, full_rows_height,
00171 1, texture->format(),
00172 type, static_cast<char*>(dataVariant->array()) + array_offset));
00173 array_offset += full_rows_height * width * dataVariant->datasize() * tuplesize;
00174 SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), 0, 0, full_rows_height,
00175 full_surfaces_depth, last_row_count, 1,
00176 1, texture->format(),
00177 type, static_cast<char*>(dataVariant->array()) + array_offset));
00178 }
00179 break;
00180 default:
00181 SH_DEBUG_WARN("Texture target " << texture->target() << " not handled by GL backend");
00182 break;
00183 }
00184
00185
00186 return true;
00187 }
00188
00189 int cost()
00190 {
00191
00192 return 100;
00193 }
00194
00195 static HostGlTextureTransfer* instance;
00196 };
00197
00198 HostGlTextureTransfer* HostGlTextureTransfer::instance = new HostGlTextureTransfer();
00199
00200 }