X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Ftexture2d.cpp;h=197e04df63830269f92a04ed4279636319ef4344;hb=b617c5d7b5283ad260a77f01e42e6170cabbc03d;hp=e8e975926e62d683c9bc9c2f978654e796fc0ac7;hpb=7adcad3b40a03000a82e32db4523761c218309b8;p=libs%2Fgl.git diff --git a/source/texture2d.cpp b/source/texture2d.cpp index e8e97592..197e04df 100644 --- a/source/texture2d.cpp +++ b/source/texture2d.cpp @@ -1,5 +1,11 @@ -#include -#include +/* $Id$ + +This file is part of libmspgl +Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include "except.h" #include "texture2d.h" using namespace std; @@ -7,109 +13,94 @@ using namespace std; namespace Msp { namespace GL { -Texture2D::Texture2D() +Texture2D::Texture2D(): + width(0), + height(0) { - target=GL_TEXTURE_2D; + 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, unsigned wd, unsigned 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, unsigned wd, unsigned 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) +{ + Graphics::Image img; + img.load_file(fn); + + image(img); +} + +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(obj).image(img); +} + +void Texture2D::Loader::raw_data(const string &data) +{ + Texture2D &t2d = static_cast(obj); + 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(obj).storage(fmt, w, h, b); } } // namespace GL