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;