From 55dbeb5e04516699b8415104e346243d5e4c48c9 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 27 Oct 2016 11:13:39 +0300 Subject: [PATCH] Implement 2D array textures --- extensions/arb_geometry_shader4.glext | 1 + extensions/ext_texture_array.glext | 2 + scripts/extgen.py | 6 +++ source/resources.cpp | 2 + source/texture2darray.cpp | 73 +++++++++++++++++++++++++++ source/texture2darray.h | 39 ++++++++++++++ source/texture3d.cpp | 12 ++++- source/texture3d.h | 4 +- 8 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 extensions/ext_texture_array.glext create mode 100644 source/texture2darray.cpp create mode 100644 source/texture2darray.h diff --git a/extensions/arb_geometry_shader4.glext b/extensions/arb_geometry_shader4.glext index 04cfbb3b..801f39b5 100644 --- a/extensions/arb_geometry_shader4.glext +++ b/extensions/arb_geometry_shader4.glext @@ -1,2 +1,3 @@ extension ARB_geometry_shader4 backport none +ignore glFramebufferTextureLayerARB diff --git a/extensions/ext_texture_array.glext b/extensions/ext_texture_array.glext new file mode 100644 index 00000000..7051d8eb --- /dev/null +++ b/extensions/ext_texture_array.glext @@ -0,0 +1,2 @@ +extension EXT_texture_array +backport none diff --git a/scripts/extgen.py b/scripts/extgen.py index fd239d70..45094a4d 100755 --- a/scripts/extgen.py +++ b/scripts/extgen.py @@ -33,6 +33,7 @@ if sys.argv[i].startswith("gl"): target_ext = sys.argv[i] backport_ext = None out_base = None +ignore_things = [] if target_ext.endswith(".glext"): fn = target_ext target_ext = None @@ -49,6 +50,8 @@ if target_ext.endswith(".glext"): secondary.append(parts[1]) elif parts[0]=="backport": backport_ext = parts[1] + elif parts[0]=="ignore": + ignore_things.append(parts[1]) if i+1().base().suffix(".tex2d").suffix(".png").suffix(".jpg").keyword("texture2d").creator(&Resources::create_texture2d); add_type().base().suffix(".tex3d").keyword("texture3d"); add_type().base().suffix(".texcb").keyword("texture_cube"); + add_type().base().suffix(".tex2da").keyword("texture2d_array"); } void Resources::set_default_texture_filter(TextureFilter tf) diff --git a/source/texture2darray.cpp b/source/texture2darray.cpp new file mode 100644 index 00000000..27e0d533 --- /dev/null +++ b/source/texture2darray.cpp @@ -0,0 +1,73 @@ +#include +#include +#include "error.h" +#include "pixelstore.h" +#include "texture2darray.h" + +using namespace std; + +namespace Msp { +namespace GL { + +Texture2DArray::Texture2DArray(): + Texture3D(GL_TEXTURE_2D_ARRAY) +{ + static Require _req(EXT_texture_array); +} + +void Texture2DArray::layer_image(unsigned level, unsigned z, PixelFormat fmt, DataType type, const void *data) +{ + unsigned w = get_width(); + unsigned h = get_height(); + unsigned d = get_depth(); + get_level_size(level, w, h, d); + + sub_image(level, 0, 0, z, w, h, 1, fmt, type, data); +} + +void Texture2DArray::layer_image(unsigned level, unsigned z, const Graphics::Image &img) +{ + if(!get_width()) + throw invalid_operation("Texture2D::layer_image"); + + unsigned w = img.get_width(); + unsigned h = img.get_height(); + PixelFormat fmt = pixelformat_from_graphics(img.get_format()); + if(w!=get_width() || h!=get_height()) + throw incompatible_data("Texture2D::image"); + + PixelStore pstore = PixelStore::from_image(img); + BindRestore _bind_ps(pstore); + + layer_image(level, z, fmt, UNSIGNED_BYTE, img.get_data()); +} + + +Texture2DArray::Loader::Loader(Texture2DArray &t): + DataFile::DerivedObjectLoader(t) +{ + init(); +} + +Texture2DArray::Loader::Loader(Texture2DArray &t, Collection &c): + DataFile::DerivedObjectLoader(t, c) +{ + init(); +} + +void Texture2DArray::Loader::init() +{ + add("external_image", &Loader::external_image); +} + +void Texture2DArray::Loader::external_image(unsigned z, const string &fn) +{ + Graphics::Image img; + RefPtr io = get_collection().open_raw(fn); + img.load_io(*io); + + obj.layer_image(0, z, img); +} + +} // namespace GL +} // namespace Msp diff --git a/source/texture2darray.h b/source/texture2darray.h new file mode 100644 index 00000000..5e0969aa --- /dev/null +++ b/source/texture2darray.h @@ -0,0 +1,39 @@ +#ifndef MSP_GL_TEXTURE2DARRAY_H_ +#define MSP_GL_TEXTURE2DARRAY_H_ + +#include "texture3d.h" + +namespace Msp { +namespace GL { + +/** +An array of two-dimensional textures. It's very much like a 3D texture, with +two important differences: there's no filtering nor mipmapping along the third +dimension. +*/ +class Texture2DArray: public Texture3D +{ +public: + class Loader: public Msp::DataFile::DerivedObjectLoader + { + public: + Loader(Texture2DArray &); + Loader(Texture2DArray &, Collection &); + private: + void init(); + + void external_image(unsigned, const std::string &); + }; + + Texture2DArray(); + + void layer_image(unsigned, unsigned, PixelFormat, DataType, const void *); + void layer_image(unsigned, unsigned, const Graphics::Image &); + + unsigned get_layers() const { return get_depth(); } +}; + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/texture3d.cpp b/source/texture3d.cpp index 8b014aee..8cb26e7f 100644 --- a/source/texture3d.cpp +++ b/source/texture3d.cpp @@ -11,6 +11,15 @@ using namespace std; namespace Msp { namespace GL { +Texture3D::Texture3D(GLenum t): + Texture(t), + ifmt(RGB), + width(0), + height(0), + depth(0), + allocated(0) +{ } + Texture3D::Texture3D(): Texture(GL_TEXTURE_3D), ifmt(RGB), @@ -161,7 +170,8 @@ void Texture3D::get_level_size(unsigned level, unsigned &w, unsigned &h, unsigne { w >>= level; h >>= level; - d >>= level; + if(target!=GL_TEXTURE_2D_ARRAY) + d >>= level; if(!w && (h || d)) w = 1; diff --git a/source/texture3d.h b/source/texture3d.h index 75ae0fe9..55a0e3db 100644 --- a/source/texture3d.h +++ b/source/texture3d.h @@ -33,6 +33,8 @@ private: unsigned depth; unsigned allocated; +protected: + Texture3D(GLenum); public: Texture3D(); @@ -82,7 +84,7 @@ public: unsigned get_width() const { return width; } unsigned get_height() const { return height; } unsigned get_depth() const { return depth; } -private: +protected: void get_level_size(unsigned, unsigned &, unsigned &, unsigned &); public: -- 2.43.0