-/*] 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 <cstring> // strncmp
#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 "opengl.hh"
namespace moof {
+MOOF_REGISTER_RESOURCE(image, bmp, textures);
MOOF_REGISTER_RESOURCE(image, png, textures);
-//static int power_of_two(int input)
-//{
- //int value = 1;
-
- //while (value < input)
- //{
- //value <<= 1;
- //}
- //return value;
-//}
-
-unsigned image::global_object_ = 0;
+static int higher_power_of_two(int input)
+{
+ int value = 2;
+ while (value <= input) value <<= 1;
+ return value;
+}
-static void read_from_stream(png_structp context, png_bytep data, png_size_t length)
+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);
}
-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),
- wrap_t_(GL_CLAMP)
+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)
+ {
+ 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;
+};
+
+
+static SDL_Surface* load_png(const std::string& path, texture_attributes& attribs)
{
- std::ifstream file(path.c_str());
- if (!file.good()) throw std::runtime_error("no valid image found at " + path);
+ 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;
+ int bpp;
png_byte colors;
png_bytepp rows = 0;
png_textp texts = 0;
- int nutext_s;
+ int nutext_s;
bytesRead = file.read((char*)signature, sizeof(signature)).gcount();
if (bytesRead < sizeof(signature) ||
struct png
{
- png_structp context;
+ png_structp context;
png_infop info;
png() :
- context(png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)),
+ context(png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ 0, 0, 0)),
info(png_create_info_struct(context))
{
if (!context || !info) throw 0;
~png()
{
png_destroy_read_struct(context ? &context : 0,
- info ? &info : 0, 0);
+ info ? &info : 0, 0);
}
} png;
colors = png_get_color_type(png.context, png.info);
switch (colors)
{
- case PNG_COLOR_TYPE_PALETTE:
- png_set_palette_to_rgb(png.context);
- break;
+ 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:
+ if (bpp < 8) png_set_expand(png.context);
+ break;
- case PNG_COLOR_TYPE_GRAY_ALPHA:
- png_set_gray_to_rgb(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);
depth_ = bpp * channels_;
// read comments
- bool isTexture = false;
+ bool texture = false;
png_get_text(png.context, png.info, &texts, &nutext_s);
for (int i = 0; i < nutext_s; ++i)
{
if (strncmp(texts[i].key, "X-Yoink-Texture", 11) == 0)
{
set_texture_info(texts[i].text);
- isTexture = true;
+ texture = true;
break;
}
}
pixels_ = new char[width_ * pitch_];
rows = new png_bytep[height_];
- if (isTexture)
+ 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_);
+ 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_);
+ rows[i] = (png_bytep)(pixels_ +
+ i * channels_ * width_);
}
}
);
SDL_WM_SetIcon(context, 0);
-
SDL_FreeSurface(context);
}
-
bool image::tile_coordinates(int index, scalar coords[8]) const
{
// make sure the index represents a real tile
return true;
}
-
void image::bind() const
{
ASSERT(video::current() && "should have a video context set");
global_object_ = 0;
}
-
/*
* 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
{
- if (object_)
- {
- // already loaded
- return;
- }
+ 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;
+ else mode = GL_RGBA;
glTexImage2D
//gluBuild2DMipmaps
{
if (object_)
{
- if (object_ == global_object_)
- {
- global_object_ = 0;
- }
-
+ if (object_ == global_object_) global_object_ = 0;
glDeleteTextures(1, (GLuint*)&object_);
object_ = 0;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_);
}
-
void image::set_texture_info(const std::string& info)
{
script script;