src/texture.cpp in rays-0.1.12 vs src/texture.cpp in rays-0.1.13

- old
+ new

@@ -1,29 +1,35 @@ -#include "rays/texture.h" +#include "texture.h" +#include <assert.h> #include "rays/exception.h" #include "rays/bitmap.h" -#include "rays/opengl.h" +#include "rays/debug.h" +#include "opengl.h" +#include "color_space.h" #include "frame_buffer.h" namespace Rays { struct Texture::Data { - int id, width, height, width_pow2, height_pow2; + Context context = NULL; + GLuint id = 0; + + int width, height, width_pow2, height_pow2; + ColorSpace color_space; - bool alpha_only, dirty; + bool modified; Data () - : id(-1) { clear(); } ~Data () @@ -31,81 +37,83 @@ clear(); } void clear () { - if (id >= 0) - { - GLuint id_ = id; - glDeleteTextures(1, &id_); - } + delete_texture(); - id = -1; - width = height = width_pow2 = height_pow2 = 0; + width = + height = + width_pow2 = + height_pow2 = 0; color_space = COLORSPACE_UNKNOWN; - alpha_only = dirty = false; + modified = false; } - };// Texture::Data + void delete_texture () + { + if (!has_id()) return; + Context current_context = OpenGL_get_context(); - static void - create_texture ( - Texture::Data* self, const Bitmap* bitmap, GLenum format, GLenum type) - { - if (!self || (bitmap && !*bitmap)) - argument_error(__FILE__, __LINE__); + assert(context); + OpenGL_set_context(context); - GLuint id = 0; - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); - if (glIsTexture(id) == GL_FALSE) - opengl_error(__FILE__, __LINE__, "failed to create texture."); + glDeleteTextures(1, &id); - self->id = id; + OpenGL_set_context(current_context); - //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); + context = NULL; + id = 0; + } - glTexImage2D( - GL_TEXTURE_2D, 0, format, self->width_pow2, self->height_pow2, 0, - format, type, bitmap ? bitmap->pixels() : NULL); + bool has_id () const + { + return context && id > 0; + } - check_error(__FILE__, __LINE__); - } + };// Texture::Data + static int min_pow2 (int num) { int n = 1; while (n < num) n *= 2; return n; } static void - colorspace_for_alphabitmap (ColorSpace* result, ColorSpace cs) + setup_texture (Texture::Data* self, const void* pixels = NULL) { - if (!result || !cs) - argument_error(__FILE__, __LINE__); + assert(self && !self->has_id()); - *result = COLORSPACE_UNKNOWN; + if (self->context) + invalid_state_error(__FILE__, __LINE__); - if (cs.is_float()) - *result = GRAY_float; - else - { - switch (cs.bpc()) - { - 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: rays_error(__FILE__, __LINE__, "invalid bpc."); - } - } + self->context = OpenGL_get_context(); + if (!self->context) + opengl_error(__FILE__, __LINE__); + + glGenTextures(1, &self->id); + glBindTexture(GL_TEXTURE_2D, self->id); + if (glIsTexture(self->id) == GL_FALSE) + opengl_error(__FILE__, __LINE__, "failed to create texture."); + + //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_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//GL_LINEAR); + + GLenum format, type; + ColorSpace_get_gl_format_and_type(&format, &type, self->color_space); + + glTexImage2D( + GL_TEXTURE_2D, 0, format, self->width_pow2, self->height_pow2, 0, + format, type, pixels); + + OpenGL_check_error(__FILE__, __LINE__); } template <int BytesPerPixel> static inline void copy_pixel (uchar* dest, const uchar* src) @@ -139,200 +147,168 @@ template <int BytesPerPixel> static inline void copy_pixels ( size_t width, - uchar* dest, size_t dest_offset, const uchar* src, size_t src_offset) + uchar* dest, size_t dest_stride, const uchar* src, size_t src_stride) { - if (!dest || !src || dest_offset <= 0 || src_offset <= 0) + if (!dest || !src || dest_stride <= 0 || src_stride <= 0) argument_error(__FILE__, __LINE__); while (width--) { copy_pixel<BytesPerPixel>(dest, src); - dest += dest_offset; - src += src_offset; + dest += dest_stride; + src += src_stride; } } static inline void copy_pixels ( size_t Bpp, size_t width, - uchar* dest, size_t dest_offset, const uchar* src, size_t src_offset) + uchar* dest, size_t dest_stride, const uchar* src, size_t src_stride) { switch (Bpp) { - case 1: copy_pixels<1>(width, dest, dest_offset, src, src_offset); break; - case 2: copy_pixels<2>(width, dest, dest_offset, src, src_offset); break; - 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; + case 1: copy_pixels<1>(width, dest, dest_stride, src, src_stride); break; + case 2: copy_pixels<2>(width, dest, dest_stride, src, src_stride); break; + case 3: copy_pixels<3>(width, dest, dest_stride, src, src_stride); break; + case 4: copy_pixels<4>(width, dest, dest_stride, src, src_stride); break; } } static void - copy_bitmap (Bitmap* dest, const Bitmap& src, int src_offset = 0) + copy_bitmap (Bitmap* dest, const Bitmap& src) { - if (!dest || !src || src_offset < 0) + if (!dest || !src) argument_error(__FILE__, __LINE__); + int width = std::min(src.width(), dest->width()); + int height = std::min(src.height(), dest->height()); 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)) - 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); + copy_pixels( + src_Bpp, width, + dest->at<uchar>(0, y), dest_Bpp, + src. at<uchar>(0, y), src_Bpp); } } - static void - setup_texture ( - Texture::Data* self, int width, int height, const ColorSpace& cs, - const Bitmap* bitmap, bool alpha_only) + + Texture::Texture () { - if (!self || width <= 0 || height <= 0 || !cs || (bitmap && !*bitmap)) + } + + Texture::Texture (int width, int height, const ColorSpace& cs) + { + if (width <= 0 || height <= 0 || !cs) argument_error(__FILE__, __LINE__); - GLenum format, type; - cs.get_gl_enums(&format, &type, alpha_only); - - self->clear(); - 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; + self->modified = true; - 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."); - } + setup_texture(self.get()); + } - Bitmap bmp; - if (bitmap) + Texture::Texture (const Bitmap& bitmap) + { + if (!bitmap) + argument_error(__FILE__, __LINE__); + + self->width = bitmap.width(); + self->height = bitmap.height(); + self->width_pow2 = min_pow2(self->width); + self->height_pow2 = min_pow2(self->height); + self->color_space = bitmap.color_space(); + self->modified = true; + + Bitmap bmp = bitmap; + if ( + self->width_pow2 != self->width || + self->height_pow2 != self->height) { - 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."); + bmp = Bitmap(self->width_pow2, self->height_pow2, self->color_space); + if (!bmp) + rays_error(__FILE__, __LINE__); - copy_bitmap(&bmp, *bitmap, alpha_only ? self->color_space.alpha_pos() : 0); - bitmap = &bmp; - } + copy_bitmap(&bmp, bitmap); } - create_texture(self, bitmap, format, type); + setup_texture(self.get(), bmp.pixels()); } - - 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 alpha_only) - { - setup_texture( - self.get(), bitmap.width(), bitmap.height(), bitmap.color_space(), - &bitmap, alpha_only); - } - Texture::~Texture () { } - GLuint - Texture::id () const + int + Texture::width () const { - return self->id; + return self->width; } int - Texture::width () const + Texture::reserved_width () const { - return self->width; + return self->width_pow2; } int Texture::height () const { return self->height; } + int + Texture::reserved_height () const + { + return self->height_pow2; + } + const ColorSpace& Texture::color_space () const { return self->color_space; } - bool - Texture::alpha_only () const + Context + Texture::context () const { - return self->alpha_only; + return self->context; } - float - Texture::s (float x) const + GLuint + Texture::id () const { - return x / (float) self->width_pow2; + return self->id; } - float - Texture::t (float y) const + void + Texture::set_modified (bool modified) { - return y / (float) self->height_pow2; + self->modified = modified; } - float - Texture::s_max () const - { - return s(self->width); - } - - float - Texture::t_max () const - { - return t(self->height); - } - bool - Texture::dirty () const + Texture::modified () const { - return self->dirty; + return self->modified; } - void - Texture::set_dirty (bool b) - { - self->dirty = b; - } - Texture::operator bool () const { - return self->id >= 0 && self->width > 0 && self->height > 0; + return + self->has_id() && + self->width > 0 && + self->height > 0 && + self->color_space; } bool Texture::operator ! () const {