--- /dev/null
+#include <algorithm>
+#include <msp/gl/extensions/arb_direct_state_access.h>
+#include <msp/gl/extensions/arb_draw_instanced.h>
+#include <msp/gl/extensions/arb_occlusion_query.h>
+#include <msp/gl/extensions/ext_framebuffer_blit.h>
+#include <msp/gl/extensions/ext_framebuffer_object.h>
+#include <msp/gl/extensions/msp_clear_buffer.h>
+#include "batch.h"
+#include "commands_backend.h"
+#include "error.h"
+#include "framebuffer.h"
+#include "gl.h"
+#include "pipelinestate.h"
+#include "query.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+OpenGLCommands::OpenGLCommands():
+ pipeline_state(0)
+{ }
+
+void OpenGLCommands::use_pipeline(const PipelineState *ps)
+{
+ pipeline_state = ps;
+ if(!pipeline_state)
+ OpenGLPipelineState::clear();
+}
+
+void OpenGLCommands::clear(const ClearValue *values)
+{
+ const Framebuffer *target = pipeline_state->get_framebuffer();
+ if(!target)
+ throw invalid_operation("OpenGLCommands::clear");
+
+ if(!ARB_direct_state_access)
+ {
+ static Require _req(MSP_clear_buffer);
+ pipeline_state->apply();
+ }
+
+ unsigned i = 0;
+ for(FrameAttachment a: target->get_format())
+ {
+ if(get_attach_point(a)==get_attach_point(DEPTH_ATTACHMENT))
+ {
+ if(ARB_direct_state_access)
+ glClearNamedFramebufferfv(target->id, GL_DEPTH, 0, &values->depth_stencil.depth);
+ else
+ glClearBufferfv(GL_DEPTH, 0, &values->depth_stencil.depth);
+ }
+ else if(get_attach_point(a)==get_attach_point(STENCIL_ATTACHMENT))
+ {
+ if(ARB_direct_state_access)
+ glClearNamedFramebufferiv(target->id, GL_STENCIL, 0, &values->depth_stencil.stencil);
+ else
+ glClearBufferiv(GL_STENCIL, 0, &values->depth_stencil.stencil);
+ }
+ else
+ {
+ if(ARB_direct_state_access)
+ glClearNamedFramebufferfv(target->id, GL_COLOR, i++, &values->color.r);
+ else
+ glClearBufferfv(GL_COLOR, i++, &values->color.r);
+ }
+ ++values;
+ }
+}
+
+void OpenGLCommands::draw(const Batch &batch)
+{
+ pipeline_state->apply();
+ void *data_ptr = reinterpret_cast<void *>(batch.get_offset());
+ glDrawElements(batch.gl_prim_type, batch.size(), batch.gl_index_type, data_ptr);
+}
+
+void OpenGLCommands::draw_instanced(const Batch &batch, unsigned count)
+{
+ static Require req(ARB_draw_instanced);
+
+ pipeline_state->apply();
+ void *data_ptr = reinterpret_cast<void *>(batch.get_offset());
+ glDrawElementsInstanced(batch.gl_prim_type, batch.size(), batch.gl_index_type, data_ptr, count);
+}
+
+void OpenGLCommands::resolve_multisample(Framebuffer &target)
+{
+ static Require _req(EXT_framebuffer_blit);
+
+ const Framebuffer *source = pipeline_state->get_framebuffer();
+
+ unsigned width = min(source->get_width(), target.get_width());
+ unsigned height = min(source->get_height(), target.get_height());
+ unsigned buffers = get_gl_buffer_bits(source->get_format())&get_gl_buffer_bits(target.get_format());
+
+ if(ARB_direct_state_access)
+ glBlitNamedFramebuffer(source->id, target.id, 0, 0, width, height, 0, 0, width, height, buffers, GL_NEAREST);
+ else
+ {
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, source->id);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target.id);
+
+ target.refresh();
+
+ glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, buffers, GL_NEAREST);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, source->id);
+ }
+}
+
+void OpenGLCommands::begin_query(const QueryPool &pool, unsigned index)
+{
+ if(index>=pool.queries.size())
+ throw out_of_range("OpenGLCommands::begin_query");
+ glBeginQuery(pool.gl_type, pool.queries[index]);
+}
+
+void OpenGLCommands::end_query(const QueryPool &pool, unsigned)
+{
+ glEndQuery(pool.gl_type);
+}
+
+} // namespace GL
+} // namespace Msp