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

GlTextureStorage.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 "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     // Bind texture name for this scope.
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     // @todo a little hackish...but we promise host->data() will not change... 
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     // If the texture is not full, must not copy more than count
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     // Texture downloads are expensive!
00192     return 100;
00193   }
00194 
00195   static HostGlTextureTransfer* instance;
00196 };
00197 
00198 HostGlTextureTransfer* HostGlTextureTransfer::instance = new HostGlTextureTransfer();
00199 
00200 }

Generated on Mon Jan 24 18:36:29 2005 for Sh by  doxygen 1.4.1