X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Ftexture2d.cpp;h=b8f2f26b7076320f78f5ef792dc69a9acd7e1b82;hb=a5797c9babd17673285b3b15c7572c2d8fe1595c;hp=52144e59c397d240444bfb3bb3e98a6bafb3b650;hpb=f098a871fc6dc7b61a5aca5581fa327e4124c036;p=libs%2Fgl.git diff --git a/source/texture2d.cpp b/source/texture2d.cpp index 52144e59..b8f2f26b 100644 --- a/source/texture2d.cpp +++ b/source/texture2d.cpp @@ -5,8 +5,7 @@ Copyright © 2007 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ -#include -#include +#include "except.h" #include "texture2d.h" using namespace std; @@ -14,113 +13,94 @@ using namespace std; namespace Msp { namespace GL { -Texture2D::Texture2D() +Texture2D::Texture2D(): + width(0), + height(0) { target=GL_TEXTURE_2D; + bind(); } -/** -Uploads an image into the texture. Direct wrapper for glTexImage2D. -*/ -void Texture2D::image(int level, int ifmt, sizei wd, sizei ht, int border, GLenum fmt, GLenum type, void *data) +void Texture2D::storage(PixelFormat fmt, sizei wd, sizei ht, int brd) +{ + if(width>0) + throw InvalidState("Texture storage may only be specified once"); + if(wd==0 || ht==0) + throw InvalidParameterValue("Invalid texture dimensions"); + + ifmt=fmt; + width=wd; + height=ht; + border=brd; +} + +void Texture2D::image(int level, PixelFormat fmt, DataType type, const void *data) { + if(width==0) + throw InvalidState("Texture storage has not been specified"); + maybe_bind(); - glTexImage2D(target, level, ifmt, wd, ht, border, fmt, type, data); - width_=wd; - height_=ht; + glTexImage2D(target, level, ifmt, width, height, border, fmt, type, data); } -/** -Uploads an image into the texture, with a simpler interface. -*/ -void Texture2D::image(int level, sizei wd, sizei ht, TextureFormat tfmt, void *data) +void Texture2D::sub_image(int level, int x, int y, sizei wd, sizei ht, PixelFormat fmt, DataType type, const void *data) +{ + if(width==0) + throw InvalidState("Texture storage has not been specified"); + + maybe_bind(); + + glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data); +} + +void Texture2D::load_image(const string &fn) { - int ifmt; - int fmt; - int type; - - switch(tfmt) - { - case LUMINANCE8: ifmt=GL_LUMINANCE; fmt=GL_LUMINANCE; type=GL_UNSIGNED_BYTE; break; - case LUMINANCE8_ALPHA8: ifmt=GL_LUMINANCE_ALPHA; fmt=GL_LUMINANCE_ALPHA; type=GL_UNSIGNED_BYTE; break; - case RGB8: ifmt=GL_RGB; fmt=GL_RGB; type=GL_UNSIGNED_BYTE; break; - case RGBA8: ifmt=GL_RGBA; fmt=GL_RGBA; type=GL_UNSIGNED_INT_8_8_8_8_REV; break; - case BGR8: ifmt=GL_RGB; fmt=GL_BGR; type=GL_UNSIGNED_BYTE; break; - case BGRA8: ifmt=GL_RGBA; fmt=GL_BGRA; type=GL_UNSIGNED_INT_8_8_8_8_REV; break; - default: throw InvalidParameterValue("Invalid texture format"); - } - - image(level, ifmt, wd, ht, 0, fmt, type, data); + Graphics::Image img; + img.load_file(fn); + + image(img); } -/** -Loads an image from a file and uploads it into the texture. Currently assumes -the file to be a PNG image. -*/ -void Texture2D::image(const string &fn) +void Texture2D::image(const Graphics::Image &img) +{ + unsigned w=img.get_width(); + unsigned h=img.get_height(); + PixelFormat fmt=pixelformat_from_graphics(img.get_format()); + if(width==0) + storage(fmt, w, h, 0); + else if(w!=width || h!=height) + throw IncompatibleData("Image does not match texture storage"); + + image(0, fmt, UNSIGNED_BYTE, img.get_data()); +} + + +Texture2D::Loader::Loader(Texture2D &t): + Texture::Loader(t) +{ + add("image_data", &Loader::image_data); + add("raw_data", &Loader::raw_data); + add("storage", &Loader::storage); +} + +void Texture2D::Loader::image_data(const string &data) +{ + Graphics::Image img; + img.load_memory(data.data(), data.size()); + + static_cast(tex).image(img); +} + +void Texture2D::Loader::raw_data(const string &data) +{ + Texture2D &t2d=static_cast(tex);; + t2d.image(0, t2d.ifmt, UNSIGNED_BYTE, data.data()); +} + +void Texture2D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h, unsigned b) { - FILE *file=fopen(fn.c_str(), "r"); - if(!file) throw Exception("Couldn't open "+fn); - - char sig[8]; - fread(sig, 8, 1, file); - if(png_sig_cmp((png_byte *)sig, 0, 8)) - throw Exception("Not a PNG image"); - - png_struct *pngs=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); - png_info *pngi=png_create_info_struct(pngs); - - if(setjmp(png_jmpbuf(pngs))) - { - png_destroy_read_struct(&pngs, &pngi, 0); - fclose(file); - throw Exception("PNG error"); - } - png_init_io(pngs, file); - png_set_sig_bytes(pngs, 8); - - png_read_info(pngs, pngi); - - unsigned wd=png_get_image_width(pngs, pngi); - unsigned ht=png_get_image_height(pngs, pngi); - unsigned depth=png_get_bit_depth(pngs, pngi); - unsigned ctype=png_get_color_type(pngs, pngi); - - if(ctype==PNG_COLOR_TYPE_PALETTE || depth<8) - { - png_destroy_read_struct(&pngs, &pngi, 0); - fclose(file); - throw Exception("Invalid color type or bit depth"); - } - - if(depth==16) - png_set_strip_16(pngs); - - TextureFormat fmt; - unsigned planes; - - switch(ctype) - { - case PNG_COLOR_TYPE_GRAY: fmt=LUMINANCE8; planes=1; break; - case PNG_COLOR_TYPE_GRAY_ALPHA: fmt=LUMINANCE8_ALPHA8; planes=2; break; - case PNG_COLOR_TYPE_RGB: fmt=RGB8; planes=3; break; - case PNG_COLOR_TYPE_RGB_ALPHA: fmt=RGBA8; planes=4; break; - default: throw Exception("Invalid color type"); - } - - png_byte *data=new png_byte[wd*ht*planes]; - png_byte *row_ptrs[ht]; - for(unsigned i=0; i(tex).storage(fmt, w, h, b); } } // namespace GL