X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Ftexture2d.cpp;h=baee22eefc56b31f9fe41c44c53a888598c3cbba;hb=e92458a4a0e6191bff549a8b316dbbbd7c56e90f;hp=e8e975926e62d683c9bc9c2f978654e796fc0ac7;hpb=7adcad3b40a03000a82e32db4523761c218309b8;p=libs%2Fgl.git diff --git a/source/texture2d.cpp b/source/texture2d.cpp index e8e97592..baee22ee 100644 --- a/source/texture2d.cpp +++ b/source/texture2d.cpp @@ -1,5 +1,12 @@ -#include -#include +/* $Id$ + +This file is part of libmspgl +Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include "except.h" +#include "ilwrap.h" #include "texture2d.h" using namespace std; @@ -7,109 +14,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 width, sizei height, int border, GLenum fmt, GLenum type, void *data) +void Texture2D::storage(PixelFormat fmt, sizei wd, sizei ht, int brd) { - if(bound!=this) bind(); + 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, width, height, border, fmt, type, data); } -/** -Uploads an image into the texture. -*/ -void Texture2D::image(int level, sizei width, sizei height, 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) { - 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; 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; break; - default: return; - } - - image(level, ifmt, width, height, 0, fmt, type, data); + if(width==0) + throw InvalidState("Texture storage has not been specified"); + + maybe_bind(); + + glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data); } -/** -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::load_image(const string &fn) +{ + Image img; + img.load_file(fn); + + image(img); +} + +void Texture2D::image(const Image &img) +{ + unsigned w=img.get_width(); + unsigned h=img.get_height(); + PixelFormat fmt=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) +{ + Image img; + img.load_lump(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 width=png_get_image_width(pngs, pngi); - unsigned height=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; - } - - png_byte *data=(png_byte *)malloc(width*height*planes); - png_byte *row_ptrs[height]; - for(unsigned i=0; i(tex).storage(fmt, w, h, b); } } // namespace GL