]> git.tdb.fi Git - libs/gl.git/commitdiff
Deal with nontrivial image configurations
authorMikko Rasa <tdb@tdb.fi>
Fri, 11 Oct 2013 11:51:41 +0000 (14:51 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 11 Oct 2013 11:51:41 +0000 (14:51 +0300)
source/bindable.h
source/pixelformat.cpp
source/pixelformat.h
source/pixelstore.cpp [new file with mode: 0644]
source/pixelstore.h [new file with mode: 0644]
source/texture2d.cpp
source/texture3d.cpp
source/texturecube.cpp

index 76c2fb528b7967839fa606a6c8a076ce190ee525..bde5e85a11752b3a95a07de5187ad174b3c4a50a 100644 (file)
@@ -33,6 +33,36 @@ template<typename T>
 const T *Bindable<T>::cur_obj;
 
 
+/**
+A helper class for Bindables that revert to a default object on unbind.
+*/
+template<typename T>
+class BindableWithDefault: protected Bindable<T>
+{
+protected:
+       BindableWithDefault() { }
+
+public:
+       static const T *current()
+       {
+               if(!Bindable<T>::cur_obj)
+                       Bindable<T>::cur_obj = &default_object();
+               return Bindable<T>::cur_obj;
+       }
+
+       static void unbind()
+       {
+               default_object().bind();
+       }
+
+       static const T &default_object()
+       {
+               static T obj;
+               return obj;
+       }
+};
+
+
 /**
 RAII class for binding things.  Binds the thing upon construction and unbinds
 it upon destruction.  If a null pointer is given, unbinds upon construction and
index 836012f9d0c7cfd294e542bcbb0c10d3cc932c69..26600b33661fca3c7e73729702278f0aa4664feb 100644 (file)
@@ -48,13 +48,27 @@ PixelFormat pixelformat_from_graphics(Graphics::PixelFormat pf)
        case Graphics::LUMINANCE: return LUMINANCE;
        case Graphics::LUMINANCE_ALPHA: return LUMINANCE_ALPHA;
        case Graphics::RGB: return RGB;
+       case Graphics::RGBX:
        case Graphics::RGBA: return RGBA;
        case Graphics::BGR: return BGR;
+       case Graphics::BGRX:
        case Graphics::BGRA: return BGRA;
        default: throw invalid_argument("pixelformat_from_graphics");
        }
 }
 
+PixelFormat storage_pixelformat_from_graphics(Graphics::PixelFormat pf)
+{
+       switch(pf)
+       {
+       case Graphics::RGBX:
+       case Graphics::BGR:
+       case Graphics::BGRX: return RGB;
+       case Graphics::BGRA: return RGBA;
+       default: return pixelformat_from_graphics(pf);
+       }
+}
+
 PixelFormat get_base_pixelformat(PixelFormat pf)
 {
        switch(pf)
@@ -75,6 +89,31 @@ PixelFormat get_base_pixelformat(PixelFormat pf)
        }
 }
 
+unsigned get_component_count(PixelFormat pf)
+{
+       switch(get_base_pixelformat(pf))
+       {
+       case COLOR_INDEX:
+       case STENCIL_INDEX:
+       case DEPTH_COMPONENT:
+       case RED:
+       case GREEN:
+       case BLUE:
+       case LUMINANCE:
+               return 1;
+       case LUMINANCE_ALPHA:
+               return 2;
+       case RGB:
+       case BGR:
+               return 3;
+       case RGBA:
+       case BGRA:
+               return 4;
+       default:
+               throw invalid_argument("get_pixelformat_component_count");
+       }
+}
+
 void require_pixelformat(PixelFormat pf)
 {
        switch(pf)
index 4dabcbb5bfdbdf3d2194eddca4f5910d6b336b2a..c232da1e5876f838cd6db34b9ad496adfb3ae113 100644 (file)
@@ -42,8 +42,10 @@ enum PixelFormat
 void operator>>(const LexicalConverter &, PixelFormat &);
 
 PixelFormat pixelformat_from_graphics(Graphics::PixelFormat);
+PixelFormat storage_pixelformat_from_graphics(Graphics::PixelFormat);
 
 PixelFormat get_base_pixelformat(PixelFormat);
+unsigned get_component_count(PixelFormat);
 
 void require_pixelformat(PixelFormat);
 
diff --git a/source/pixelstore.cpp b/source/pixelstore.cpp
new file mode 100644 (file)
index 0000000..c32cf60
--- /dev/null
@@ -0,0 +1,62 @@
+#include <algorithm>
+#include "gl.h"
+#include "pixelformat.h"
+#include "pixelstore.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+PixelStore::PixelStore():
+       row_length(0),
+       image_height(0),
+       skip_pixels(0),
+       skip_rows(0),
+       skip_images(0),
+       alignment(4)
+{ }
+
+PixelStore PixelStore::from_image(const Graphics::Image &img)
+{
+       PixelStore pstore;
+       unsigned stride = img.get_stride();
+       unsigned ncomp = get_component_count(pixelformat_from_graphics(img.get_format()));
+       pstore.set_canvas_size(img.get_stride()/ncomp, 0);
+       pstore.set_alignment(min(stride&~(stride-1), 8U));
+       return pstore;
+}
+
+void PixelStore::set_canvas_size(unsigned w, unsigned h)
+{
+       row_length = w;
+       image_height = h;
+}
+
+void PixelStore::set_origin(unsigned x, unsigned y, unsigned z)
+{
+       skip_pixels = x;
+       skip_rows = y;
+       skip_images = z;
+}
+
+void PixelStore::set_alignment(unsigned a)
+{
+       alignment = a;
+}
+
+void PixelStore::bind() const
+{
+       if(set_current(this))
+       {
+               glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+               glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image_height);
+               glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
+               glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+               glPixelStorei(GL_UNPACK_SKIP_IMAGES, skip_images);
+               glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+       }
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/pixelstore.h b/source/pixelstore.h
new file mode 100644 (file)
index 0000000..0c43030
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef MSP_GL_PIXELSTORE_H_
+#define MSP_GL_PIXELSTORE_H_
+
+#include <msp/graphics/image.h>
+#include "bindable.h"
+
+namespace Msp {
+namespace GL {
+
+class PixelStore: public BindableWithDefault<PixelStore>
+{
+private:
+       unsigned row_length;
+       unsigned image_height;
+       unsigned skip_pixels;
+       unsigned skip_rows;
+       unsigned skip_images;
+       unsigned alignment;
+
+public:
+       PixelStore();
+
+       static PixelStore from_image(const Graphics::Image &);
+
+       void set_canvas_size(unsigned, unsigned);
+       void set_origin(unsigned, unsigned, unsigned);
+       void set_alignment(unsigned);
+
+       void bind() const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index 0e9b40c6320d0a5514a9bde091abffe5cb131d69..7a9701f5e616f448465c1335f695b871d3d34d04 100644 (file)
@@ -1,6 +1,7 @@
 #include <msp/io/memory.h>
 #include "bindable.h"
 #include "error.h"
+#include "pixelstore.h"
 #include "texture2d.h"
 
 using namespace std;
@@ -81,10 +82,13 @@ void Texture2D::image(const Graphics::Image &img)
        unsigned h = img.get_height();
        PixelFormat fmt = pixelformat_from_graphics(img.get_format());
        if(width==0)
-               storage(fmt, w, h);
+               storage(storage_pixelformat_from_graphics(img.get_format()), w, h);
        else if(w!=width || h!=height)
                throw incompatible_data("Texture2D::image");
 
+       PixelStore pstore = PixelStore::from_image(img);
+       Bind _bind_ps(pstore, true);
+
        image(0, fmt, UNSIGNED_BYTE, img.get_data());
 }
 
index 73c4b817827cfef191e21079a982323a3d87363a..3d322d4b9bd9c14834097c81773c085e9bda7584 100644 (file)
@@ -3,6 +3,7 @@
 #include <msp/graphics/image.h>
 #include "bindable.h"
 #include "error.h"
+#include "pixelstore.h"
 #include "texture3d.h"
 
 using namespace std;
@@ -110,11 +111,14 @@ void Texture3D::load_image(const string &fn, int dp)
 
        PixelFormat fmt = pixelformat_from_graphics(img.get_format());
        if(width==0)
-               storage(fmt, w, h, d);
+               storage(storage_pixelformat_from_graphics(img.get_format()), w, h, d);
        else if(w!=width || h!=height || d!=depth)
                throw incompatible_data("Texture3D::load_image");
 
-       image(0, fmt, UNSIGNED_INT, img.get_data());
+       PixelStore pstore = PixelStore::from_image(img);
+       Bind _bind_ps(pstore, true);
+
+       image(0, fmt, UNSIGNED_BYTE, img.get_data());
 }
 
 void Texture3D::get_level_size(unsigned level, unsigned &w, unsigned &h, unsigned &d)
index eb7448c324ea14c7e82e0dd0da32ba8d9e30ed87..38d99367fe4441d431a7699d08515fc8977ae025 100644 (file)
@@ -3,6 +3,7 @@
 #include <msp/strings/format.h>
 #include "bindable.h"
 #include "error.h"
+#include "pixelstore.h"
 #include "texturecube.h"
 
 using namespace std;
@@ -78,13 +79,16 @@ void TextureCube::image(TextureCubeFace face, const Graphics::Image &img)
        if(size==0)
        {
                if(w==h)
-                       storage(fmt, w);
+                       storage(storage_pixelformat_from_graphics(img.get_format()), w);
                else
                        throw incompatible_data("TextureCube::image");
        }
        else if(w!=size || h!=size)
                throw incompatible_data("TextureCube::image");
 
+       PixelStore pstore = PixelStore::from_image(img);
+       Bind _bind_ps(pstore, true);
+
        image(face, 0, fmt, UNSIGNED_BYTE, img.get_data());
 }