src/texture.cpp in rays-0.1.6 vs src/texture.cpp in rays-0.1.7

- old
+ new

@@ -1,25 +1,31 @@ #include "rays/texture.h" -#include <rays/bitmap.h> +#include "rays/exception.h" +#include "rays/bitmap.h" +#include "rays/opengl.h" +#include "frame_buffer.h" namespace Rays { struct Texture::Data { - Bitmap bitmap; + int id, width, height, width_pow2, height_pow2; - int id, width, height; + ColorSpace color_space; + bool alpha_only, dirty; + Data () - : id(-1), width(0), height(0) + : id(-1) { + clear(); } ~Data () { clear(); @@ -31,76 +37,59 @@ { GLenum id_ = id; glDeleteTextures(1, &id_); } - bitmap = Bitmap(); id = -1; - width = height = 0; + width = height = width_pow2 = height_pow2 = 0; + color_space = COLORSPACE_UNKNOWN; + alpha_only = dirty = false; } };// Texture::Data - static bool - get_component_type (GLenum* result, ColorSpace cs) + static void + create_texture ( + Texture::Data* self, const Bitmap* bitmap, GLenum format, GLenum type) { - if (!result || !cs) return false; + if (!self || (bitmap && !*bitmap)) + argument_error(__FILE__, __LINE__); - if (cs.is_float()) - *result = GL_FLOAT; - else - { - switch (cs.bpc()) - { - case 8: *result = GL_UNSIGNED_BYTE; break; - case 16: *result = GL_UNSIGNED_SHORT; break; - case 32: *result = GL_UNSIGNED_INT; break; - default: return false; - } - } - return true; - } - - static bool - create_texture (Texture::Data* self, GLenum format) - { - if (!self || !self->bitmap) return false; - - GLenum type; - if (!get_component_type(&type, self->bitmap.color_space())) - return false; - GLuint id = 0; glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); if (glIsTexture(id) == GL_FALSE) - return false; + opengl_error(__FILE__, __LINE__, "failed to create texture."); self->id = id; - glTexImage2D( - GL_TEXTURE_2D, 0, format, self->bitmap.width(), self->bitmap.height(), 0, - format, type, self->bitmap.data()); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//GL_LINEAR); - return true; + glTexImage2D( + GL_TEXTURE_2D, 0, format, self->width_pow2, self->height_pow2, 0, + format, type, bitmap ? bitmap->pixels() : NULL); + + check_error(__FILE__, __LINE__); } static int min_pow2 (int num) { int n = 1; while (n < num) n *= 2; return n; } - static bool + static void colorspace_for_alphabitmap (ColorSpace* result, ColorSpace cs) { - if (!result || !cs) return false; + if (!result || !cs) + argument_error(__FILE__, __LINE__); *result = COLORSPACE_UNKNOWN; if (cs.is_float()) *result = GRAY_float; @@ -110,15 +99,13 @@ { case 8: *result = GRAY_8; break; case 16: *result = GRAY_16; break; case 24: *result = GRAY_24; break; case 32: *result = GRAY_32; break; - default: return false; + default: rays_error(__FILE__, __LINE__, "invalid bpc."); } } - - return true; } template <int BytesPerPixel> static inline void copy_pixel (uchar* dest, const uchar* src) @@ -144,22 +131,22 @@ template <> inline void copy_pixel<4> (uchar* dest, const uchar* src) { - assert(sizeof(ulong) == 4); - *(ulong*) dest = *(ulong*) src; + assert(sizeof(uint) == 4); + *(uint*) dest = *(uint*) src; } template <int BytesPerPixel> static inline void copy_pixels ( size_t width, uchar* dest, size_t dest_offset, const uchar* src, size_t src_offset) { if (!dest || !src || dest_offset <= 0 || src_offset <= 0) - return; + argument_error(__FILE__, __LINE__); while (width--) { copy_pixel<BytesPerPixel>(dest, src); dest += dest_offset; @@ -179,134 +166,99 @@ case 3: copy_pixels<3>(width, dest, dest_offset, src, src_offset); break; case 4: copy_pixels<4>(width, dest, dest_offset, src, src_offset); break; } } - static bool + static void copy_bitmap (Bitmap* dest, const Bitmap& src, int src_offset = 0) { if (!dest || !src || src_offset < 0) - return false; + argument_error(__FILE__, __LINE__); int src_Bpp = src.color_space().Bpp(); int src_Bpc = src.color_space().Bpc(); int dest_Bpp = dest->color_space().Bpp(); if (src_offset >= (src_Bpp / src_Bpc)) - return false; + rays_error(__FILE__, __LINE__, "invalid src_offset."); int width = std::min(src.width(), dest->width()); int height = std::min(src.height(), dest->height()); for (int y = 0; y < height; ++y) { const uchar* s = src. at<uchar>(0, y) + src_offset * src_Bpc; uchar* d = dest->at<uchar>(0, y); copy_pixels(src_Bpp, width, d, dest_Bpp, s, src_Bpp); } - - return true; } - static bool - create_alpha_texture (Texture::Data* self) + static void + setup_texture ( + Texture::Data* self, int width, int height, const ColorSpace& cs, + const Bitmap* bitmap, bool alpha_only) { - if (!self || !self->bitmap) return false; + if (!self || width <= 0 || height <= 0 || !cs || (bitmap && !*bitmap)) + argument_error(__FILE__, __LINE__); - ColorSpace cs = self->bitmap.color_space(); - int width_pow2 = min_pow2(self->width); - int height_pow2 = min_pow2(self->height); + GLenum format, type; + cs.get_gl_enums(&format, &type, alpha_only); - if ( - width_pow2 != self->width || - height_pow2 != self->height || - cs.is_rgb() || - cs.is_bgr()) - { - ColorSpace newcs; - if (!colorspace_for_alphabitmap(&newcs, cs)) - return false; + self->clear(); - Bitmap bmp(width_pow2, height_pow2, newcs); - if (!bmp) return false; + self->width = width; + self->height = height; + self->width_pow2 = min_pow2(width); + self->height_pow2 = min_pow2(height); + self->color_space = cs; + self->alpha_only = alpha_only; + self->dirty = true; - if (!copy_bitmap(&bmp, self->bitmap, cs.alpha_pos())) - return false; - - self->bitmap = bmp; - cs = self->bitmap.color_space(); + if (alpha_only) + { + colorspace_for_alphabitmap(&self->color_space, cs); + if (!self->color_space.is_gray()) + rays_error(__FILE__, __LINE__, "alpha_only takes only gray color-space."); } - if (!self->bitmap.color_space().is_gray()) - return false; - - return create_texture(self, GL_ALPHA); - } - - static bool - create_color_texture (Texture::Data* self) - { - if (!self || !self->bitmap) return false; - - int width_pow2 = min_pow2(self->width); - int height_pow2 = min_pow2(self->height); - - if ( - width_pow2 != self->width || - height_pow2 != self->height) + Bitmap bmp; + if (bitmap) { - Bitmap bmp( - width_pow2, height_pow2, self->bitmap.color_space()); - if (!bmp) return false; + if ( + self->color_space != cs || + self->width_pow2 != self->width || + self->height_pow2 != self->height) + { + bmp = Bitmap(self->width_pow2, self->height_pow2, self->color_space); + if (!bmp) + rays_error(__FILE__, __LINE__, "creating bitmap failed."); - if (!copy_bitmap(&bmp, self->bitmap)) - return false; - - self->bitmap = bmp; + copy_bitmap(&bmp, *bitmap, alpha_only ? self->color_space.alpha_pos() : 0); + bitmap = &bmp; + } } - ColorSpace cs = self->bitmap.color_space(); - - bool alpha = cs.has_alpha(); - if (cs.is_rgb()) - return create_texture(self, alpha ? GL_RGBA : GL_RGB); - else if (cs.is_bgr()) - return create_texture(self, alpha ? GL_BGRA : GL_BGR); - else if (cs.is_gray()) - return create_texture(self, GL_LUMINANCE); - else - return false; + create_texture(self, bitmap, format, type); } - static bool - setup_texture ( - Texture::Data* self, const Bitmap& bitmap, bool alphaonly = false) - { - if (!self || !bitmap) return false; - self->clear(); - - self->bitmap = bitmap; - if (!self->bitmap) return false; - - self->width = self->bitmap.width(); - self->height = self->bitmap.height(); - - if (alphaonly) - return create_alpha_texture(self); - else - return create_color_texture(self); + Texture::Texture () + { } - - Texture::Texture () + Texture::Texture (int width, int height, const ColorSpace& cs, bool alpha_only) { + setup_texture( + self.get(), width, height, cs, + NULL, alpha_only); } - Texture::Texture (const Bitmap& bitmap, bool alphaonly) + Texture::Texture (const Bitmap& bitmap, bool alpha_only) { - setup_texture(self.get(), bitmap, alphaonly); + setup_texture( + self.get(), bitmap.width(), bitmap.height(), bitmap.color_space(), + &bitmap, alpha_only); } Texture::~Texture () { } @@ -327,20 +279,32 @@ Texture::height () const { return self->height; } + const ColorSpace& + Texture::color_space () const + { + return self->color_space; + } + + bool + Texture::alpha_only () const + { + return self->alpha_only; + } + float Texture::s (float x) const { - return x / (float) self->bitmap.width(); + return x / (float) self->width_pow2; } float Texture::t (float y) const { - return y / (float) self->bitmap.height(); + return y / (float) self->height_pow2; } float Texture::s_max () const { @@ -351,13 +315,19 @@ Texture::t_max () const { return t(self->height); } - const Bitmap& - Texture::bitmap () const + bool + Texture::dirty () const { - return self->bitmap; + return self->dirty; + } + + void + Texture::set_dirty (bool b) + { + self->dirty = b; } Texture::operator bool () const { return self->id >= 0 && self->width > 0 && self->height > 0;