texture_cache.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2014, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //
00028 // *****************************************************************************
00029 
00030 #include <tile_map/texture_cache.h>
00031 
00032 #include <cmath>
00033 
00034 #include <boost/make_shared.hpp>
00035 
00036 #include <GL/gl.h>
00037 #include <GL/glu.h>
00038 
00039 #include <ros/ros.h>
00040 
00041 #include <QGLWidget>
00042 #include <QImage>
00043 
00044 #include <swri_math_util/math_util.h>
00045 
00046 namespace tile_map
00047 {
00048   Texture::Texture(int32_t texture_id, size_t hash) : 
00049     id(texture_id),
00050     url_hash(hash)
00051   {
00052   }
00053 
00054   Texture::~Texture()
00055   {
00056     //ROS_ERROR("==== DELETING TEXTURE: %d ====", id);
00057     // The texture will automatically be freed from the GPU memory when it goes
00058     // out of scope.  This is effectively when it is no longer in the texture
00059     // cache or being referenced for a render.
00060     GLuint ids[1];
00061     ids[0] = id;
00062     glDeleteTextures(1, &ids[0]);
00063   }
00064 
00065   TextureCache::TextureCache(ImageCachePtr image_cache, size_t size) : 
00066     cache_(size),
00067     image_cache_(image_cache)
00068   {
00069   
00070   }
00071 
00072   TexturePtr TextureCache::GetTexture(size_t url_hash, const QString& url, bool& failed)
00073   {
00074     TexturePtr texture;
00075 
00076     failed = false;
00077 
00078     TexturePtr* texture_ptr = cache_.take(url_hash);
00079     if (texture_ptr)
00080     {
00081       texture = *texture_ptr;
00082       delete texture_ptr;
00083     }
00084     
00085     if (!texture)
00086     {
00087       ImagePtr image = image_cache_->GetImage(url_hash, url);
00088       
00089       if (image)
00090       {
00091         failed = image->Failed();
00092         boost::shared_ptr<QImage> image_ptr = image->GetImage();
00093         if (image_ptr)
00094         {
00095           // All of the OpenGL calls need to occur on the main thread and so
00096           // can't be done in the background.  The QImage calls could 
00097           // potentially be done in a background thread by the image cache.
00098           QImage qimage = *image_ptr;
00099         
00100           GLuint ids[1];
00101           uint32_t check = 9999999;
00102           ids[0] = check;
00103           
00104           glGenTextures(1, &ids[0]);
00105         
00106           if (check == ids[0])
00107           {
00108             ROS_ERROR("FAILED TO CREATE TEXTURE");
00109             
00110             GLenum err = glGetError();
00111             const GLubyte *errString = gluErrorString(err);
00112             ROS_ERROR("GL ERROR(%u): %s", err, errString);
00113             return texture;
00114           }
00115         
00116           texture_ptr = new TexturePtr(boost::make_shared<Texture>(ids[0], url_hash));
00117           texture = *texture_ptr;
00118 
00119           float max_dim = std::max(qimage.width(), qimage.height());
00120           int32_t dimension = swri_math_util::Round(
00121             std::pow(2, std::ceil(std::log(max_dim) / std::log(2.0f))));
00122 
00123           if (qimage.width() != dimension || qimage.height() != dimension)
00124           {
00125             qimage = qimage.scaled(dimension, dimension, Qt::IgnoreAspectRatio, Qt::FastTransformation);
00126           }
00127           
00128           glBindTexture(GL_TEXTURE_2D, texture->id);
00129           glTexImage2D(
00130             GL_TEXTURE_2D, 
00131             0, 
00132             3, 
00133             dimension, 
00134             dimension, 
00135             0, 
00136             GL_RGBA, 
00137             GL_UNSIGNED_BYTE, 
00138             QGLWidget::convertToGLFormat(qimage).bits());
00139             
00140           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00141           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00142 
00143           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00144           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00145           
00146           cache_.insert(url_hash, texture_ptr);
00147         }
00148       }
00149     }
00150     
00151     return texture;
00152   }
00153   
00154   void TextureCache::AddTexture(const TexturePtr& texture)
00155   {
00156     if (texture)
00157     {
00158       TexturePtr* texture_ptr = new TexturePtr(texture);
00159       cache_.insert(texture->url_hash, texture_ptr);
00160     }
00161   }
00162 
00163   void TextureCache::Clear()
00164   {
00165     image_cache_->Clear();
00166     cache_.clear();
00167   }
00168 }


tile_map
Author(s): Marc Alban
autogenerated on Thu Aug 24 2017 02:46:24