From: Mikko Rasa Date: Sat, 13 Nov 2021 14:54:53 +0000 (+0200) Subject: Add correct copy and move semantics to most classes X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=e70662d7812464159f2e47f4bebb69d88f89ae93;p=libs%2Fgl.git Add correct copy and move semantics to most classes --- diff --git a/source/backends/opengl/buffer_backend.cpp b/source/backends/opengl/buffer_backend.cpp index a0404e7b..ab78b1b5 100644 --- a/source/backends/opengl/buffer_backend.cpp +++ b/source/backends/opengl/buffer_backend.cpp @@ -24,11 +24,18 @@ OpenGLBuffer::OpenGLBuffer() glGenBuffers(1, &id); } +OpenGLBuffer::OpenGLBuffer(OpenGLBuffer &&other): + id(other.id) +{ + other.id = 0; +} + OpenGLBuffer::~OpenGLBuffer() { if(this==scratch_binding) unbind_scratch(); - glDeleteBuffers(1, &id); + if(id) + glDeleteBuffers(1, &id); } void OpenGLBuffer::allocate() diff --git a/source/backends/opengl/buffer_backend.h b/source/backends/opengl/buffer_backend.h index f435e868..1e5106a5 100644 --- a/source/backends/opengl/buffer_backend.h +++ b/source/backends/opengl/buffer_backend.h @@ -18,6 +18,7 @@ protected: static OpenGLBuffer *scratch_binding; OpenGLBuffer(); + OpenGLBuffer(OpenGLBuffer &&); ~OpenGLBuffer(); void allocate(); diff --git a/source/backends/opengl/framebuffer_backend.cpp b/source/backends/opengl/framebuffer_backend.cpp index db1905d2..de8a9c6e 100644 --- a/source/backends/opengl/framebuffer_backend.cpp +++ b/source/backends/opengl/framebuffer_backend.cpp @@ -32,6 +32,13 @@ OpenGLFramebuffer::OpenGLFramebuffer(bool is_system): } } +OpenGLFramebuffer::OpenGLFramebuffer(OpenGLFramebuffer &&other): + id(other.id), + status(other.status) +{ + other.id = 0; +} + OpenGLFramebuffer::~OpenGLFramebuffer() { if(id) diff --git a/source/backends/opengl/framebuffer_backend.h b/source/backends/opengl/framebuffer_backend.h index 7a7ebfbe..24f43441 100644 --- a/source/backends/opengl/framebuffer_backend.h +++ b/source/backends/opengl/framebuffer_backend.h @@ -2,12 +2,13 @@ #define MSP_GL_FRAMEBUFFER_BACKEND_H_ #include +#include #include "frameformat.h" namespace Msp { namespace GL { -class OpenGLFramebuffer +class OpenGLFramebuffer: public NonCopyable { friend class OpenGLCommands; friend class OpenGLPipelineState; @@ -17,6 +18,7 @@ protected: mutable unsigned status; OpenGLFramebuffer(bool); + OpenGLFramebuffer(OpenGLFramebuffer &&); ~OpenGLFramebuffer(); void set_system_format(const FrameFormat &); diff --git a/source/backends/opengl/pipelinestate_backend.h b/source/backends/opengl/pipelinestate_backend.h index 0b1c4a87..566b819c 100644 --- a/source/backends/opengl/pipelinestate_backend.h +++ b/source/backends/opengl/pipelinestate_backend.h @@ -19,6 +19,7 @@ protected: static unsigned n_clip_distances; OpenGLPipelineState(); + OpenGLPipelineState(OpenGLPipelineState &&) { } ~OpenGLPipelineState(); void apply() const; diff --git a/source/backends/opengl/program_backend.cpp b/source/backends/opengl/program_backend.cpp index 132ad1c0..685f1542 100644 --- a/source/backends/opengl/program_backend.cpp +++ b/source/backends/opengl/program_backend.cpp @@ -46,6 +46,17 @@ OpenGLProgram::OpenGLProgram() id = glCreateProgram(); } +OpenGLProgram::OpenGLProgram(OpenGLProgram &&other): + id(other.id), + linked(other.linked), + uniform_calls(move(other.uniform_calls)), + debug_name(move(other.debug_name)) +{ + move(other.stage_ids, other.stage_ids+MAX_STAGES, stage_ids); + other.id = 0; + fill(other.stage_ids, other.stage_ids+MAX_STAGES, 0); +} + OpenGLProgram::~OpenGLProgram() { for(unsigned i=0; i #include #include +#include #include "reflectdata.h" namespace Msp { namespace GL { -class OpenGLProgram +class OpenGLProgram: public NonCopyable { friend class OpenGLPipelineState; @@ -46,6 +47,7 @@ protected: std::string debug_name; OpenGLProgram(); + OpenGLProgram(OpenGLProgram &&); ~OpenGLProgram(); bool has_stages() const; diff --git a/source/backends/opengl/query_backend.cpp b/source/backends/opengl/query_backend.cpp index 07360ba5..877e888f 100644 --- a/source/backends/opengl/query_backend.cpp +++ b/source/backends/opengl/query_backend.cpp @@ -19,6 +19,13 @@ OpenGLQueryPool::OpenGLQueryPool(unsigned t): } } +OpenGLQueryPool::OpenGLQueryPool(OpenGLQueryPool &&other): + gl_type(other.gl_type), + queries(move(other.queries)) +{ + other.queries.clear(); +} + OpenGLQueryPool::~OpenGLQueryPool() { glDeleteQueries(queries.size(), queries.data()); diff --git a/source/backends/opengl/query_backend.h b/source/backends/opengl/query_backend.h index 7bbbeb66..ccda73b0 100644 --- a/source/backends/opengl/query_backend.h +++ b/source/backends/opengl/query_backend.h @@ -1,12 +1,13 @@ #ifndef MSP_GL_QUERY_BACKEND_H_ #define MSP_GL_QUERY_BACKEND_H_ +#include #include namespace Msp { namespace GL { -class OpenGLQueryPool +class OpenGLQueryPool: public NonCopyable { friend class OpenGLCommands; @@ -15,6 +16,7 @@ protected: std::vector queries; OpenGLQueryPool(unsigned); + OpenGLQueryPool(OpenGLQueryPool &&); ~OpenGLQueryPool(); void resize(); diff --git a/source/backends/opengl/renderer_backend.h b/source/backends/opengl/renderer_backend.h index f6f7334b..4adcce3a 100644 --- a/source/backends/opengl/renderer_backend.h +++ b/source/backends/opengl/renderer_backend.h @@ -1,12 +1,13 @@ #ifndef MSP_GL_RENDERER_BACKEND_H_ #define MSP_GL_RENDERER_BACKEND_H_ +#include #include "pipelinestate.h" namespace Msp { namespace GL { -class OpenGLRenderer +class OpenGLRenderer: public NonCopyable { protected: PipelineState pipeline_state; diff --git a/source/backends/opengl/sampler_backend.cpp b/source/backends/opengl/sampler_backend.cpp index be3f67cb..8198e40f 100644 --- a/source/backends/opengl/sampler_backend.cpp +++ b/source/backends/opengl/sampler_backend.cpp @@ -25,6 +25,12 @@ OpenGLSampler::OpenGLSampler() glGenSamplers(1, &id); } +OpenGLSampler::OpenGLSampler(OpenGLSampler &&other): + id(other.id) +{ + other.id = 0; +} + OpenGLSampler::~OpenGLSampler() { if(id) diff --git a/source/backends/opengl/sampler_backend.h b/source/backends/opengl/sampler_backend.h index 2f644431..f90fbb22 100644 --- a/source/backends/opengl/sampler_backend.h +++ b/source/backends/opengl/sampler_backend.h @@ -1,10 +1,12 @@ #ifndef MSP_GL_SAMPLER_BACKEND_H_ #define MSP_GL_SAMPLER_BACKEND_H_ +#include + namespace Msp { namespace GL { -class OpenGLSampler +class OpenGLSampler: public NonCopyable { friend class OpenGLPipelineState; @@ -12,6 +14,7 @@ protected: unsigned id = 0; OpenGLSampler(); + OpenGLSampler(OpenGLSampler &&); ~OpenGLSampler(); static bool check_anisotropic(bool); diff --git a/source/backends/opengl/texture_backend.cpp b/source/backends/opengl/texture_backend.cpp index ba648677..ebfeb025 100644 --- a/source/backends/opengl/texture_backend.cpp +++ b/source/backends/opengl/texture_backend.cpp @@ -25,6 +25,14 @@ OpenGLTexture::OpenGLTexture(unsigned t): } } +OpenGLTexture::OpenGLTexture(OpenGLTexture &&other): + id(other.id), + target(other.target), + debug_name(move(other.debug_name)) +{ + other.id = 0; +} + OpenGLTexture::~OpenGLTexture() { if(this==scratch_binding) diff --git a/source/backends/opengl/texture_backend.h b/source/backends/opengl/texture_backend.h index 69756206..ecb3056f 100644 --- a/source/backends/opengl/texture_backend.h +++ b/source/backends/opengl/texture_backend.h @@ -19,6 +19,7 @@ protected: static OpenGLTexture *scratch_binding; OpenGLTexture(unsigned); + OpenGLTexture(OpenGLTexture &&); ~OpenGLTexture(); void create(); diff --git a/source/backends/opengl/vertexsetup_backend.cpp b/source/backends/opengl/vertexsetup_backend.cpp index 90189db7..acd14f48 100644 --- a/source/backends/opengl/vertexsetup_backend.cpp +++ b/source/backends/opengl/vertexsetup_backend.cpp @@ -27,9 +27,16 @@ OpenGLVertexSetup::OpenGLVertexSetup() glGenVertexArrays(1, &id); } +OpenGLVertexSetup::OpenGLVertexSetup(OpenGLVertexSetup &&other): + id(other.id) +{ + other.id = 0; +} + OpenGLVertexSetup::~OpenGLVertexSetup() { - glDeleteVertexArrays(1, &id); + if(id) + glDeleteVertexArrays(1, &id); } void OpenGLVertexSetup::require_format(const VertexFormat &fmt, bool instanced) diff --git a/source/backends/opengl/vertexsetup_backend.h b/source/backends/opengl/vertexsetup_backend.h index 954dcc7f..e0dae1bc 100644 --- a/source/backends/opengl/vertexsetup_backend.h +++ b/source/backends/opengl/vertexsetup_backend.h @@ -1,13 +1,15 @@ #ifndef MSP_GL_VERTEXSETUP_BACKEND_H_ #define MSP_GL_VERTEXSETUP_BACKEND_H_ +#include + namespace Msp { namespace GL { class VertexArray; class VertexFormat; -class OpenGLVertexSetup +class OpenGLVertexSetup: public NonCopyable { friend class OpenGLPipelineState; @@ -15,6 +17,7 @@ protected: unsigned id; OpenGLVertexSetup(); + OpenGLVertexSetup(OpenGLVertexSetup &&); ~OpenGLVertexSetup(); static void require_format(const VertexFormat &, bool); diff --git a/source/builders/meshbuilder.cpp b/source/builders/meshbuilder.cpp index 92e2ee06..79770725 100644 --- a/source/builders/meshbuilder.cpp +++ b/source/builders/meshbuilder.cpp @@ -1,6 +1,8 @@ #include "mesh.h" #include "meshbuilder.h" +using namespace std; + namespace Msp { namespace GL { @@ -27,7 +29,7 @@ void MeshBuilder::begin_() void MeshBuilder::end_() { - mesh.add_batch(*batch); + mesh.add_batch(move(*batch)); delete batch; batch = 0; } diff --git a/source/core/batch.cpp b/source/core/batch.cpp index 9639a320..382cfbdb 100644 --- a/source/core/batch.cpp +++ b/source/core/batch.cpp @@ -53,10 +53,6 @@ Batch::Batch(PrimitiveType t): set_index_type(UNSIGNED_SHORT); } -Batch::~Batch() -{ -} - void Batch::set_index_type(DataType t) { if(t==index_type) diff --git a/source/core/batch.h b/source/core/batch.h index 45101d43..dd07adb5 100644 --- a/source/core/batch.h +++ b/source/core/batch.h @@ -40,7 +40,6 @@ private: public: Batch(PrimitiveType); - ~Batch(); PrimitiveType get_type() const { return prim_type; } diff --git a/source/core/bufferable.cpp b/source/core/bufferable.cpp index c312a433..374c4eeb 100644 --- a/source/core/bufferable.cpp +++ b/source/core/bufferable.cpp @@ -8,6 +8,23 @@ using namespace std; namespace Msp { namespace GL { +Bufferable::Bufferable(Bufferable &&other): + buffer(other.buffer), + offset(other.offset), + next_in_buffer(other.next_in_buffer), + prev_in_buffer(other.prev_in_buffer), + location_dirty(other.location_dirty), + dirty(other.dirty) +{ + other.buffer = 0; + other.next_in_buffer = 0; + other.prev_in_buffer = 0; + if(next_in_buffer) + next_in_buffer->prev_in_buffer = this; + if(prev_in_buffer) + prev_in_buffer->next_in_buffer = this; +} + Bufferable::~Bufferable() { unlink_from_buffer(); diff --git a/source/core/bufferable.h b/source/core/bufferable.h index 4a4114d0..8bd3f77f 100644 --- a/source/core/bufferable.h +++ b/source/core/bufferable.h @@ -1,6 +1,8 @@ #ifndef MSP_GL_BUFFERABLE_H_ #define MSP_GL_BUFFERABLE_H_ +#include + namespace Msp { namespace GL { @@ -14,7 +16,7 @@ A dirty flag is provided for derived classes. It should be set when the data in the buffer is considered out of date, and is cleared by Bufferable after uploading fresh data to the buffer. */ -class Bufferable +class Bufferable: public NonCopyable { public: /** @@ -45,6 +47,7 @@ protected: mutable bool dirty = false; Bufferable() = default; + Bufferable(Bufferable &&); public: virtual ~Bufferable(); diff --git a/source/core/mesh.cpp b/source/core/mesh.cpp index b5628eb1..208126ef 100644 --- a/source/core/mesh.cpp +++ b/source/core/mesh.cpp @@ -14,6 +14,22 @@ Mesh::Mesh(const VertexFormat &f) storage(f); } +Mesh::Mesh(Mesh &&other): + Resource(move(other)), + vertices(move(other.vertices)), + batches(move(other.batches)), + vbuf(other.vbuf), + ibuf(other.ibuf), + vtx_setup(move(other.vtx_setup)), + dirty(other.dirty), + disallow_rendering(other.disallow_rendering), + face_winding(other.face_winding), + debug_name(move(other.debug_name)) +{ + other.vbuf = 0; + other.ibuf = 0; +} + Mesh::~Mesh() { set_manager(0); @@ -94,11 +110,11 @@ char *Mesh::modify_vertex(size_t i) return vertices.modify(i); } -void Mesh::add_batch(const Batch &b) +void Mesh::add_batch(Batch &&b) { if(batches.empty()) { - batches.push_back(b); + batches.emplace_back(move(b)); if(ibuf) batches.back().use_buffer(ibuf); } @@ -114,7 +130,7 @@ void Mesh::add_batch(const Batch &b) } Batch *prev = &batches.back(); - batches.push_back(b); + batches.emplace_back(move(b)); if(reallocate) { prev = 0; @@ -281,7 +297,7 @@ void Mesh::Loader::batch(PrimitiveType p) { Batch btc(p); load_sub(btc); - obj.add_batch(btc); + obj.add_batch(move(btc)); } diff --git a/source/core/mesh.h b/source/core/mesh.h index f8e1b6c1..ba2aebc7 100644 --- a/source/core/mesh.h +++ b/source/core/mesh.h @@ -83,6 +83,7 @@ private: public: Mesh() = default; Mesh(const VertexFormat &); + Mesh(Mesh &&); ~Mesh(); /** Sets the vertex format for the mesh. It cannot be changed once set. */ @@ -105,7 +106,7 @@ public: /** Adds a batch to the mesh. It may be combined with the last existing batch if the primitive types are compatible. */ - void add_batch(const Batch &b); + void add_batch(Batch &&b); const std::vector &get_batches() const { return batches; } diff --git a/source/core/query.h b/source/core/query.h index d5b83b96..8f9b17e8 100644 --- a/source/core/query.h +++ b/source/core/query.h @@ -1,7 +1,6 @@ #ifndef MSP_GL_QUERY_H_ #define MSP_GL_QUERY_H_ -#include #include "query_backend.h" namespace Msp { @@ -20,7 +19,7 @@ enum QueryType A collection of query objects, which can be used to gather feedback from the GPU. Semantics of the queries depend on the query type. */ -class QueryPool: public QueryPoolBackend, public Msp::NonCopyable +class QueryPool: public QueryPoolBackend { friend QueryPoolBackend; diff --git a/source/core/texture2d.h b/source/core/texture2d.h index 3a9edae1..fbcee696 100644 --- a/source/core/texture2d.h +++ b/source/core/texture2d.h @@ -34,6 +34,8 @@ private: unsigned levels = 0; public: + Texture2D() = default; + Texture2D(Texture2D &&) = default; virtual ~Texture2D(); /** Sets storage format and dimensions and allocates memory for the texture. diff --git a/source/core/uniformblock.h b/source/core/uniformblock.h index 810afd77..1144158d 100644 --- a/source/core/uniformblock.h +++ b/source/core/uniformblock.h @@ -21,7 +21,7 @@ Applications normally don't need to deal with UniformBlocks directly. They're managed by the ProgramData class, which provides a higher-level interface for setting uniform values. */ -class UniformBlock: public UniformBlockBackend, public NonCopyable, public Bufferable +class UniformBlock: public UniformBlockBackend, public Bufferable { private: std::vector data; diff --git a/source/core/vertexarray.h b/source/core/vertexarray.h index 8e56ee22..575a716e 100644 --- a/source/core/vertexarray.h +++ b/source/core/vertexarray.h @@ -37,8 +37,6 @@ private: std::vector data; unsigned stride = 0; - VertexArray(const VertexArray &); - VertexArray &operator=(const VertexArray &); public: VertexArray() = default; diff --git a/source/render/instancearray.h b/source/render/instancearray.h index d793ce2e..e6f8690c 100644 --- a/source/render/instancearray.h +++ b/source/render/instancearray.h @@ -2,6 +2,7 @@ #define MSP_GL_INSTANCEARRAY_H_ #include +#include #include "programdata.h" #include "renderable.h" #include "vertexarray.h" @@ -24,7 +25,7 @@ elements of the array corresponds to a row of the transform matrix. If the Mesh or Technique of the Object is changed during the lifetime of the InstanceArray, behaviour is undefined. */ -class InstanceArray: public Renderable +class InstanceArray: public Renderable, public NonCopyable { public: template diff --git a/source/render/object.cpp b/source/render/object.cpp index 9a9f759c..e2e95a9b 100644 --- a/source/render/object.cpp +++ b/source/render/object.cpp @@ -27,7 +27,21 @@ Object::Object(const Mesh *m, const Technique *t): set_technique(t); } -// TODO should have copy-c'tor to set watch on lod0 mesh if necessary +Object::Object(const Object &other): + lods(other.lods), + bounding_sphere(other.bounding_sphere) +{ + if(other.lod0_watched) + watch_lod0(); +} + +Object::Object(Object &&other): + lods(move(other.lods)), + bounding_sphere(move(other.bounding_sphere)) +{ + if(other.lod0_watched) + watch_lod0(); +} Object::~Object() { @@ -59,15 +73,20 @@ void Object::set_mesh(unsigned i, const Mesh *m) lod0_watched = false; if(i==0 && m) - if(ResourceManager *rm = m->get_manager()) - { - rm->observe_resource(*m, *this); - lod0_watched = true; - } + watch_lod0(); update_bounding_sphere(); } +void Object::watch_lod0() +{ + if(ResourceManager *rm = lods[0].mesh->get_manager()) + { + rm->observe_resource(*lods[0].mesh, *this); + lod0_watched = true; + } +} + void Object::update_bounding_sphere() { vector points; diff --git a/source/render/object.h b/source/render/object.h index 7d9f1619..dc923267 100644 --- a/source/render/object.h +++ b/source/render/object.h @@ -77,10 +77,13 @@ private: public: Object(); Object(const Mesh *, const Technique *); + Object(const Object &); + Object(Object &&); ~Object(); private: LevelOfDetail &get_lod(unsigned, const char *); + void watch_lod0(); public: /** Sets the mesh for the highest level of detail (index 0). */ diff --git a/source/render/programdata.cpp b/source/render/programdata.cpp index 40eba5e5..cfd2c0f5 100644 --- a/source/render/programdata.cpp +++ b/source/render/programdata.cpp @@ -60,6 +60,22 @@ ProgramData &ProgramData::operator=(const ProgramData &other) return *this; } +ProgramData::ProgramData(ProgramData &&other): + tied_program(other.tied_program), + uniforms(move(other.uniforms)), + uniform_data(move(other.uniform_data)), + generation(other.generation), + blocks(move(other.blocks)), + programs(move(other.programs)), + last_buffer_block(other.last_buffer_block), + buffer(other.buffer), + dirty(other.dirty), + debug_name(move(other.debug_name)) +{ + other.blocks.clear(); + other.buffer = 0; +} + ProgramData::~ProgramData() { for(SharedBlock &b: blocks) diff --git a/source/render/programdata.h b/source/render/programdata.h index 9b8a25cb..53f48a6b 100644 --- a/source/render/programdata.h +++ b/source/render/programdata.h @@ -165,6 +165,7 @@ public: ProgramData(const ProgramData &); ProgramData(const ProgramData &, const Program *); ProgramData &operator=(const ProgramData &); + ProgramData(ProgramData &&); ~ProgramData(); private: diff --git a/source/render/renderer.cpp b/source/render/renderer.cpp index 6c8f1b67..58a56ff2 100644 --- a/source/render/renderer.cpp +++ b/source/render/renderer.cpp @@ -27,10 +27,6 @@ Renderer::Renderer() texture_stack.reserve(32); } -Renderer::~Renderer() -{ -} - void Renderer::begin() { if(current_state) diff --git a/source/render/renderer.h b/source/render/renderer.h index a0b4e75f..b9e795de 100644 --- a/source/render/renderer.h +++ b/source/render/renderer.h @@ -110,7 +110,6 @@ private: public: Renderer(); - ~Renderer(); /** Begins rendering, allowing commands to be issued. */ void begin(); diff --git a/source/render/rendertarget.h b/source/render/rendertarget.h index 98189e78..b7d4af03 100644 --- a/source/render/rendertarget.h +++ b/source/render/rendertarget.h @@ -1,6 +1,7 @@ #ifndef RENDERTARGET_H_ #define RENDERTARGET_H_ +#include #include "framebuffer.h" namespace Msp { @@ -15,7 +16,7 @@ Wraps a Framebuffer and its attachments for easier management. All attachments will be created as 2D or 2D multisample textures, depending on the sample count of the format. */ -class RenderTarget +class RenderTarget: public NonCopyable { private: unsigned width; @@ -25,10 +26,7 @@ private: public: RenderTarget(unsigned, unsigned, const FrameFormat & = (COLOR_ATTACHMENT, DEPTH_ATTACHMENT)); -private: - RenderTarget(const RenderTarget &); - RenderTarget &operator=(const RenderTarget &); -public: + RenderTarget(RenderTarget &&) = default; ~RenderTarget(); unsigned get_width() const { return width; } diff --git a/source/render/scene.h b/source/render/scene.h index 692dcd0d..d07a81da 100644 --- a/source/render/scene.h +++ b/source/render/scene.h @@ -63,9 +63,6 @@ protected: mutable Vector4 frustum_edges[6]; Scene() = default; -private: - Scene(const Scene &); - Scene &operator=(const Scene &); public: virtual ~Scene() = default; diff --git a/source/render/sequence.h b/source/render/sequence.h index b6a8cb34..6ee74986 100644 --- a/source/render/sequence.h +++ b/source/render/sequence.h @@ -34,7 +34,7 @@ format. A Sequence itself is normally rendered with an empty tag. A special "noclear" tag can be used to suppress clearing. */ -class Sequence: public Renderable +class Sequence: public Renderable, public NonCopyable { public: class Step diff --git a/source/render/view.cpp b/source/render/view.cpp index 411c2774..cac82d5d 100644 --- a/source/render/view.cpp +++ b/source/render/view.cpp @@ -11,6 +11,14 @@ View::~View() delete internal_renderer; } +View::View(View &&other): + camera(other.camera), + content(other.content), + internal_renderer(other.internal_renderer) +{ + other.internal_renderer = 0; +} + void View::set_camera(Camera *c) { camera = c; diff --git a/source/render/view.h b/source/render/view.h index bdddb65d..b8a116a6 100644 --- a/source/render/view.h +++ b/source/render/view.h @@ -1,6 +1,7 @@ #ifndef MSP_GL_VIEW_H_ #define MSP_GL_VIEW_H_ +#include #include "framebuffer.h" namespace Msp { @@ -17,7 +18,7 @@ application in some way. The content renderable's render() function is called with an empty tag. A Sequence can be used to specify other tags and add post-processing. */ -class View +class View: public NonCopyable { protected: Camera *camera = 0; @@ -26,6 +27,7 @@ protected: View() = default; public: + View(View &&); virtual ~View(); virtual unsigned get_width() const { return get_target().get_width(); } diff --git a/source/resources/resource.cpp b/source/resources/resource.cpp index 644c55bb..60d611f8 100644 --- a/source/resources/resource.cpp +++ b/source/resources/resource.cpp @@ -10,6 +10,19 @@ Resource::~Resource() manager->remove_resource(*this); } +Resource::Resource(Resource &&other): + manager(other.manager), + manager_data(other.manager_data) +{ + if(manager) + { + manager->move_resource(other, *this); + manager_data = manager->get_data_for_resource(*this); + } + other.manager = 0; + other.manager_data = 0; +} + void Resource::set_manager(ResourceManager *m) { if(manager) diff --git a/source/resources/resource.h b/source/resources/resource.h index d763ac44..2a312e96 100644 --- a/source/resources/resource.h +++ b/source/resources/resource.h @@ -2,6 +2,7 @@ #define MSP_GL_RESOURCE_H_ #include +#include #include namespace Msp { @@ -10,7 +11,7 @@ namespace GL { class ResourceManager; class Resources; -class Resource +class Resource: public NonCopyable { public: class AsyncLoader @@ -29,6 +30,7 @@ protected: void *manager_data = 0; Resource() = default; + Resource(Resource &&); public: virtual ~Resource(); diff --git a/source/resources/resourcemanager.cpp b/source/resources/resourcemanager.cpp index 02a93d94..c72b361c 100644 --- a/source/resources/resourcemanager.cpp +++ b/source/resources/resourcemanager.cpp @@ -63,6 +63,16 @@ void ResourceManager::add_resource(Resource &r) insert_unique(resources, &r, ManagedResource(r)); } +void ResourceManager::move_resource(Resource &from, Resource &to) +{ + if(to.get_manager()!=this || from.get_manager_data()!=to.get_manager_data()) + throw invalid_operation("ResourceManager::move_resource"); + ManagedResource *managed = reinterpret_cast(to.get_manager_data()); + MutexLock lock(map_mutex); + insert_unique(resources, &to, *managed); + resources.erase(&from); +} + const ResourceManager::ManagedResource &ResourceManager::get_managed_resource(const Resource &r) const { MutexLock lock(map_mutex); diff --git a/source/resources/resourcemanager.h b/source/resources/resourcemanager.h index bd87de89..ec1bb3f0 100644 --- a/source/resources/resourcemanager.h +++ b/source/resources/resourcemanager.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -23,7 +24,7 @@ public: }; -class ResourceManager +class ResourceManager: public NonCopyable { public: enum LoadingPolicy @@ -135,6 +136,7 @@ public: void set_max_retain_frames(unsigned); void add_resource(Resource &); + void move_resource(Resource &, Resource &); private: const ManagedResource &get_managed_resource(const Resource &) const; ManagedResource &get_managed_resource(const Resource &);