]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/opengl/commands_backend.cpp
Move all OpenGL-specific code to a separate directory
[libs/gl.git] / source / backends / opengl / commands_backend.cpp
diff --git a/source/backends/opengl/commands_backend.cpp b/source/backends/opengl/commands_backend.cpp
new file mode 100644 (file)
index 0000000..fd66b99
--- /dev/null
@@ -0,0 +1,126 @@
+#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