]> Dogcows Code - chaz/yoink/blobdiff - src/moof/image.cc
compression functions; fixed texture seams
[chaz/yoink] / src / moof / image.cc
index f2f0c09294654145b89e068ebc34a0384c8d8ccf..c9c0638dba4adf6561eccdfc9ba941ab00f9f33c 100644 (file)
 
-/*]  Copyright (c) 2009-2010, Charles McGarvey  [**************************
+/*]  Copyright (c) 2009-2011, Charles McGarvey  [*****************************
 **]  All rights reserved.
 *
-* vi:ts=4 sw=4 tw=75
-*
 * Distributable under the terms and conditions of the 2-clause BSD license;
 * see the file COPYING for a complete text of the license.
 *
-**************************************************************************/
-
-#include <cstdio>              // FILE
-#include <cstring>             // strncmp
-
-#include <boost/algorithm/string.hpp>
+*****************************************************************************/
 
+#include <fstream>
+#include <stdexcept>
 #include <png.h>
+
 #include <SDL/SDL.h>
 
+#include <stlplus/portability/file_system.hpp>
+
 #include "backend.hh"
+#include "debug.hh"
 #include "image.hh"
 #include "log.hh"
-#include "manager.hh"
+#include "opengl.hh"
+#include "script.hh"
+#include "video.hh"
 
 
 namespace moof {
 
 
-class image::impl : public manager<impl>
+MOOF_REGISTER_RESOURCE(image, bmp, textures);
+MOOF_REGISTER_RESOURCE(image, png, textures);
+
+
+static int higher_power_of_two(int input)
 {
-public:
+       int value = 2;
+       while (value <= input) value <<= 1;
+       return value;
+}
 
-       explicit impl() :
-               context_(0),
-               pixels_(0) {}
+static void read_from_stream(png_structp context,
+               png_bytep data, png_size_t length)
+{
+       std::istream& stream(*(std::istream*)png_get_io_ptr(context));
+       stream.read((char*)data, length);
+}
 
-       ~impl()
+
+struct texture_attributes
+{
+       texture_attributes() :
+               min_filter(GL_NEAREST),
+               mag_filter(GL_NEAREST),
+               tile_s(1),
+               tile_t(1),
+               wrap_s(GL_CLAMP_TO_EDGE),
+               wrap_t(GL_CLAMP_TO_EDGE) {}
+
+       void init(const std::string& info)
        {
-               SDL_FreeSurface(context_);
-               delete[] pixels_;
+               script script;
+               log::import(script);
+
+               script::slot g = script.globals();
+#define EXPORT_CONSTANT(K) g.set_field(#K, GL_##K)
+               EXPORT_CONSTANT(CLAMP);
+               EXPORT_CONSTANT(CLAMP_TO_EDGE);
+               EXPORT_CONSTANT(REPEAT);
+               EXPORT_CONSTANT(LINEAR);
+               EXPORT_CONSTANT(NEAREST);
+               EXPORT_CONSTANT(LINEAR_MIPMAP_LINEAR);
+               EXPORT_CONSTANT(LINEAR_MIPMAP_NEAREST);
+               EXPORT_CONSTANT(NEAREST_MIPMAP_LINEAR);
+               EXPORT_CONSTANT(NEAREST_MIPMAP_NEAREST);
+#undef export_constant
+
+               if (script.do_string(info) != script::success)
+               {
+                       std::string str;
+                       script[-1].get(str);
+                       log_warning(str);
+               }
+               else
+               {
+                       log_info("loading texture information...");
+
+                       script::slot globals = script.globals();
+                       globals.get(min_filter, "min_filter");
+                       globals.get(mag_filter, "mag_filter");
+                       globals.get(tile_s, "tile_s");
+                       globals.get(tile_t, "tile_t");
+                       globals.get(wrap_s, "wrap_s");
+                       globals.get(wrap_t, "wrap_t");
+               }
        }
 
+       GLuint  min_filter;
+       GLuint  mag_filter;
+       int     tile_s;
+       int     tile_t;
+       GLuint  wrap_s;
+       GLuint  wrap_t;
+};
 
-       void flip()
-       {
-               unsigned char*  pixels = (Uint8*)(context_->pixels);
 
-               unsigned                pitch = context_->pitch;
-               unsigned char   line[pitch];
+static SDL_Surface* load_png(const std::string& path, texture_attributes& attribs)
+{
+       std::ifstream file(path.c_str(), std::ifstream::binary);
+       if (!file.good())
+               throw std::runtime_error("no valid image found at " + path);
+
+       png_byte        signature[8];
+       size_t          bytesRead;
+
+       int             bpp;
+
+       png_byte        colors;
+       png_bytepp      rows;
 
-               int                             yBegin = 0;
-               int                             yEnd = context_->h - 1;
+       png_textp       texts = 0;
+       int             nutext_s;
 
-               if (SDL_MUSTLOCK(context_)) SDL_LockSurface(context_);
-               while (yBegin < yEnd)
+       bytesRead = file.read((char*)signature, sizeof(signature)).gcount();
+       if (bytesRead < sizeof(signature) ||
+               png_sig_cmp(signature, 0, sizeof(signature)) != 0) throw 0;
+
+       struct png
+       {
+               png_structp     context;
+               png_infop       info;
+               png() :
+                       context(png_create_read_struct(PNG_LIBPNG_VER_STRING,
+                                               0, 0, 0)),
+                       info(png_create_info_struct(context))
                {
-                       memcpy(line,                    pixels + pitch * yBegin, pitch);
-                       memcpy(pixels + pitch * yBegin, pixels + pitch * yEnd,   pitch);
-                       memcpy(pixels + pitch * yEnd,   line,                    pitch);
-                       yBegin++;
-                       yEnd--;
+                       if (!context || !info) throw 0;
                }
-               if (SDL_MUSTLOCK(context_)) SDL_UnlockSurface(context_);
-       }
+               ~png()
+               {
+                       png_destroy_read_struct(context ? &context : 0,
+                                       info ? &info : 0, 0);
+               }
+       } png;
+
+       if (setjmp(png_jmpbuf(png.context))) throw 0;
+
+       png_set_read_fn(png.context, (void*)&file, read_from_stream);
+       png_set_sig_bytes(png.context, sizeof(signature));
+       png_read_info(png.context, png.info);
 
-       void set_as_icon() const
+       bpp = png_get_bit_depth(png.context, png.info);
+       colors = png_get_color_type(png.context, png.info);
+       switch (colors)
        {
-               SDL_WM_SetIcon(context_, 0);
+       case PNG_COLOR_TYPE_PALETTE:
+               png_set_palette_to_rgb(png.context);
+               break;
+
+       case PNG_COLOR_TYPE_GRAY:
+               if (bpp < 8) png_set_expand(png.context);
+               break;
+
+       case PNG_COLOR_TYPE_GRAY_ALPHA:
+               png_set_gray_to_rgb(png.context);
+               break;
        }
 
+       if (bpp == 16) png_set_strip_16(png.context);
+
+       png_read_update_info(png.context, png.info);
+
+       bpp = png_get_bit_depth(png.context, png.info);
+       int channels = png_get_channels(png.context, png.info);
+       int depth = bpp * channels;
 
-       void init(const std::string& name, bool flipped = false)
+       // read comments
+       bool texture = false;
+       png_get_text(png.context, png.info, &texts, &nutext_s);
+       for (int i = 0; i < nutext_s; ++i)
        {
-               std::string path(name);
+               if (std::string(texts[i].key) == "X-Yoink-Texture")
+               {
+                       attribs.init(texts[i].text);
+                       texture = true;
+                       break;
+               }
+       }
 
-               FILE* fp = image::open_file(path);
-               if (!fp) return;
+       int width       = png_get_image_width(png.context, png.info);
+       int height      = png_get_image_height(png.context, png.info);
+       int pitch       = png_get_rowbytes(png.context, png.info);
+       char* pixels    = new char[height * pitch];
 
-               png_byte        signature[8];
-               size_t          bytesRead;
+       rows = new png_bytep[height];
+       if (texture)
+       {
+               log_debug("texture detected; loading flipped");
+               for (int i = 0; i < height; ++i)
+               {
+                       rows[height-1-i] = (png_bytep)(pixels +
+                                       i * channels * width);
+               }
+       }
+       else
+       {
+               log_debug("no texture attributes found");
+               for (int i = 0; i < height; ++i)
+               {
+                       rows[i] = (png_bytep)(pixels +
+                                       i * channels * width);
+               }
+       }
 
-               png_infop       pngInfo = 0;
-               png_infop       pngInfoEnd = 0;
-               png_structp pngObj = 0;
+       png_read_image(png.context, rows);
+       delete[] rows;
 
-               int     width;
-               int     height;
-               int     pitch;
-               int bpp;
-               int channels;
+       png_read_end(png.context, 0);
 
-               png_byte        colors;
-               png_bytepp      rows = 0;
+       SDL_Surface* src = SDL_CreateRGBSurfaceFrom
+       (
+               pixels,
+               width,
+               height, 
+               depth,
+               pitch,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
+#else
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
+#endif
+       );
+       if (!src) throw std::runtime_error(SDL_GetError());
+       return src;
+}
 
-               png_textp       texts = 0;
-               int                     nutext_s;
+static SDL_Surface* load_bmp(const std::string& path)
+{
+       return SDL_LoadBMP(path.c_str());
+}
 
-               bytesRead = fread(signature, 1, sizeof(signature), fp);
-               if (bytesRead < sizeof(signature) ||
-                       png_sig_cmp(signature, 0, sizeof(signature)) != 0) goto cleanup;
 
-               pngObj = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
-               if (!pngObj)     goto cleanup;
+#if 0
+static void save_bmp(SDL_Surface* image, const std::string& path)
+{
+       if (SDL_SaveBMP(image, path.c_str()) != 0)
+               throw std::runtime_error(SDL_GetError());
+}
 
-               pngInfo = png_create_info_struct(pngObj);
-               if (!pngInfo)    goto cleanup;
 
-               pngInfoEnd = png_create_info_struct(pngObj);
-               if (!pngInfoEnd) goto cleanup;
+static void destroy_context(SDL_Surface* context)
+{
+       if (context->flags & SDL_PREALLOC) delete[] (char*)context->pixels;
+       SDL_FreeSurface(context);
+}
+#endif
 
-               if (setjmp(png_jmpbuf(pngObj))) goto cleanup;
 
-               png_init_io(pngObj, fp);
-               png_set_sig_bytes(pngObj, sizeof(signature));
-               png_read_info(pngObj, pngInfo);
+image::image(const std::string& path) :
+       pixels_(0),
+       object_(0),
+       min_filter_(GL_NEAREST),
+       mag_filter_(GL_NEAREST),
+       tile_s_(1),
+       tile_t_(1),
+       wrap_s_(GL_CLAMP_TO_EDGE),
+       wrap_t_(GL_CLAMP_TO_EDGE)
+{
+       std::string ext = stlplus::extension_part(path);
 
-               bpp = png_get_bit_depth(pngObj, pngInfo);
-               colors = png_get_color_type(pngObj, pngInfo);
-               switch (colors)
-               {
-                       case PNG_COLOR_TYPE_PALETTE:
-                               png_set_palette_to_rgb(pngObj);
-                               break;
+       SDL_Surface* context = 0;
+       if (ext == "png")
+       {
+               texture_attributes attribs;
+               context = load_png(path, attribs);
+               pixels_ = (char*)context->pixels;
+               width_ = context->w;
+               height_ = context->h;
+               depth_ = 32;
+               pitch_ = context->pitch;
+               channels_ = 4;
+               min_filter_ = attribs.min_filter;
+               mag_filter_ = attribs.mag_filter;
+               tile_s_ = attribs.tile_s;
+               tile_t_ = attribs.tile_t;
+               wrap_s_ = attribs.wrap_s;
+               wrap_t_ = attribs.wrap_t;
+               postprocess();
+       }
+       else if (ext == "bmp")
+       {
+               context = load_bmp(path);
+               pixels_ = (char*)context->pixels;
+               width_ = context->w;
+               height_ = context->h;
+               depth_ = 32;
+               pitch_ = context->pitch;
+               channels_ = 4;
+       }
+       // TODO leaking context
+}
 
-                       case PNG_COLOR_TYPE_GRAY:
-                               if (bpp < 8) png_set_expand(pngObj);
-                               break;
+image::~image()
+{
+       unload_from_gl();
+       delete[] pixels_;
+}
 
-                       case PNG_COLOR_TYPE_GRAY_ALPHA:
-                               png_set_gray_to_rgb(pngObj);
-                               break;
-               }
 
-               if (bpp == 16) png_set_strip_16(pngObj);
+void image::postprocess()
+{
+       if (1 == tile_s_ && 1 == tile_t_) return;
+
+       SDL_Surface* src = SDL_CreateRGBSurfaceFrom
+       (
+               pixels_,
+               width_,
+               height_, 
+               depth_,
+               pitch_,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
+#else
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
+#endif
+       );
+       SDL_Surface* dst = SDL_CreateRGBSurface(
+               SDL_SWSURFACE,
+               higher_power_of_two(width_),
+               higher_power_of_two(height_),
+               depth_,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
+#else
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
+#endif
+       );
+       ASSERT(src && dst);
 
-               png_read_update_info(pngObj, pngInfo);
+       SDL_SetAlpha(src, 0, 128);
+       SDL_SetAlpha(dst, 0, 128);
 
-               bpp = png_get_bit_depth(pngObj, pngInfo);
-               channels = png_get_channels(pngObj, pngInfo);
-               depth_ = bpp * channels;
+       int src_tilew = src->w / tile_s_;
+       int src_tileh = src->h / tile_t_;
+       int dst_tilew = dst->w / tile_s_;
+       int dst_tileh = dst->h / tile_t_;
 
-               if (channels == 3) color_mode_ = GL_RGB;
-               else               color_mode_ = GL_RGBA;
-               
-               // read comments
-               png_get_text(pngObj, pngInfo, &texts, &nutext_s);
-               for (int i = 0; i < nutext_s; ++i)
+       for (int t = 0; t < tile_t_; ++t) for (int s = 0; s < tile_s_; ++s)
+       {
+               SDL_Rect srcrect;
+               SDL_Rect dstrect;
+               srcrect.x = s * src_tilew;
+               srcrect.y = t * src_tileh;
+               srcrect.w = src_tilew;
+               srcrect.h = src_tileh;
+               dstrect.x = s * dst_tilew + (src_tilew / 2);
+               dstrect.y = t * dst_tileh + (src_tileh / 2);
+               log_warning("SRC", srcrect.x, srcrect.y, srcrect.w, srcrect.h);
+               log_warning("DST", dstrect.x, dstrect.y);
+               SDL_BlitSurface(src, &srcrect, dst, &dstrect);
+
+               srcrect.x = s * src_tilew;
+               srcrect.y = t * src_tileh;
+               srcrect.w = 1;
+               srcrect.h = src_tileh;
+               dstrect.y = t * dst_tileh + (src_tileh / 2);
+               for (int x = s * dst_tilew + (src_tilew / 2) - 1; s * dst_tilew <= x; --x)
                {
-                       if (strncmp(texts[i].key, "TextureInfo", 11) == 0)
-                       {
-                               comment_ = texts[i].text;
-                               break;
-                       }
+                       dstrect.x = x;
+                       SDL_BlitSurface(src, &srcrect, dst, &dstrect);
                }
 
-               width  = png_get_image_width(pngObj, pngInfo);
-               height = png_get_image_height(pngObj, pngInfo);
-
-               pitch = png_get_rowbytes(pngObj, pngInfo);
-               pixels_ = new char[width * pitch];
-
-               rows = new png_bytep[height];
-               if (flipped)
+               srcrect.x = (s + 1) * src_tilew - 1;
+               srcrect.y = t * src_tileh;
+               srcrect.w = 1;
+               srcrect.h = src_tileh;
+               dstrect.y = t * dst_tileh + (src_tileh / 2);
+               for (int x = (s + 1) * dst_tilew - (src_tilew / 2); x < (s + 1) * dst_tilew; ++x)
                {
-                       for (int i = 0; i < height; ++i)
-                       {
-                               rows[height - 1 - i] = (png_bytep)(pixels_ +
-                                                                                                  i * channels * width);
-                       }
+                       dstrect.x = x;
+                       SDL_BlitSurface(src, &srcrect, dst, &dstrect);
                }
-               else
+
+               srcrect.x = s * src_tilew;
+               srcrect.y = t * src_tileh;
+               srcrect.w = src_tilew;
+               srcrect.h = 1;
+               dstrect.x = s * dst_tilew + (src_tilew / 2);
+               for (int y = t * dst_tileh + (src_tileh / 2) - 1; t * dst_tileh <= y; --y)
                {
-                       for (int i = 0; i < height; ++i)
-                       {
-                               rows[i] = (png_bytep)(pixels_ + i * channels * width);
-                       }
+                       dstrect.y = y;
+                       SDL_BlitSurface(src, &srcrect, dst, &dstrect);
                }
 
-               png_read_image(pngObj, rows);
-               png_read_end(pngObj, 0);
-
-               context_ = SDL_CreateRGBSurfaceFrom
-               (
-                       pixels_,
-                       width,
-                       height, 
-                       bpp * channels,
-                       pitch,
+               srcrect.x = s * src_tilew;
+               srcrect.y = (t + 1) * src_tileh - 1;
+               srcrect.w = src_tilew;
+               srcrect.h = 1;
+               dstrect.x = s * dst_tilew + (src_tilew / 2);
+               for (int y = (t + 1) * dst_tileh - (src_tileh / 2); y < (t + 1) * dst_tileh; ++y)
+               {
+                       dstrect.y = y;
+                       SDL_BlitSurface(src, &srcrect, dst, &dstrect);
+               }
+       }
+       SDL_FreeSurface(src);
+
+       char* pixels = new char[dst->w * dst->pitch];
+       SDL_Surface* finaldst = SDL_CreateRGBSurfaceFrom
+       (
+               pixels,
+               dst->w,
+               dst->h, 
+               depth_,
+               dst->pitch,
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
-                       0x000000FF,
-                       0x0000FF00,
-                       0x00FF0000,
-                       0xFF000000
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
 #else
-                       0xFF000000,
-                       0x00FF0000,
-                       0x0000FF00,
-                       0x000000FF
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
 #endif
-               );
+       );
+       SDL_BlitSurface(dst, 0, finaldst, 0);
 
-       cleanup:
+       //SDL_SaveBMP(dst, (stlplus::basename_part(path) + ".bmp").c_str());
+       SDL_FreeSurface(dst);
 
-               delete[] rows;
-               png_destroy_read_struct(pngObj     ? &pngObj     : 0,
-                                                               pngInfo    ? &pngInfo    : 0,
-                                                               pngInfoEnd ? &pngInfoEnd : 0);
-               fclose(fp);
-       }
-
-
-       SDL_Surface*    context_;
-       char*                   pixels_;
-
-       unsigned                depth_;
-       GLuint                  color_mode_;
+       width_ = finaldst->w;
+       height_ = finaldst->h;
+       pitch_ = finaldst->pitch;
 
-       std::string             comment_;
-
-private:
-
-       backend                 backend_;
-};
+       SDL_FreeSurface(finaldst);
 
-
-image::image(const std::string& name) :
-       // pass through
-       impl_(image::impl::instance(name)) {}
+       delete[] pixels_;
+       pixels_ = pixels;
+}
 
 
-bool image::is_valid() const
+void image::fix_uv(std::vector<vector2>& p) const
 {
-       return impl_->context_;
+       vector2 mid(SCALAR(0.0), SCALAR(0.0));
+       for (int i = 0; i < p.size(); ++i)
+       {
+               mid[0] += p[i][0];
+               mid[1] += p[i][1];
+       }
+       mid[0] /= p.size();
+       mid[1] /= p.size();
+       mid[0] *= tile_s_;
+       mid[1] *= tile_t_;
+       mid[0] = std::floor(mid[0]);
+       mid[1] = std::floor(mid[1]);
+       log_warning("midpoint:", mid);
+       scalar s = mid[0];
+       scalar t = mid[1];
+
+       scalar  src_width = width_ >> 1;
+       scalar  src_height = height_ >> 1;
+       int     src_tilew = src_width / tile_s_;
+       int     src_tileh = src_height / tile_t_;
+       int     dst_tilew = width_ / tile_s_;
+       int     dst_tileh = height_ / tile_t_;
+
+       for (int i = 0; i < p.size(); ++i)
+       {
+               //scalar s = p[i][0] * src_width;
+               scalar x = s * dst_tilew + (src_tilew / 2) + (p[i][0] * src_width - s * src_tilew);
+               p[i][0] = x / width_;
+               //scalar t = p[i][1] * src_height;
+               scalar y = t * dst_tileh + (src_tileh / 2) + (p[i][1] * src_height - t * src_tileh);;
+               p[i][1] = y / height_;
+       }
 }
 
-int image::width() const
-{
-       return impl_->context_->w;
-}
 
-int image::height() const
+void image::set_as_icon() const
 {
-       return impl_->context_->h;
-}
+       backend backend;
+
+       SDL_Surface* context = SDL_CreateRGBSurfaceFrom
+       (
+               pixels_,
+               width_,
+               height_, 
+               depth_,
+               pitch_,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
+#else
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
+#endif
+       );
 
-unsigned image::depth() const
-{
-       return impl_->depth_;
+       SDL_WM_SetIcon(context, 0);
+       SDL_FreeSurface(context);
 }
 
-unsigned image::pitch() const
+bool image::tile_coordinates(int index, scalar coords[8]) const
 {
-       return impl_->context_->pitch;
+       // make sure the index represents a real tile
+       if (index < 0 && index >= tile_s_ * tile_t_) return false;
+
+       scalar w = 1.0 / scalar(tile_s_);
+       scalar h = 1.0 / scalar(tile_t_);
+
+       coords[0] = scalar(index % tile_s_) * w;
+       coords[1] = (scalar(tile_t_ - 1) - scalar(index / tile_s_)) * h;
+       coords[2] = coords[0] + w;
+       coords[3] = coords[1];
+       coords[4] = coords[2];
+       coords[5] = coords[1] + h;
+       coords[6] = coords[0];
+       coords[7] = coords[5];
+
+       return true;
 }
 
-GLuint image::mode() const
+void image::bind() const
 {
-       return impl_->color_mode_;
-}
+       ASSERT(video::ready() && "should have a video context set");
 
-std::string image::comment() const
-{
-       return impl_->comment_;
+       if (object_ == 0)
+       {
+               upload_to_gl();
+       }
+       if (object_ != global_object_)
+       {
+               glBindTexture(GL_TEXTURE_2D, (GLuint)object_);
+               global_object_ = object_;
+       }
 }
 
-const char* image::pixels() const
+void image::reset_binding()
 {
-       return impl_->pixels_;
-}
+       ASSERT(video::ready() && "should have a video context set");
 
-char* image::pixels()
-{
-       return impl_->pixels_;
+       glBindTexture(GL_TEXTURE_2D, 0);
+       global_object_ = 0;
 }
 
-
-void image::flip()
+/*
+ * Upload the image to GL so that it will be accessible by a much more
+ * manageable handle and hopefully reside in video memory.
+ */
+void image::upload_to_gl() const
 {
-       // pass through
-       impl_->flip();
+       if (object_) return;    // already loaded
+
+       glGenTextures(1, (GLuint*)&object_);
+       glBindTexture(GL_TEXTURE_2D, (GLuint)object_);
+
+       GLuint mode;
+       if (channels_ == 3) mode = GL_RGB;
+       else mode = GL_RGBA;
+       
+       glTexImage2D
+       //gluBuild2DMipmaps
+       (
+               GL_TEXTURE_2D,
+               0,
+               mode,
+               //3,
+               width_,
+               height_,
+               0,
+               mode,
+               GL_UNSIGNED_BYTE,
+               pixels_
+       );
+
+       set_properties();
+
+       // we want to know when the GL context is recreated
+       //dispatcher& dispatcher = dispatcher::global();
+       //new_context_ = dispatcher.add_target("video.newcontext",
+                                               //boost::bind(&image::context_recreated, this));
+       // FIXME this has const issues
 }
 
-void image::set_as_icon() const
+void image::unload_from_gl() const
 {
-       // pass through
-       impl_->set_as_icon();
+       if (object_)
+       {
+               if (object_ == global_object_) global_object_ = 0;
+               glDeleteTextures(1, (GLuint*)&object_);
+               object_ = 0;
+       }
 }
 
-
-bool image::find_path(std::string& name)
+void image::context_recreated()
 {
-       return resource::find_path(name, "images/", "png");
+       object_ = global_object_ = 0;
+       upload_to_gl();
 }
 
-FILE* image::open_file(std::string& name)
+/*
+ * Sets some texture properties such as the filters and external
+ * coordinate behavior.
+ */
+void image::set_properties() const
 {
-       return resource::open_file(name, "images/", "png");
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_);
 }
 
 
+unsigned image::global_object_ = 0;
+
+
 } // namespace moof
 
This page took 0.035375 seconds and 4 git commands to generate.