From 9d696772b2194b67d8e3e4da11169900eab58c0d Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 23 Aug 2014 19:12:48 +0300 Subject: [PATCH] Enable resource management on Texture2D --- source/resources.cpp | 11 ++++-- source/texture.cpp | 15 +++++-- source/texture.h | 7 ++-- source/texture1d.h | 4 ++ source/texture2d.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++-- source/texture2d.h | 13 +++++- source/texture3d.h | 4 ++ source/texturecube.h | 3 ++ 8 files changed, 137 insertions(+), 14 deletions(-) diff --git a/source/resources.cpp b/source/resources.cpp index d1fd371c..79c5e85f 100644 --- a/source/resources.cpp +++ b/source/resources.cpp @@ -62,9 +62,10 @@ Texture2D *Resources::create_texture2d(const string &name) if(RefPtr io = open_from_sources(name)) { Graphics::Image image; - image.load_io(*io); + if(!resource_manager) + image.load_io(*io); - RefPtr tex = new GL::Texture2D; + RefPtr tex = new GL::Texture2D(resource_manager); if(default_tex_filter==NEAREST_MIPMAP_NEAREST || default_tex_filter==NEAREST_MIPMAP_LINEAR || default_tex_filter==LINEAR_MIPMAP_NEAREST || default_tex_filter==LINEAR_MIPMAP_LINEAR) @@ -76,7 +77,11 @@ Texture2D *Resources::create_texture2d(const string &name) tex->set_mag_filter(default_tex_filter); tex->set_min_filter(default_tex_filter); - tex->image(image, srgb_conversion); + // TODO Somehow pass the srgb flag if a resource manager is in use + if(resource_manager) + resource_manager->set_resource_location(*tex, *this, name); + else + tex->image(image, srgb_conversion); return tex.release(); } diff --git a/source/texture.cpp b/source/texture.cpp index d738bb36..a23e57c7 100644 --- a/source/texture.cpp +++ b/source/texture.cpp @@ -2,6 +2,7 @@ #include #include #include "error.h" +#include "resourcemanager.h" #include "resources.h" #include "texture.h" #include "texunit.h" @@ -43,7 +44,8 @@ void operator>>(const LexicalConverter &c, TextureWrap &tw) } -Texture::Texture(GLenum t): +Texture::Texture(GLenum t, ResourceManager *m): + id(0), target(t), min_filter(NEAREST_MIPMAP_LINEAR), mag_filter(LINEAR), @@ -55,12 +57,16 @@ Texture::Texture(GLenum t): cmp_func(LEQUAL), dirty_params(0) { - glGenTextures(1, &id); + if(m) + set_manager(m); + else + glGenTextures(1, &id); } Texture::~Texture() { - glDeleteTextures(1, &id); + if(id) + glDeleteTextures(1, &id); } void Texture::update_parameter(int mask) const @@ -172,6 +178,9 @@ void Texture::set_compare_func(Predicate f) void Texture::bind_to(unsigned i) const { + if(!id) + manager->load_resource(*this); + TexUnit &unit = TexUnit::get_unit(i); const Texture *cur = unit.get_texture(); if(unit.set_texture(this)) diff --git a/source/texture.h b/source/texture.h index 477eaca3..5566dccb 100644 --- a/source/texture.h +++ b/source/texture.h @@ -4,12 +4,11 @@ #include #include "gl.h" #include "predicate.h" +#include "resource.h" namespace Msp { namespace GL { -class Resources; - enum TextureFilter { /// No filtering @@ -65,7 +64,7 @@ texture to be usable. If texture coordinates fall outside of the principal range of the texture, wrapping is applied. The default for all directions is REPEAT. */ -class Texture +class Texture: public Resource { protected: class Loader: public DataFile::CollectionObjectLoader @@ -116,7 +115,7 @@ protected: Predicate cmp_func; mutable int dirty_params; - Texture(GLenum); + Texture(GLenum, ResourceManager * = 0); Texture(const Texture &); Texture &operator=(const Texture &); public: diff --git a/source/texture1d.h b/source/texture1d.h index 9957eeb4..b4cf0d0b 100644 --- a/source/texture1d.h +++ b/source/texture1d.h @@ -25,6 +25,10 @@ public: private: unsigned get_level_size(unsigned); + +public: + virtual AsyncLoader *load(IO::Seekable &) { return 0; } + virtual void unload() { } }; } // namespace GL diff --git a/source/texture2d.cpp b/source/texture2d.cpp index 96da77d1..f36cadae 100644 --- a/source/texture2d.cpp +++ b/source/texture2d.cpp @@ -1,5 +1,6 @@ #include #include "bindable.h" +#include "buffer.h" #include "error.h" #include "pixelstore.h" #include "resources.h" @@ -10,8 +11,27 @@ using namespace std; namespace Msp { namespace GL { -Texture2D::Texture2D(): - Texture(GL_TEXTURE_2D), +class Texture2D::AsyncLoader: public Resource::AsyncLoader +{ +private: + Texture2D &texture; + IO::Seekable &io; + Buffer pixel_buffer; + char *mapped_address; + Graphics::Image image; + unsigned n_bytes; + int phase; + +public: + AsyncLoader(Texture2D &, IO::Seekable &); + + virtual bool needs_sync() const; + virtual bool process(); +}; + + +Texture2D::Texture2D(ResourceManager *m): + Texture(GL_TEXTURE_2D, m), width(0), height(0), allocated(0) @@ -78,6 +98,11 @@ void Texture2D::load_image(const string &fn, bool srgb) } void Texture2D::image(const Graphics::Image &img, bool srgb) +{ + image(img, srgb, false); +} + +void Texture2D::image(const Graphics::Image &img, bool srgb, bool from_buffer) { unsigned w = img.get_width(); unsigned h = img.get_height(); @@ -95,7 +120,7 @@ void Texture2D::image(const Graphics::Image &img, bool srgb) PixelStore pstore = PixelStore::from_image(img); BindRestore _bind_ps(pstore); - image(0, fmt, UNSIGNED_BYTE, img.get_data()); + image(0, fmt, UNSIGNED_BYTE, from_buffer ? 0 : img.get_data()); } void Texture2D::get_level_size(unsigned level, unsigned &w, unsigned &h) @@ -109,6 +134,17 @@ void Texture2D::get_level_size(unsigned level, unsigned &w, unsigned &h) h = 1; } +Resource::AsyncLoader *Texture2D::load(IO::Seekable &io) +{ + return new AsyncLoader(*this, io); +} + +void Texture2D::unload() +{ + glDeleteTextures(1, &id); + id = 0; +} + Texture2D::Loader::Loader(Texture2D &t): DataFile::DerivedObjectLoader(t) @@ -156,5 +192,57 @@ void Texture2D::Loader::storage_b(PixelFormat fmt, unsigned w, unsigned h, unsig storage(fmt, w, h); } + +Texture2D::AsyncLoader::AsyncLoader(Texture2D &t, IO::Seekable &i): + texture(t), + io(i), + pixel_buffer(PIXEL_UNPACK_BUFFER), + mapped_address(0), + phase(0) +{ + if(!texture.id) + glGenTextures(1, &texture.id); +} + +bool Texture2D::AsyncLoader::needs_sync() const +{ + return phase%2; +} + +bool Texture2D::AsyncLoader::process() +{ + if(phase==0) + { + /* TODO Enhance the ImageLoader system so that the image can be loaded + directly to the buffer */ + image.load_io(io); + n_bytes = image.get_stride()*image.get_height(); + } + else if(phase==1) + { + pixel_buffer.data(n_bytes, 0); + mapped_address = reinterpret_cast(pixel_buffer.map(WRITE_ONLY)); + } + else if(phase==2) + { + const char *data = reinterpret_cast(image.get_data()); + copy(data, data+n_bytes, mapped_address); + } + else if(phase==3) + { + Bind _bind_buf(pixel_buffer, PIXEL_UNPACK_BUFFER); + if(!pixel_buffer.unmap()) + { + phase = 1; + return false; + } + + texture.image(image, false, true); + } + + ++phase; + return phase>3; +} + } // namespace GL } // namespace Msp diff --git a/source/texture2d.h b/source/texture2d.h index 639d47a6..a37e2a4d 100644 --- a/source/texture2d.h +++ b/source/texture2d.h @@ -5,6 +5,7 @@ #include #include "datatype.h" #include "pixelformat.h" +#include "resource.h" #include "texture.h" namespace Msp { @@ -33,13 +34,15 @@ public: }; private: + class AsyncLoader; + PixelFormat ifmt; unsigned width; unsigned height; unsigned allocated; public: - Texture2D(); + Texture2D(ResourceManager * = 0); /** Defines storage structure for the texture. Must be called before an image can be uploaded. Once storage is defined, it can't be changed. */ @@ -71,11 +74,19 @@ public: format will be used. */ void image(const Graphics::Image &, bool srgb = false); +private: + void image(const Graphics::Image &, bool, bool); + +public: unsigned get_width() const { return width; } unsigned get_height() const { return height; } private: void get_level_size(unsigned, unsigned &, unsigned &); + +public: + virtual Resource::AsyncLoader *load(IO::Seekable &); + virtual void unload(); }; } // namespace GL diff --git a/source/texture3d.h b/source/texture3d.h index 25c96c5c..6c087a2d 100644 --- a/source/texture3d.h +++ b/source/texture3d.h @@ -60,6 +60,10 @@ public: unsigned get_depth() const { return depth; } private: void get_level_size(unsigned, unsigned &, unsigned &, unsigned &); + +public: + virtual AsyncLoader *load(IO::Seekable &) { return 0; } + virtual void unload() { } }; } // namespace GL diff --git a/source/texturecube.h b/source/texturecube.h index 077b58ac..1c0d6724 100644 --- a/source/texturecube.h +++ b/source/texturecube.h @@ -102,6 +102,9 @@ public: /** Returns a vector pointing to the center a texel. */ Vector3 get_texel_direction(TextureCubeFace, unsigned, unsigned); + + virtual AsyncLoader *load(IO::Seekable &) { return 0; } + virtual void unload() { } }; void operator>>(const LexicalConverter &, TextureCubeFace &); -- 2.43.0