]> git.sesse.net Git - casparcg/blobdiff - core/mixer/gpu/ogl_device.cpp
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / core / mixer / gpu / ogl_device.cpp
index d771df013d11b81f5f42dadd3623940157274515..584038fbc58eac6e0b193b63340f589b58e461b4 100644 (file)
@@ -35,6 +35,8 @@
 #include <common/assert.h>\r
 #include <boost/foreach.hpp>\r
 \r
+#include <asmlib.h>\r
+\r
 #include <gl/glew.h>\r
 \r
 namespace caspar { namespace core {\r
@@ -111,14 +113,25 @@ safe_ptr<device_buffer> ogl_device::allocate_device_buffer(int width, int height
        return make_safe_ptr(buffer);\r
 }\r
                                \r
-safe_ptr<device_buffer> ogl_device::create_device_buffer(int width, int height, int stride)\r
+safe_ptr<device_buffer> ogl_device::create_device_buffer(int width, int height, int stride, bool zero)\r
 {\r
        CASPAR_VERIFY(stride > 0 && stride < 5);\r
        CASPAR_VERIFY(width > 0 && height > 0);\r
        auto& pool = device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
        std::shared_ptr<device_buffer> buffer;\r
-       if(!pool->items.try_pop(buffer))                \r
-               buffer = executor_.invoke([&]{return allocate_device_buffer(width, height, stride);}, high_priority);                   \r
+               \r
+       if(!pool->items.try_pop(buffer))                        \r
+               buffer =  executor_.invoke([&]{return allocate_device_buffer(width, height, stride);});\r
+\r
+       if(zero)\r
+       {               \r
+               executor_.invoke([&]\r
+               {\r
+                       scoped_state scope(*this);\r
+                       attach(*buffer);\r
+                       glClear(GL_COLOR_BUFFER_BIT);\r
+               }, high_priority);      \r
+       }               \r
        \r
        //++pool->usage_count;\r
 \r
@@ -234,15 +247,10 @@ void ogl_device::flush()
        //}\r
 }\r
 \r
-void ogl_device::yield()\r
+bool ogl_device::yield()\r
 {\r
-       push_state();\r
-       auto restore_state = make_scope_guard([&]\r
-       {\r
-               pop_state();\r
-       });\r
-       \r
-       executor_.yield();\r
+       scoped_state scope(*this);\r
+       return executor_.yield();\r
 }\r
 \r
 boost::unique_future<void> ogl_device::gc()\r
@@ -289,21 +297,25 @@ void ogl_device::push_state()
        state_stack_.push(state_);\r
 }\r
 \r
-void ogl_device::pop_state()\r
+ogl_device::state ogl_device::pop_state()\r
 {\r
-       if(state_stack_.size() == 1)\r
+       if(state_stack_.size() <= 1)\r
                BOOST_THROW_EXCEPTION(invalid_operation());\r
 \r
+       auto prev_state = state_stack_.top();\r
        state_stack_.pop();\r
        auto new_state = state_stack_.top();\r
-       viewport(new_state.viewport[0], new_state.viewport[1], new_state.viewport[2], new_state.viewport[3]);\r
-       scissor(new_state.scissor[0], new_state.scissor[1], new_state.scissor[2], new_state.scissor[3]);\r
-       stipple_pattern(new_state.pattern.data());\r
-       blend_func(new_state.blend_func[0], new_state.blend_func[1], new_state.blend_func[2], new_state.blend_func[3]);\r
+       \r
+       viewport(new_state.viewport);\r
+       scissor(new_state.scissor);\r
+       stipple_pattern(new_state.pattern);\r
+       blend_func(new_state.blend_func);\r
        attach(new_state.attached_texture);\r
        use(new_state.active_shader);\r
        for(int n = 0; n < 16; ++n)\r
                bind(new_state.binded_textures[n], n);\r
+\r
+       return prev_state;\r
 }\r
 \r
 void ogl_device::enable(GLenum cap)\r
@@ -326,9 +338,8 @@ void ogl_device::disable(GLenum cap)
        }\r
 }\r
 \r
-void ogl_device::viewport(int x, int y, int width, int height)\r
+void ogl_device::viewport(const std::array<GLint, 4>& viewport)\r
 {\r
-       std::array<int, 4> viewport = {{x, y, width, height}};\r
        if(viewport != state_.viewport)\r
        {               \r
                glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);\r
@@ -336,13 +347,17 @@ void ogl_device::viewport(int x, int y, int width, int height)
        }\r
 }\r
 \r
-void ogl_device::scissor(int x, int y, int width, int height)\r
+void ogl_device::viewport(int x, int y, int width, int height)\r
+{\r
+       std::array<int, 4> ar = {{x, y, width, height}};\r
+       viewport(ar);\r
+}\r
+\r
+void ogl_device::scissor(const std::array<GLint, 4>& scissor)\r
 {\r
-       std::array<int, 4> scissor = {{x, y, width, height}};\r
        if(scissor != state_.scissor)\r
        {               \r
-               state def_state_;\r
-               if(scissor == def_state_.scissor)\r
+               if(scissor == state().scissor)\r
                {\r
                        disable(GL_SCISSOR_TEST);\r
                }\r
@@ -355,21 +370,23 @@ void ogl_device::scissor(int x, int y, int width, int height)
        }\r
 }\r
 \r
-void ogl_device::stipple_pattern(const GLubyte* pattern)\r
+void ogl_device::scissor(int x, int y, int width, int height)\r
 {\r
-       std::array<GLubyte, 32*32> pattern2;\r
-       memcpy(pattern2.data(), pattern, 32*32);\r
+       std::array<int, 4> ar = {{x, y, width, height}};\r
+       scissor(ar);\r
+}\r
 \r
-       if(pattern2 != state_.pattern)\r
+void ogl_device::stipple_pattern(const std::array<GLubyte, 32*32>& pattern)\r
+{\r
+       if(pattern != state_.pattern)\r
        {\r
-               state def_state_;\r
-               if(pattern2 == def_state_.pattern)\r
+               if(pattern == state().pattern)\r
                        disable(GL_POLYGON_STIPPLE);\r
                else\r
                {\r
                        enable(GL_POLYGON_STIPPLE);\r
-                       glPolygonStipple(pattern2.data());\r
-                       state_.pattern = pattern2;\r
+                       glPolygonStipple(pattern.data());\r
+                       state_.pattern = pattern;\r
                }\r
        }\r
 }\r
@@ -399,6 +416,33 @@ void ogl_device::bind(GLint id, int index)
        }\r
 }\r
 \r
+void ogl_device::blend_func(const std::array<GLint, 4>& func)\r
+{\r
+       if(state_.blend_func != func)\r
+       {\r
+               state def_state_;\r
+               if(func == def_state_.blend_func)\r
+                       disable(GL_BLEND);\r
+               else\r
+               {\r
+                       enable(GL_BLEND);\r
+                       GL(glBlendFuncSeparate(func[0], func[1], func[2], func[3]));\r
+                       state_.blend_func = func;\r
+               }\r
+       }\r
+}\r
+\r
+void ogl_device::blend_func(int c1, int c2, int a1, int a2)\r
+{\r
+       std::array<int, 4> ar = {c1, c2, a1, a2};\r
+       blend_func(ar);\r
+}\r
+\r
+void ogl_device::blend_func(int c1, int c2)\r
+{\r
+       blend_func(c1, c2, c1, c2);\r
+}\r
+\r
 void ogl_device::bind(const device_buffer& texture, int index)\r
 {\r
        //while(true)\r
@@ -412,17 +456,6 @@ void ogl_device::bind(const device_buffer& texture, int index)
        bind(texture.id(), index);\r
 }\r
 \r
-void ogl_device::clear(device_buffer& texture)\r
-{      \r
-       auto prev = state_.attached_texture;\r
-       attach(texture);\r
-       auto restore_attachement = make_scope_guard([&]\r
-       {\r
-               attach(prev);\r
-       });\r
-\r
-       GL(glClear(GL_COLOR_BUFFER_BIT));\r
-}\r
 \r
 void ogl_device::use(GLint id)\r
 {\r
@@ -438,46 +471,23 @@ void ogl_device::use(const shader& shader)
        use(shader.id());\r
 }\r
 \r
-void ogl_device::blend_func(int c1, int c2, int a1, int a2)\r
-{\r
-       std::array<int, 4> func = {c1, c2, a1, a2};\r
-\r
-       if(state_.blend_func != func)\r
-       {\r
-               state def_state_;\r
-               if(func == def_state_.blend_func)\r
-                       disable(GL_BLEND);\r
-               else\r
-               {\r
-                       enable(GL_BLEND);\r
-                       GL(glBlendFuncSeparate(c1, c2, a1, a2));\r
-                       state_.blend_func = func;\r
-               }\r
-       }\r
-}\r
-\r
-void ogl_device::blend_func(int c1, int c2)\r
-{\r
-       blend_func(c1, c2, c1, c2);\r
-}\r
 \r
 boost::unique_future<safe_ptr<host_buffer>> ogl_device::transfer(const safe_ptr<device_buffer>& source)\r
 {              \r
        return begin_invoke([=]() -> safe_ptr<host_buffer>\r
        {\r
-               push_state();\r
-               auto restore_state = make_scope_guard([&]\r
-               {\r
-                       pop_state();\r
-               });\r
-\r
                auto dest = create_host_buffer(source->width()*source->height()*source->stride(), host_buffer::read_only);\r
 \r
-               attach(*source);\r
+               {\r
+                       scoped_state scope(*this);\r
+\r
+                       attach(*source);\r
        \r
-               dest->bind();\r
-               GL(glReadPixels(0, 0, source->width(), source->height(), format(source->stride()), GL_UNSIGNED_BYTE, NULL));\r
-               dest->unbind();\r
+                       dest->bind();\r
+                       GL(glReadPixels(0, 0, source->width(), source->height(), format(source->stride()), GL_UNSIGNED_BYTE, NULL));\r
+\r
+                       dest->unbind();\r
+               }\r
        \r
                auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\r
 \r
@@ -491,7 +501,10 @@ boost::unique_future<safe_ptr<host_buffer>> ogl_device::transfer(const safe_ptr<
                        GL(glGetSynciv(sync, GL_SYNC_STATUS, 1, &length, values));\r
 \r
                        if(values[0] != GL_SIGNALED)            \r
-                               yield();\r
+                       {\r
+                               if(!yield())\r
+                                       Sleep(2);\r
+                       }\r
                        else\r
                                break;\r
                }\r
@@ -505,14 +518,10 @@ boost::unique_future<safe_ptr<host_buffer>> ogl_device::transfer(const safe_ptr<
 boost::unique_future<safe_ptr<device_buffer>> ogl_device::transfer(const safe_ptr<host_buffer>& source, int width, int height, int stride)\r
 {              \r
        return begin_invoke([=]() -> safe_ptr<device_buffer>\r
-       {\r
-               push_state();\r
-               auto restore_state = make_scope_guard([&]\r
-               {\r
-                       pop_state();\r
-               });\r
-               \r
+       {               \r
                auto dest = create_device_buffer(width, height, stride);\r
+               \r
+               scoped_state scope(*this);\r
 \r
                source->unmap();\r
                source->bind();\r
@@ -521,10 +530,31 @@ boost::unique_future<safe_ptr<device_buffer>> ogl_device::transfer(const safe_pt
                GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dest->width(), dest->height(), format(dest->stride()), GL_UNSIGNED_BYTE, NULL));\r
                        \r
                source->unbind();\r
-\r
+               \r
                return dest;\r
        });\r
 }\r
 \r
+ogl_device::state::state()\r
+       : attached_texture(0)\r
+       , active_shader(0)\r
+{\r
+       binded_textures.assign(0);\r
+       viewport.assign(std::numeric_limits<int>::max());\r
+       scissor.assign(std::numeric_limits<int>::max());\r
+       blend_func.assign(std::numeric_limits<int>::max());\r
+       pattern.assign(0xFF);\r
+}       \r
+\r
+ogl_device::state::state(const state& other)\r
+{\r
+       A_memcpy(this, &other, sizeof(state));\r
+}\r
+\r
+ogl_device::state& ogl_device::state::operator=(const state& other)\r
+{\r
+       A_memcpy(this, &other, sizeof(state));\r
+}\r
+\r
 }}\r
 \r