#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
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
//}\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
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
}\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
}\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
}\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
}\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
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
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
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
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
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