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()
static OpenGLBuffer *scratch_binding;
OpenGLBuffer();
+ OpenGLBuffer(OpenGLBuffer &&);
~OpenGLBuffer();
void allocate();
}
}
+OpenGLFramebuffer::OpenGLFramebuffer(OpenGLFramebuffer &&other):
+ id(other.id),
+ status(other.status)
+{
+ other.id = 0;
+}
+
OpenGLFramebuffer::~OpenGLFramebuffer()
{
if(id)
#define MSP_GL_FRAMEBUFFER_BACKEND_H_
#include <string>
+#include <msp/core/noncopyable.h>
#include "frameformat.h"
namespace Msp {
namespace GL {
-class OpenGLFramebuffer
+class OpenGLFramebuffer: public NonCopyable
{
friend class OpenGLCommands;
friend class OpenGLPipelineState;
mutable unsigned status;
OpenGLFramebuffer(bool);
+ OpenGLFramebuffer(OpenGLFramebuffer &&);
~OpenGLFramebuffer();
void set_system_format(const FrameFormat &);
static unsigned n_clip_distances;
OpenGLPipelineState();
+ OpenGLPipelineState(OpenGLPipelineState &&) { }
~OpenGLPipelineState();
void apply() const;
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<MAX_STAGES; ++i)
#include <map>
#include <string>
#include <vector>
+#include <msp/core/noncopyable.h>
#include "reflectdata.h"
namespace Msp {
namespace GL {
-class OpenGLProgram
+class OpenGLProgram: public NonCopyable
{
friend class OpenGLPipelineState;
std::string debug_name;
OpenGLProgram();
+ OpenGLProgram(OpenGLProgram &&);
~OpenGLProgram();
bool has_stages() const;
}
}
+OpenGLQueryPool::OpenGLQueryPool(OpenGLQueryPool &&other):
+ gl_type(other.gl_type),
+ queries(move(other.queries))
+{
+ other.queries.clear();
+}
+
OpenGLQueryPool::~OpenGLQueryPool()
{
glDeleteQueries(queries.size(), queries.data());
#ifndef MSP_GL_QUERY_BACKEND_H_
#define MSP_GL_QUERY_BACKEND_H_
+#include <msp/core/noncopyable.h>
#include <vector>
namespace Msp {
namespace GL {
-class OpenGLQueryPool
+class OpenGLQueryPool: public NonCopyable
{
friend class OpenGLCommands;
std::vector<unsigned> queries;
OpenGLQueryPool(unsigned);
+ OpenGLQueryPool(OpenGLQueryPool &&);
~OpenGLQueryPool();
void resize();
#ifndef MSP_GL_RENDERER_BACKEND_H_
#define MSP_GL_RENDERER_BACKEND_H_
+#include <msp/core/noncopyable.h>
#include "pipelinestate.h"
namespace Msp {
namespace GL {
-class OpenGLRenderer
+class OpenGLRenderer: public NonCopyable
{
protected:
PipelineState pipeline_state;
glGenSamplers(1, &id);
}
+OpenGLSampler::OpenGLSampler(OpenGLSampler &&other):
+ id(other.id)
+{
+ other.id = 0;
+}
+
OpenGLSampler::~OpenGLSampler()
{
if(id)
#ifndef MSP_GL_SAMPLER_BACKEND_H_
#define MSP_GL_SAMPLER_BACKEND_H_
+#include <msp/core/noncopyable.h>
+
namespace Msp {
namespace GL {
-class OpenGLSampler
+class OpenGLSampler: public NonCopyable
{
friend class OpenGLPipelineState;
unsigned id = 0;
OpenGLSampler();
+ OpenGLSampler(OpenGLSampler &&);
~OpenGLSampler();
static bool check_anisotropic(bool);
}
}
+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)
static OpenGLTexture *scratch_binding;
OpenGLTexture(unsigned);
+ OpenGLTexture(OpenGLTexture &&);
~OpenGLTexture();
void create();
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)
#ifndef MSP_GL_VERTEXSETUP_BACKEND_H_
#define MSP_GL_VERTEXSETUP_BACKEND_H_
+#include <msp/core/noncopyable.h>
+
namespace Msp {
namespace GL {
class VertexArray;
class VertexFormat;
-class OpenGLVertexSetup
+class OpenGLVertexSetup: public NonCopyable
{
friend class OpenGLPipelineState;
unsigned id;
OpenGLVertexSetup();
+ OpenGLVertexSetup(OpenGLVertexSetup &&);
~OpenGLVertexSetup();
static void require_format(const VertexFormat &, bool);
#include "mesh.h"
#include "meshbuilder.h"
+using namespace std;
+
namespace Msp {
namespace GL {
void MeshBuilder::end_()
{
- mesh.add_batch(*batch);
+ mesh.add_batch(move(*batch));
delete batch;
batch = 0;
}
set_index_type(UNSIGNED_SHORT);
}
-Batch::~Batch()
-{
-}
-
void Batch::set_index_type(DataType t)
{
if(t==index_type)
public:
Batch(PrimitiveType);
- ~Batch();
PrimitiveType get_type() const { return prim_type; }
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();
#ifndef MSP_GL_BUFFERABLE_H_
#define MSP_GL_BUFFERABLE_H_
+#include <msp/core/noncopyable.h>
+
namespace Msp {
namespace GL {
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:
/**
mutable bool dirty = false;
Bufferable() = default;
+ Bufferable(Bufferable &&);
public:
virtual ~Bufferable();
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);
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);
}
}
Batch *prev = &batches.back();
- batches.push_back(b);
+ batches.emplace_back(move(b));
if(reallocate)
{
prev = 0;
{
Batch btc(p);
load_sub(btc);
- obj.add_batch(btc);
+ obj.add_batch(move(btc));
}
public:
Mesh() = default;
Mesh(const VertexFormat &);
+ Mesh(Mesh &&);
~Mesh();
/** Sets the vertex format for the mesh. It cannot be changed once set. */
/** 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<Batch> &get_batches() const { return batches; }
#ifndef MSP_GL_QUERY_H_
#define MSP_GL_QUERY_H_
-#include <msp/core/noncopyable.h>
#include "query_backend.h"
namespace Msp {
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;
unsigned levels = 0;
public:
+ Texture2D() = default;
+ Texture2D(Texture2D &&) = default;
virtual ~Texture2D();
/** Sets storage format and dimensions and allocates memory for the texture.
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<char> data;
std::vector<char> data;
unsigned stride = 0;
- VertexArray(const VertexArray &);
- VertexArray &operator=(const VertexArray &);
public:
VertexArray() = default;
#define MSP_GL_INSTANCEARRAY_H_
#include <vector>
+#include <msp/core/noncopyable.h>
#include "programdata.h"
#include "renderable.h"
#include "vertexarray.h"
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<typename 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()
{
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<Vector3> points;
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). */
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)
ProgramData(const ProgramData &);
ProgramData(const ProgramData &, const Program *);
ProgramData &operator=(const ProgramData &);
+ ProgramData(ProgramData &&);
~ProgramData();
private:
texture_stack.reserve(32);
}
-Renderer::~Renderer()
-{
-}
-
void Renderer::begin()
{
if(current_state)
public:
Renderer();
- ~Renderer();
/** Begins rendering, allowing commands to be issued. */
void begin();
#ifndef RENDERTARGET_H_
#define RENDERTARGET_H_
+#include <msp/core/noncopyable.h>
#include "framebuffer.h"
namespace Msp {
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;
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; }
mutable Vector4 frustum_edges[6];
Scene() = default;
-private:
- Scene(const Scene &);
- Scene &operator=(const Scene &);
public:
virtual ~Scene() = default;
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
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;
#ifndef MSP_GL_VIEW_H_
#define MSP_GL_VIEW_H_
+#include <msp/core/noncopyable.h>
#include "framebuffer.h"
namespace Msp {
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;
View() = default;
public:
+ View(View &&);
virtual ~View();
virtual unsigned get_width() const { return get_target().get_width(); }
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)
#define MSP_GL_RESOURCE_H_
#include <cstdint>
+#include <msp/core/noncopyable.h>
#include <msp/io/seekable.h>
namespace Msp {
class ResourceManager;
class Resources;
-class Resource
+class Resource: public NonCopyable
{
public:
class AsyncLoader
void *manager_data = 0;
Resource() = default;
+ Resource(Resource &&);
public:
virtual ~Resource();
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<ManagedResource *>(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);
#include <deque>
#include <cstdint>
#include <msp/core/mutex.h>
+#include <msp/core/noncopyable.h>
#include <msp/core/semaphore.h>
#include <msp/core/thread.h>
#include <msp/datafile/collection.h>
};
-class ResourceManager
+class ResourceManager: public NonCopyable
{
public:
enum LoadingPolicy
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 &);