00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009 #include "vgui_cache_wizard.h"
00010
00011 #include <vil1/vil1_crop.h>
00012 #include <vil1/vil1_pixel.h>
00013
00014 #include <vcl_cassert.h>
00015 #include <vcl_iostream.h>
00016
00017 #include <vgui/vgui_pixel.h>
00018 #include <vgui/vgui_macro.h>
00019 #include <vgui/internals/vgui_accelerate.h>
00020
00021 #define DEFAULT_QUADRANT_WIDTH 256
00022 #define DEFAULT_QUADRANT_HEIGHT 256
00023 #define INVALID_TEXTURE_NAME -1
00024
00025 #define mb_jigerry_pokery(a,b) ((a/b)+(a%b ? 1:0))
00026 #define mb_is_valid(x) (int(x) != INVALID_TEXTURE_NAME)
00027
00028 bool debug = false;
00029
00030
00031
00032
00033
00034 vgui_cache_wizard::vgui_cache_wizard(int quadrant_width,
00035 int quadrant_height)
00036 {
00037 if (debug)
00038 vcl_cerr << __FILE__": this is the constructor\n";
00039
00040
00041
00042
00043
00044 GLint max_texture_size;
00045 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
00046 if (max_texture_size>256)
00047 max_texture_size = 256;
00048
00049 if (quadrant_width<max_texture_size)
00050 quadrant_width_ = quadrant_width;
00051 else
00052 quadrant_width_ = max_texture_size;
00053 if (quadrant_height<max_texture_size)
00054 quadrant_height_ = quadrant_height;
00055 else
00056 quadrant_height_ = max_texture_size;
00057
00058 max_texture_num_ = (unsigned int)(8388608.0f/(quadrant_width_*quadrant_height_*4.0f))*3;
00059
00060 texture_names_ = new GLuint[max_texture_num_];
00061 glGenTextures(max_texture_num_,texture_names_);
00062 }
00063
00064
00065 vgui_cache_wizard::~vgui_cache_wizard()
00066 {
00067 vcl_list<GLuint>::iterator i = cache_queue_.begin();
00068 for (int j=0; i!=cache_queue_.end(); ++i,++j)
00069 texture_names_[j] = *i;
00070 glDeleteTextures(cache_queue_.size(),texture_names_);
00071 delete texture_names_;
00072 }
00073
00074 vgui_cache_wizard *vgui_cache_wizard::Instance()
00075 {
00076 static vgui_cache_wizard *instance_ = new vgui_cache_wizard(DEFAULT_QUADRANT_WIDTH, DEFAULT_QUADRANT_HEIGHT);
00077 return instance_;
00078 }
00079
00080
00081 int vgui_cache_wizard::load_image(vil1_image img)
00082 {
00083
00084 vcl_vector<wizard_image *>::iterator i = images_.begin();
00085 for (int j = 0; i!=images_.end(); ++i,++j)
00086 if ((*i)->first == img)
00087 return j;
00088
00089
00090 int cx = mb_jigerry_pokery(img.width(),quadrant_width_);
00091 int cy = mb_jigerry_pokery(img.height(),quadrant_height_);
00092
00093 dimension *dim = new dimension(cx,cy);
00094 dimensions_.push_back(dim);
00095
00096 image_cache_quadrants *mapping = new image_cache_quadrants;
00097 for (int i = 0;i<cy;i++)
00098 for (int j = 0;j<cx;j++)
00099 mapping->push_back(unsigned(INVALID_TEXTURE_NAME));
00100
00101 wizard_image *wz = new wizard_image(img,mapping);
00102 images_.push_back(wz);
00103 return images_.size()-1;
00104 }
00105
00106
00107 bool vgui_cache_wizard::get_section(int id,int x,int y,int width,int height,
00108 image_cache_quadrants *quadrants,
00109 dimension *pos,
00110 dimension *size)
00111 {
00112
00113 wizard_image *wz = images_[id];
00114 vil1_image img = wz->first;
00115 image_cache_quadrants *icq = wz->second;
00116 dimension *d = dimensions_[id];
00117
00118 int qx_c = x/quadrant_width_;
00119 int qy_c = y/quadrant_height_;
00120
00121 int qw_c = (x+width)/quadrant_width_-qx_c;
00122 int qh_c = (y+height)/quadrant_height_-qy_c;
00123 if (debug)
00124 vcl_cerr<<"X: "<<qx_c<<"Y: "<<qy_c<<"W:"<<qw_c<<" H:"<<qh_c<<vcl_endl;
00125 pos->first = qx_c;
00126 pos->second = qy_c;
00127 size->first = qw_c;
00128 size->second = qh_c;
00129
00130
00131 int ul_q = qy_c*d->first+qx_c;
00132 glEnable(GL_TEXTURE_2D);
00133 vgui_macro_report_errors;
00134
00135 for (int i = 0;i<=qh_c;i++)
00136 for (int j = 0;j<=qw_c;j++)
00137 {
00138
00139
00140 int index = ul_q+i*d->first+j;
00141
00142 if (index<0 || index>=int(icq->size()))
00143 {
00144 vcl_cerr << __FILE__ ": index out of range\n";
00145 return false;
00146 }
00147 if (mb_is_valid((*icq)[index]))
00148 {
00149 quadrants->push_back((*icq)[index]);
00150 vcl_list<GLuint>::iterator i;
00151 for (i = cache_queue_.begin();i!=cache_queue_.end() && (*i)!=(*icq)[index]; i++)
00152 ;
00153 cache_queue_.erase(i);
00154 cache_queue_.push_back((*icq)[index]);
00155 }
00156 else
00157 {
00158
00159
00160 GLuint texture_name;
00161 if (cache_queue_.size() == max_texture_num_)
00162 {
00163
00164 texture_name = cache_queue_.front();
00165 vcl_cerr<<"Texture name: "<<texture_name<<vcl_endl;
00166 cache_queue_.pop_front();
00167
00168
00169 for (vcl_vector<wizard_image *>::iterator i = images_.begin(); i!=images_.end();i++)
00170 for (image_cache_quadrants::iterator k = (*i)->second->begin(); k!=(*i)->second->end();k++)
00171 if ((*k) == texture_name)
00172 {
00173 *k = GLuint(INVALID_TEXTURE_NAME);
00174 vcl_cerr<<"Invalidated!\n";
00175 }
00176 }
00177 else
00178 {
00179 unsigned int k = 0;
00180 while (k<max_texture_num_ && texture_names_[k] == GLuint(-1)) ++k;
00181 texture_name = texture_names_[k];
00182 texture_names_[k] = GLuint(-1);
00183 }
00184
00185 glBindTexture(GL_TEXTURE_2D,texture_name);
00186 TexImage2D_Brownie(vil1_crop(img,pos->first*quadrant_width_+j*quadrant_width_,
00187 pos->second*quadrant_height_+i*quadrant_height_,
00188 quadrant_width_,
00189 quadrant_height_));
00190 quadrants->push_back(texture_name);
00191 cache_queue_.push_back(texture_name);
00192
00193 (*icq)[index] = texture_name;
00194 }
00195 }
00196 return true;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206 #define fsm_macro_begin(pix, wh) \
00207 pix *data = new pix[ img.width()*img.height() ]; \
00208 section_ok = img.get_section( data, 0,0, img.width(),img.height() ); \
00209 char const *what = wh; \
00210 \
00211 if (false) {}
00212
00213
00214
00215
00216
00217 #define fsm_macro_magic(fmt, typ, sto) \
00218 if (format==fmt && type==typ) { \
00219 if (debug) \
00220 vcl_cerr << __FILE__ ": converting " << what << " image to " #fmt "," #typ " format\n"; \
00221 if (!the_pixels) \
00222 the_pixels = new sto[img.width()*img.height()]; \
00223 vgui_pixel_convert_span(data, static_cast<sto*>(the_pixels), \
00224 img.width()*img.height()); \
00225 }
00226
00227
00228 #define fsm_macro_end \
00229 delete [] data; \
00230 assert(section_ok);
00231
00232 void vgui_cache_wizard::TexImage2D_Brownie(vil1_image img)
00233 {
00234 void *the_pixels = 0;
00235 bool section_ok;
00236
00237
00238
00239
00240 GLenum format,type;
00241 vgui_accelerate::instance()->vgui_choose_cache_format(&format,&type);
00242
00243 vil1_pixel_format_t pixel_format = vil1_pixel_format(img);
00244
00245 if (pixel_format == VIL1_BYTE)
00246 {
00247 fsm_macro_begin(GLubyte, "8 bit greyscale");
00248 fsm_macro_magic(GL_RGB, GL_UNSIGNED_BYTE, vgui_pixel_rgb888);
00249 fsm_macro_magic(GL_RGBA, GL_UNSIGNED_BYTE, vgui_pixel_rgba8888);
00250 #if defined(GL_UNSIGNED_SHORT_5_6_5)
00251 fsm_macro_magic(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, vgui_pixel_rgb565);
00252 #endif
00253 #if defined(GL_BGRA)
00254 fsm_macro_magic(GL_BGRA, GL_UNSIGNED_BYTE, vgui_pixel_bgra8888);
00255 #endif
00256 #if defined(GL_EXT_abgr) || defined(GL_ABGR_EXT)
00257 fsm_macro_magic(GL_ABGR_EXT, GL_UNSIGNED_BYTE, vgui_pixel_abgr8888);
00258 #endif
00259 fsm_macro_end;
00260 }
00261
00262
00263 else if (pixel_format == VIL1_RGB_BYTE)
00264 {
00265 fsm_macro_begin(vgui_pixel_rgb888, "24 bit RGB");
00266 fsm_macro_magic(GL_RGB, GL_UNSIGNED_BYTE, vgui_pixel_rgb888);
00267 fsm_macro_magic(GL_RGBA, GL_UNSIGNED_BYTE, vgui_pixel_rgba8888);
00268 #if defined(GL_UNSIGNED_SHORT_5_6_5)
00269 fsm_macro_magic(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, vgui_pixel_rgb565);
00270 #endif
00271 #if defined(GL_BGRA)
00272 fsm_macro_magic(GL_BGRA, GL_UNSIGNED_BYTE, vgui_pixel_bgra8888);
00273 #endif
00274 #if defined(GL_EXT_abgr) || defined(GL_ABGR_EXT)
00275 fsm_macro_magic(GL_ABGR_EXT, GL_UNSIGNED_BYTE, vgui_pixel_abgr8888);
00276 #endif
00277 fsm_macro_end;
00278 }
00279
00280
00281 else if (pixel_format == VIL1_RGBA_BYTE)
00282 {
00283 fsm_macro_begin(vgui_pixel_rgba8888, "32 bit RGBA");
00284 fsm_macro_magic(GL_RGB, GL_UNSIGNED_BYTE, vgui_pixel_rgb888);
00285 fsm_macro_magic(GL_RGBA, GL_UNSIGNED_BYTE, vgui_pixel_rgba8888);
00286 #if defined(GL_UNSIGNED_SHORT_5_6_5)
00287 fsm_macro_magic(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, vgui_pixel_rgb565);
00288 #endif
00289 #if defined(GL_BGRA)
00290 fsm_macro_magic(GL_BGRA, GL_UNSIGNED_BYTE, vgui_pixel_bgra8888);
00291 #endif
00292 #if defined(GL_EXT_abgr) || defined(GL_ABGR_EXT)
00293 fsm_macro_magic(GL_ABGR_EXT, GL_UNSIGNED_BYTE, vgui_pixel_abgr8888);
00294 #endif
00295 fsm_macro_end;
00296 }
00297
00298 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00299 vgui_macro_report_errors;
00300
00301 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00302 vgui_macro_report_errors;
00303
00304 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00305 vgui_macro_report_errors;
00306
00307 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00308 vgui_macro_report_errors;
00309
00310
00311 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
00312 vgui_macro_report_errors;
00313
00314 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00315 if (debug) vcl_cerr<<"Loading texture...";
00316 glTexImage2D(GL_TEXTURE_2D,
00317 0,
00318 3,
00319 img.width(),
00320 img.height(),
00321 0,
00322 format,
00323 type,
00324 the_pixels);
00325 vgui_macro_report_errors;
00326 }