From 2814da014febe1b7e2a10fc97a463a5a680d3963 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 29 Oct 2015 14:00:56 -1000 Subject: [PATCH] Further GLES3 implementation --- include/boo/IApplication.hpp | 2 +- include/boo/IGraphicsContext.hpp | 7 +- include/boo/graphicsdev/GLES3.hpp | 33 +- .../boo/graphicsdev/IGraphicsDataFactory.hpp | 39 +- lib/graphicsdev/GLES3.cpp | 490 ++++++++++++------ lib/x11/ApplicationWayland.hpp | 2 +- lib/x11/WindowXCB.cpp | 35 +- 7 files changed, 402 insertions(+), 206 deletions(-) diff --git a/include/boo/IApplication.hpp b/include/boo/IApplication.hpp index 21a135f..574bf04 100644 --- a/include/boo/IApplication.hpp +++ b/include/boo/IApplication.hpp @@ -14,7 +14,7 @@ class IApplication; struct IApplicationCallback { - virtual int appMain(IApplication*) {} + virtual int appMain(IApplication*) {return 0;} virtual void appQuitting(IApplication*) {} virtual void appFilesOpen(IApplication*, const std::vector&) {} }; diff --git a/include/boo/IGraphicsContext.hpp b/include/boo/IGraphicsContext.hpp index 567cd76..b4c4ced 100644 --- a/include/boo/IGraphicsContext.hpp +++ b/include/boo/IGraphicsContext.hpp @@ -47,8 +47,11 @@ public: virtual void initializeContext()=0; virtual void makeCurrent()=0; - virtual std::unique_ptr createCommandQueue()=0; - virtual std::unique_ptr createDataFactory()=0; + virtual IGraphicsCommandQueue* getCommandQueue()=0; + virtual IGraphicsDataFactory* getDataFactory()=0; + + /* Creates a new context on current thread!! Call from client loading thread */ + virtual IGraphicsDataFactory* getLoadContextDataFactory()=0; }; diff --git a/include/boo/graphicsdev/GLES3.hpp b/include/boo/graphicsdev/GLES3.hpp index 141651d..7e659f2 100644 --- a/include/boo/graphicsdev/GLES3.hpp +++ b/include/boo/graphicsdev/GLES3.hpp @@ -3,38 +3,19 @@ #include "IGraphicsDataFactory.hpp" #include "IGraphicsCommandQueue.hpp" +#include "boo/IGraphicsContext.hpp" #include #include namespace boo { -class GLES3VertexArray -{ - friend class GLES3DataFactory; - GLuint m_vao = 0; - bool initObjects(); - void clearObjects(); - GLES3VertexArray() = default; -public: - operator bool() const {return m_vao != 0;} - ~GLES3VertexArray() {clearObjects();} - GLES3VertexArray& operator=(const GLES3VertexArray&) = delete; - GLES3VertexArray(const GLES3VertexArray&) = delete; - GLES3VertexArray& operator=(GLES3VertexArray&& other) - { - m_vao = other.m_vao; - other.m_vao = 0; - return *this; - } - GLES3VertexArray(GLES3VertexArray&& other) {*this = std::move(other);} -}; - class GLES3DataFactory : public IGraphicsDataFactory { + IGraphicsContext* m_parent; std::unique_ptr m_deferredData; public: - GLES3DataFactory(); + GLES3DataFactory(IGraphicsContext* parent); Platform platform() const {return PlatformOGLES3;} const char* platformName() const {return "OpenGL ES 3.0";} @@ -42,19 +23,21 @@ public: const IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t sz); IGraphicsBufferD* newDynamicBuffer(BufferUse use); - GLES3VertexArray newVertexArray(size_t elementCount, const VertexElementDescriptor* elements); - const ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); + const IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); + const IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, BlendFactor srcFac, BlendFactor dstFac, bool depthTest, bool depthWrite, bool backfaceCulling); const IShaderDataBinding* newShaderDataBinding(const IShaderPipeline* pipeline, - size_t bufCount, const IGraphicsBuffer** bufs, + const IVertexFormat* vtxFormat, + const IGraphicsBuffer* vbo, const IGraphicsBuffer* ebo, + size_t ubufCount, const IGraphicsBuffer** ubufs, size_t texCount, const ITexture** texs); void reset(); diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index 576c152..d0925d6 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -10,6 +10,9 @@ namespace boo struct IGraphicsBuffer { bool dynamic() const {return m_dynamic;} + virtual void bindVertex() const=0; + virtual void bindIndex() const=0; + virtual void bindUniform(size_t idx) const=0; protected: bool m_dynamic; IGraphicsBuffer(bool dynamic) : m_dynamic(dynamic) {} @@ -35,6 +38,7 @@ protected: struct ITexture { bool dynamic() const {return m_dynamic;} + virtual void bind(size_t idx) const=0; protected: bool m_dynamic; ITexture(bool dynamic) : m_dynamic(dynamic) {} @@ -57,6 +61,11 @@ protected: ITextureD() : ITexture(true) {} }; +/** Opaque token for representing the data layout of a vertex + * in a VBO. Also able to reference buffers for platforms like + * OpenGL that cache object refs */ +struct IVertexFormat {}; + /** Opaque token for referencing a complete graphics pipeline state necessary * to rasterize geometry (shaders and blending modes mainly) */ struct IShaderPipeline {}; @@ -104,6 +113,18 @@ struct IGraphicsDataFactory virtual IGraphicsBufferD* newDynamicBuffer(BufferUse use)=0; + enum TextureFormat + { + TextureFormatRGBA8, + TextureFormatDXT1, + TextureFormatPVRTC4 + }; + virtual const ITextureS* + newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, + const void* data, size_t sz)=0; + virtual ITextureD* + newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0; + struct VertexElementDescriptor { const IGraphicsBuffer* vertBuffer = nullptr; @@ -117,18 +138,8 @@ struct IGraphicsDataFactory VertexSemanticWeight } semantic; }; - - enum TextureFormat - { - TextureFormatRGBA8, - TextureFormatDXT1, - TextureFormatPVRTC4 - }; - virtual const ITextureS* - newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, - const void* data, size_t sz)=0; - virtual ITextureD* - newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0; + virtual const IVertexFormat* + newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)=0; enum BlendFactor { @@ -146,7 +157,9 @@ struct IGraphicsDataFactory virtual const IShaderDataBinding* newShaderDataBinding(const IShaderPipeline* pipeline, - size_t bufCount, const IGraphicsBuffer** bufs, + const IVertexFormat* vtxFormat, + const IGraphicsBuffer* vbo, const IGraphicsBuffer* ebo, + size_t ubufCount, const IGraphicsBuffer** ubufs, size_t texCount, const ITexture** texs)=0; virtual void reset()=0; diff --git a/lib/graphicsdev/GLES3.cpp b/lib/graphicsdev/GLES3.cpp index 41336a8..3ca3e7c 100644 --- a/lib/graphicsdev/GLES3.cpp +++ b/lib/graphicsdev/GLES3.cpp @@ -13,10 +13,12 @@ namespace boo struct GLES3Data : IGraphicsData { std::vector> m_SPs; + std::vector> m_SBinds; std::vector> m_SBufs; std::vector> m_DBufs; std::vector> m_STexs; std::vector> m_DTexs; + std::vector> m_VFmts; }; static const GLenum USE_TABLE[] = @@ -30,6 +32,7 @@ static const GLenum USE_TABLE[] = class GLES3GraphicsBufferS : IGraphicsBufferS { friend class GLES3DataFactory; + friend struct GLES3CommandQueue; GLuint m_buf; GLenum m_target; GLES3GraphicsBufferS(IGraphicsDataFactory::BufferUse use, const void* data, size_t sz) @@ -41,43 +44,40 @@ class GLES3GraphicsBufferS : IGraphicsBufferS } public: ~GLES3GraphicsBufferS() {glDeleteBuffers(1, &m_buf);} + + void bindVertex() const + {glBindBuffer(GL_ARRAY_BUFFER, m_buf);} + void bindIndex() const + {glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buf);} + void bindUniform(size_t idx) const + {glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_buf);} }; class GLES3GraphicsBufferD : IGraphicsBufferD { friend class GLES3DataFactory; - GLuint m_buf; + friend struct GLES3CommandQueue; + struct GLES3CommandQueue* m_q; + GLuint m_bufs[3]; GLenum m_target; void* m_mappedBuf = nullptr; size_t m_mappedSize = 0; - GLES3GraphicsBufferD(IGraphicsDataFactory::BufferUse use) + GLES3GraphicsBufferD(GLES3CommandQueue* q, IGraphicsDataFactory::BufferUse use) + : m_q(q) { m_target = USE_TABLE[use]; - glGenBuffers(1, &m_buf); + glGenBuffers(3, m_bufs); } public: - ~GLES3GraphicsBufferD() {glDeleteBuffers(1, &m_buf);} + ~GLES3GraphicsBufferD() {glDeleteBuffers(3, m_bufs);} - void load(const void* data, size_t sz) - { - glBindBuffer(m_target, m_buf); - glBufferData(m_target, sz, data, GL_DYNAMIC_DRAW); - } - void* map(size_t sz) - { - if (m_mappedBuf) - free(m_mappedBuf); - m_mappedBuf = malloc(sz); - m_mappedSize = sz; - return m_mappedBuf; - } - void unmap() - { - glBindBuffer(m_target, m_buf); - glBufferData(m_target, m_mappedSize, m_mappedBuf, GL_DYNAMIC_DRAW); - free(m_mappedBuf); - m_mappedBuf = nullptr; - } + void load(const void* data, size_t sz); + void* map(size_t sz); + void unmap(); + + void bindVertex() const; + void bindIndex() const; + void bindUniform(size_t idx) const; }; const IGraphicsBufferS* @@ -88,14 +88,6 @@ GLES3DataFactory::newStaticBuffer(BufferUse use, const void* data, size_t sz) return retval; } -IGraphicsBufferD* -GLES3DataFactory::newDynamicBuffer(BufferUse use) -{ - GLES3GraphicsBufferD* retval = new GLES3GraphicsBufferD(use); - static_cast(m_deferredData.get())->m_DBufs.emplace_back(retval); - return retval; -} - class GLES3TextureS : ITextureS { friend class GLES3DataFactory; @@ -120,33 +112,33 @@ class GLES3TextureS : ITextureS } public: ~GLES3TextureS() {glDeleteTextures(1, &m_tex);} + + void bind(size_t idx) const + { + glActiveTexture(GL_TEXTURE0 + idx); + glBindTexture(GL_TEXTURE_2D, m_tex); + } }; class GLES3TextureD : ITextureD { friend class GLES3DataFactory; - friend class GLES3CommandQueue; - GLuint m_tex; - GLuint m_fbo; + friend struct GLES3CommandQueue; + struct GLES3CommandQueue* m_q; + GLuint m_texs[2]; + GLuint m_fbo = 0; void* m_mappedBuf = nullptr; size_t m_mappedSize = 0; size_t m_width = 0; size_t m_height = 0; - GLES3TextureD(size_t width, size_t height, - IGraphicsDataFactory::TextureFormat fmt) - { - m_width = width; - m_height = height; - glGenTextures(1, &m_tex); - glBindTexture(GL_TEXTURE_2D, m_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - } + GLES3TextureD(GLES3CommandQueue* q, size_t width, size_t height, + IGraphicsDataFactory::TextureFormat fmt); public: - ~GLES3TextureD() {glDeleteTextures(1, &m_tex);} + ~GLES3TextureD(); void load(const void* data, size_t sz) { - glBindTexture(GL_TEXTURE_2D, m_tex); + glBindTexture(GL_TEXTURE_2D, m_texs[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); } void* map(size_t sz) @@ -159,11 +151,17 @@ public: } void unmap() { - glBindTexture(GL_TEXTURE_2D, m_tex); + glBindTexture(GL_TEXTURE_2D, m_texs[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_mappedBuf); free(m_mappedBuf); m_mappedBuf = nullptr; } + + void bind(size_t idx) const + { + glActiveTexture(GL_TEXTURE0 + idx); + glBindTexture(GL_TEXTURE_2D, m_texs[0]); + } }; const ITextureS* @@ -174,15 +172,8 @@ GLES3DataFactory::newStaticTexture(size_t width, size_t height, size_t mips, Tex static_cast(m_deferredData.get())->m_STexs.emplace_back(retval); return retval; } -ITextureD* -GLES3DataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) -{ - GLES3TextureD* retval = new GLES3TextureD(width, height, fmt); - static_cast(m_deferredData.get())->m_DTexs.emplace_back(retval); - return retval; -} -class GLES3ShaderPipeline : IShaderPipeline +class GLES3ShaderPipeline : public IShaderPipeline { friend class GLES3DataFactory; GLuint m_vert = 0; @@ -190,6 +181,9 @@ class GLES3ShaderPipeline : IShaderPipeline GLuint m_prog = 0; GLenum m_sfactor = GL_ONE; GLenum m_dfactor = GL_ZERO; + bool m_depthTest = true; + bool m_depthWrite = true; + bool m_backfaceCulling = true; bool initObjects() { m_vert = glCreateShader(GL_VERTEX_SHADER); @@ -236,108 +230,34 @@ public: return *this; } GLES3ShaderPipeline(GLES3ShaderPipeline&& other) {*this = std::move(other);} -}; -bool GLES3VertexArray::initObjects() -{ - glGenVertexArrays(1, &m_vao); - if (!m_vao) - return false; - return true; -} - -void GLES3VertexArray::clearObjects() -{ - glDeleteVertexArrays(1, &m_vao); - m_vao = 0; -} - -static const GLint SEMANTIC_COUNT_TABLE[] = -{ - 3, - 3, - 4, - 2, - 4 -}; - -static const size_t SEMANTIC_SIZE_TABLE[] = -{ - 12, - 12, - 4, - 8, - 16 -}; - -static const GLenum SEMANTIC_TYPE_TABLE[] = -{ - GL_FLOAT, - GL_FLOAT, - GL_UNSIGNED_BYTE, - GL_FLOAT, - GL_FLOAT -}; - -GLES3VertexArray GLES3DataFactory::newVertexArray -(size_t elementCount, const VertexElementDescriptor* elements) -{ - GLES3VertexArray vertArray; - if (!vertArray.initObjects()) + GLuint bind() const { - fprintf(stderr, "unable to create vertex array object\n"); - return vertArray; - } + glUseProgram(m_prog); - size_t stride = 0; - for (size_t i=0 ; isemantic]; - } - - size_t offset = 0; - glBindVertexArray(vertArray.m_vao); - const IGraphicsBuffer* lastVBO = nullptr; - const IGraphicsBuffer* lastEBO = nullptr; - for (size_t i=0 ; ivertBuffer != lastVBO) + if (m_dfactor != GL_ZERO) { - lastVBO = desc->vertBuffer; - if (lastVBO->dynamic()) - { - const GLES3GraphicsBufferD* vbo = static_cast(lastVBO); - glBindBuffer(GL_ARRAY_BUFFER, vbo->m_buf); - } - else - { - const GLES3GraphicsBufferS* vbo = static_cast(lastVBO); - glBindBuffer(GL_ARRAY_BUFFER, vbo->m_buf); - } + glEnable(GL_BLEND); + glBlendFunc(m_sfactor, m_dfactor); } - if (desc->indexBuffer != lastEBO) - { - lastEBO = desc->indexBuffer; - if (lastEBO->dynamic()) - { - const GLES3GraphicsBufferD* ebo = static_cast(lastEBO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo->m_buf); - } - else - { - const GLES3GraphicsBufferS* ebo = static_cast(lastEBO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo->m_buf); - } - } - glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[desc->semantic], - SEMANTIC_TYPE_TABLE[desc->semantic], GL_TRUE, stride, (void*)offset); - offset += SEMANTIC_SIZE_TABLE[desc->semantic]; - } + else + glDisable(GL_BLEND); - return vertArray; -} + if (m_depthTest) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + + glDepthMask(m_depthWrite); + + if (m_backfaceCulling) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); + + return m_prog; + } +}; static const GLenum BLEND_FACTOR_TABLE[] = { @@ -366,6 +286,9 @@ const IShaderPipeline* GLES3DataFactory::newShaderPipeline } shader.m_sfactor = BLEND_FACTOR_TABLE[srcFac]; shader.m_dfactor = BLEND_FACTOR_TABLE[dstFac]; + shader.m_depthTest = depthTest; + shader.m_depthWrite = depthWrite; + shader.m_backfaceCulling = backfaceCulling; glShaderSource(shader.m_vert, 1, &vertSource, nullptr); glCompileShader(shader.m_vert); @@ -414,23 +337,71 @@ const IShaderPipeline* GLES3DataFactory::newShaderPipeline return retval; } +struct GLES3VertexFormat : IVertexFormat +{ + GLES3CommandQueue* m_q; + GLuint m_vao = 0; + size_t m_elementCount; + std::unique_ptr m_elements; + GLES3VertexFormat(GLES3CommandQueue* q, size_t elementCount, + const GLES3DataFactory::VertexElementDescriptor* elements); + ~GLES3VertexFormat(); + void bind() const {glBindVertexArray(m_vao);} +}; + struct GLES3ShaderDataBinding : IShaderDataBinding { + const GLES3ShaderPipeline* m_pipeline; + const GLES3VertexFormat* m_vtxFormat; + size_t m_ubufCount; + std::unique_ptr m_ubufs; + size_t m_texCount; + std::unique_ptr m_texs; + GLES3ShaderDataBinding(const IShaderPipeline* pipeline, + const IVertexFormat* vtxFormat, + size_t ubufCount, const IGraphicsBuffer** ubufs, + size_t texCount, const ITexture** texs) + : m_pipeline(static_cast(pipeline)), + m_vtxFormat(static_cast(vtxFormat)), + m_ubufCount(ubufCount), + m_ubufs(new const IGraphicsBuffer*[ubufCount]), + m_texCount(texCount), + m_texs(new const ITexture*[texCount]) + { + for (size_t i=0 ; ibind(); + m_vtxFormat->bind(); + for (size_t i=0 ; ibindUniform(i); + glUniformBlockBinding(prog, i, i); + } + for (size_t i=0 ; ibind(i); } }; const IShaderDataBinding* GLES3DataFactory::newShaderDataBinding(const IShaderPipeline* pipeline, - size_t bufCount, const IGraphicsBuffer** bufs, + const IVertexFormat* vtxFormat, + const IGraphicsBuffer*, const IGraphicsBuffer*, + size_t ubufCount, const IGraphicsBuffer** ubufs, size_t texCount, const ITexture** texs) { - return nullptr; + GLES3ShaderDataBinding* retval = + new GLES3ShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs, texCount, texs); + static_cast(m_deferredData.get())->m_SBinds.emplace_back(retval); + return retval; } -GLES3DataFactory::GLES3DataFactory() -: m_deferredData(new struct GLES3Data()) {} +GLES3DataFactory::GLES3DataFactory(IGraphicsContext* parent) +: m_parent(parent), m_deferredData(new struct GLES3Data()) {} void GLES3DataFactory::reset() { @@ -444,11 +415,38 @@ std::unique_ptr GLES3DataFactory::commit() return retval; } +static const GLint SEMANTIC_COUNT_TABLE[] = +{ + 3, + 3, + 4, + 2, + 4 +}; + +static const size_t SEMANTIC_SIZE_TABLE[] = +{ + 12, + 12, + 4, + 8, + 16 +}; + +static const GLenum SEMANTIC_TYPE_TABLE[] = +{ + GL_FLOAT, + GL_FLOAT, + GL_UNSIGNED_BYTE, + GL_FLOAT, + GL_FLOAT +}; + struct GLES3CommandQueue : IGraphicsCommandQueue { Platform platform() const {return IGraphicsDataFactory::PlatformOGLES3;} const char* platformName() const {return "OpenGL ES 3.0";} - IGraphicsContext& m_parent; + IGraphicsContext* m_parent = nullptr; struct Command { @@ -489,9 +487,57 @@ struct GLES3CommandQueue : IGraphicsCommandQueue std::mutex m_mt; std::condition_variable m_cv; + /* These members are locked for multithreaded access */ + std::vector m_pendingFmtAdds; + std::vector m_pendingFmtDels; + std::vector m_pendingFboAdds; + std::vector m_pendingFboDels; + + static void ConfigureVertexFormat(GLES3VertexFormat* fmt) + { + glGenVertexArrays(1, &fmt->m_vao); + + size_t stride = 0; + for (size_t i=0 ; im_elementCount ; ++i) + { + const IGraphicsDataFactory::VertexElementDescriptor* desc = &fmt->m_elements[i]; + stride += SEMANTIC_SIZE_TABLE[desc->semantic]; + } + + size_t offset = 0; + glBindVertexArray(fmt->m_vao); + const IGraphicsBuffer* lastVBO = nullptr; + const IGraphicsBuffer* lastEBO = nullptr; + for (size_t i=0 ; im_elementCount ; ++i) + { + const IGraphicsDataFactory::VertexElementDescriptor* desc = &fmt->m_elements[i]; + if (desc->vertBuffer != lastVBO) + { + lastVBO = desc->vertBuffer; + lastVBO->bindVertex(); + } + if (desc->indexBuffer != lastEBO) + { + lastEBO = desc->indexBuffer; + lastEBO->bindIndex(); + } + glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[desc->semantic], + SEMANTIC_TYPE_TABLE[desc->semantic], GL_TRUE, stride, (void*)offset); + offset += SEMANTIC_SIZE_TABLE[desc->semantic]; + } + } + + static void ConfigureFBO(GLES3TextureD* tex) + { + glGenFramebuffers(1, &tex->m_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_fbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->m_texs[0], 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex->m_texs[1], 0); + } + static void RenderingWorker(GLES3CommandQueue* self) { - self->m_parent.makeCurrent(); + self->m_parent->makeCurrent(); while (self->m_running) { { @@ -500,6 +546,26 @@ struct GLES3CommandQueue : IGraphicsCommandQueue if (!self->m_running) break; self->m_drawBuf = self->m_completeBuf; + + if (self->m_pendingFmtAdds.size()) + for (GLES3VertexFormat* fmt : self->m_pendingFmtAdds) + ConfigureVertexFormat(fmt); + self->m_pendingFmtAdds.clear(); + + if (self->m_pendingFmtDels.size()) + for (GLuint fmt : self->m_pendingFmtDels) + glDeleteVertexArrays(1, &fmt); + self->m_pendingFmtDels.clear(); + + if (self->m_pendingFboAdds.size()) + for (GLES3TextureD* tex : self->m_pendingFboAdds) + ConfigureFBO(tex); + self->m_pendingFboAdds.clear(); + + if (self->m_pendingFboDels.size()) + for (GLuint fbo : self->m_pendingFboDels) + glDeleteFramebuffers(1, &fbo); + self->m_pendingFboDels.clear(); } std::vector& cmds = self->m_cmdBufs[self->m_drawBuf]; GLenum prim = GL_TRIANGLES; @@ -547,7 +613,7 @@ struct GLES3CommandQueue : IGraphicsCommandQueue } } - GLES3CommandQueue(IGraphicsContext& parent) + GLES3CommandQueue(IGraphicsContext* parent) : m_parent(parent), m_thr(RenderingWorker, this) {} @@ -628,6 +694,31 @@ struct GLES3CommandQueue : IGraphicsCommandQueue cmds.back().instCount = instCount; } + void addVertexFormat(GLES3VertexFormat* fmt) + { + std::unique_lock lk(m_mt); + m_pendingFmtAdds.push_back(fmt); + } + + void delVertexFormat(GLES3VertexFormat* fmt) + { + std::unique_lock lk(m_mt); + m_pendingFmtDels.push_back(fmt->m_vao); + } + + void addFBO(GLES3TextureD* tex) + { + std::unique_lock lk(m_mt); + m_pendingFboAdds.push_back(tex); + } + + void delFBO(GLES3TextureD* tex) + { + std::unique_lock lk(m_mt); + m_pendingFboDels.push_back(tex->m_fbo); + } + + void execute() { std::unique_lock lk(m_mt); @@ -645,7 +736,88 @@ struct GLES3CommandQueue : IGraphicsCommandQueue } }; -IGraphicsCommandQueue* _NewGLES3CommandQueue(IGraphicsContext& parent) +void GLES3GraphicsBufferD::load(const void* data, size_t sz) +{ + glBindBuffer(m_target, m_bufs[m_q->m_fillBuf]); + glBufferData(m_target, sz, data, GL_DYNAMIC_DRAW); +} +void* GLES3GraphicsBufferD::map(size_t sz) +{ + if (m_mappedBuf) + free(m_mappedBuf); + m_mappedBuf = malloc(sz); + m_mappedSize = sz; + return m_mappedBuf; +} +void GLES3GraphicsBufferD::unmap() +{ + glBindBuffer(m_target, m_bufs[m_q->m_fillBuf]); + glBufferData(m_target, m_mappedSize, m_mappedBuf, GL_DYNAMIC_DRAW); + free(m_mappedBuf); + m_mappedBuf = nullptr; +} +void GLES3GraphicsBufferD::bindVertex() const +{glBindBuffer(GL_ARRAY_BUFFER, m_bufs[m_q->m_drawBuf]);} +void GLES3GraphicsBufferD::bindIndex() const +{glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufs[m_q->m_drawBuf]);} +void GLES3GraphicsBufferD::bindUniform(size_t idx) const +{glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_bufs[m_q->m_drawBuf]);} + +IGraphicsBufferD* +GLES3DataFactory::newDynamicBuffer(BufferUse use) +{ + GLES3CommandQueue* q = static_cast(m_parent->getCommandQueue()); + GLES3GraphicsBufferD* retval = new GLES3GraphicsBufferD(q, use); + static_cast(m_deferredData.get())->m_DBufs.emplace_back(retval); + return retval; +} + +GLES3TextureD::GLES3TextureD(GLES3CommandQueue* q, size_t width, size_t height, + IGraphicsDataFactory::TextureFormat fmt) +: m_q(q) +{ + m_width = width; + m_height = height; + glGenTextures(2, m_texs); + glBindTexture(GL_TEXTURE_2D, m_texs[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D, m_texs[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + m_q->addFBO(this); +} +GLES3TextureD::~GLES3TextureD() {glDeleteTextures(2, m_texs); m_q->delFBO(this);} + +ITextureD* +GLES3DataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) +{ + GLES3CommandQueue* q = static_cast(m_parent->getCommandQueue()); + GLES3TextureD* retval = new GLES3TextureD(q, width, height, fmt); + static_cast(m_deferredData.get())->m_DTexs.emplace_back(retval); + return retval; +} + +GLES3VertexFormat::GLES3VertexFormat(GLES3CommandQueue* q, size_t elementCount, + const GLES3DataFactory::VertexElementDescriptor* elements) +: m_q(q), + m_elementCount(elementCount), + m_elements(new GLES3DataFactory::VertexElementDescriptor[elementCount]) +{ + for (size_t i=0 ; iaddVertexFormat(this); +} +GLES3VertexFormat::~GLES3VertexFormat() {m_q->delVertexFormat(this);} + +const IVertexFormat* GLES3DataFactory::newVertexFormat +(size_t elementCount, const VertexElementDescriptor* elements) +{ + GLES3CommandQueue* q = static_cast(m_parent->getCommandQueue()); + GLES3VertexFormat* retval = new struct GLES3VertexFormat(q, elementCount, elements); + static_cast(m_deferredData.get())->m_VFmts.emplace_back(retval); + return retval; +} + +IGraphicsCommandQueue* _NewGLES3CommandQueue(IGraphicsContext* parent) { return new struct GLES3CommandQueue(parent); } diff --git a/lib/x11/ApplicationWayland.hpp b/lib/x11/ApplicationWayland.hpp index 62693bf..352a32f 100644 --- a/lib/x11/ApplicationWayland.hpp +++ b/lib/x11/ApplicationWayland.hpp @@ -48,7 +48,7 @@ public: int run() { - + return 0; } const std::string& getUniqueName() const diff --git a/lib/x11/WindowXCB.cpp b/lib/x11/WindowXCB.cpp index a45baf7..33ddefc 100644 --- a/lib/x11/WindowXCB.cpp +++ b/lib/x11/WindowXCB.cpp @@ -28,7 +28,7 @@ namespace boo { -IGraphicsCommandQueue* _NewGLES3CommandQueue(IGraphicsContext& parent); +IGraphicsCommandQueue* _NewGLES3CommandQueue(IGraphicsContext* parent); extern PFNGLXGETVIDEOSYNCSGIPROC FglXGetVideoSyncSGI; extern PFNGLXWAITVIDEOSYNCSGIPROC FglXWaitVideoSyncSGI; @@ -168,6 +168,10 @@ struct GraphicsContextXCB : IGraphicsContext xcb_glx_context_t m_glxCtx = 0; xcb_glx_context_tag_t m_glxCtxTag = 0; + IGraphicsCommandQueue* m_commandQueue = nullptr; + IGraphicsDataFactory* m_dataFactory = nullptr; + xcb_glx_context_t m_loadCtx = 0; + public: IWindowCallback* m_callback; @@ -252,6 +256,8 @@ public: xcb_glx_destroy_context(m_xcbConn, m_glxCtx); if (m_glxWindow) xcb_glx_delete_window(m_xcbConn, m_glxWindow); + if (m_loadCtx) + xcb_glx_destroy_context(m_xcbConn, m_loadCtx); } void _setCallback(IWindowCallback* cb) @@ -295,14 +301,33 @@ public: free(reply); } - std::unique_ptr createCommandQueue() + IGraphicsCommandQueue* getCommandQueue() { - return std::unique_ptr(_NewGLES3CommandQueue(*this)); + if (!m_commandQueue) + m_commandQueue = _NewGLES3CommandQueue(this); + return m_commandQueue; } - std::unique_ptr createDataFactory() + IGraphicsDataFactory* getDataFactory() { - return std::unique_ptr(new struct GLES3DataFactory()); + if (!m_dataFactory) + m_dataFactory = new struct GLES3DataFactory(this); + return m_dataFactory; + } + + IGraphicsDataFactory* getLoadContextDataFactory() + { + if (!m_loadCtx) + { + m_loadCtx = xcb_generate_id(m_xcbConn); + xcb_glx_create_context(m_xcbConn, m_loadCtx, m_visualid, 0, m_glxCtx, 1); + xcb_generic_error_t* err = nullptr; + xcb_glx_make_context_current_reply_t* reply = + xcb_glx_make_context_current_reply(m_xcbConn, + xcb_glx_make_context_current(m_xcbConn, 0, m_glxWindow, m_glxWindow, m_loadCtx), &err); + free(reply); + } + return getDataFactory(); } };