From 30898c65495bfe4628a1cc24cc36e655b6a5ed6a Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 3 Nov 2015 15:02:05 -1000 Subject: [PATCH] OpenGL API sync --- include/boo/graphicsdev/GL.hpp | 1 + lib/graphicsdev/GL.cpp | 157 +++++++++++++++++++++++---------- lib/graphicsdev/glew.c | 2 + lib/x11/WindowXlib.cpp | 4 +- test/main.cpp | 10 ++- 5 files changed, 125 insertions(+), 49 deletions(-) diff --git a/include/boo/graphicsdev/GL.hpp b/include/boo/graphicsdev/GL.hpp index b98d893..ced4a3f 100644 --- a/include/boo/graphicsdev/GL.hpp +++ b/include/boo/graphicsdev/GL.hpp @@ -29,6 +29,7 @@ public: 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); + ITextureR* newRenderTexture(size_t width, size_t height, size_t samples); IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index eab584a..8b57cb8 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -19,6 +19,7 @@ struct GLData : IGraphicsData std::vector> m_DBufs; std::vector> m_STexs; std::vector> m_DTexs; + std::vector> m_RTexs; std::vector> m_VFmts; }; @@ -130,8 +131,7 @@ class GLTextureD : public ITextureD friend class GLDataFactory; friend struct GLCommandQueue; struct GLCommandQueue* m_q; - GLuint m_texs[2]; - GLuint m_fbo = 0; + GLuint m_texs[3]; void* m_mappedBuf = nullptr; size_t m_mappedSize = 0; size_t m_width = 0; @@ -140,26 +140,28 @@ class GLTextureD : public ITextureD public: ~GLTextureD(); - void load(const void* data, size_t sz) - { - 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) - { - if (m_mappedBuf) - free(m_mappedBuf); - m_mappedBuf = malloc(sz); - m_mappedSize = sz; - return m_mappedBuf; - } - void unmap() - { - 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 load(const void* data, size_t sz); + void* map(size_t sz); + void unmap(); + + void bind(size_t idx) const; +}; + +class GLTextureR : public ITextureR +{ + friend class GLDataFactory; + friend struct GLCommandQueue; + struct GLCommandQueue* 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; + size_t m_samples = 0; + GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t samples); +public: + ~GLTextureR(); void bind(size_t idx) const { @@ -401,9 +403,9 @@ struct GLShaderDataBinding : IShaderDataBinding } for (size_t i=0 ; idynamic()) + if (m_texs[i]->type() == ITexture::TextureDynamic) static_cast(m_texs[i])->bind(i); - else + else if (m_texs[i]->type() == ITexture::TextureStatic) static_cast(m_texs[i])->bind(i); } } @@ -509,7 +511,8 @@ struct GLCommandQueue : IGraphicsCommandQueue union { const IShaderDataBinding* binding; - const ITextureD* target; + const ITextureR* target; + const ITextureR* source; SWindowRect rect; float rgba[4]; GLbitfield flags; @@ -539,7 +542,7 @@ struct GLCommandQueue : IGraphicsCommandQueue /* These members are locked for multithreaded access */ std::vector m_pendingFmtAdds; std::vector m_pendingFmtDels; - std::vector m_pendingFboAdds; + std::vector m_pendingFboAdds; std::vector m_pendingFboDels; static void ConfigureVertexFormat(GLVertexFormat* fmt) @@ -583,7 +586,7 @@ struct GLCommandQueue : IGraphicsCommandQueue } } - static void ConfigureFBO(GLTextureD* tex) + static void ConfigureFBO(GLTextureR* tex) { glGenFramebuffers(1, &tex->m_fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_fbo); @@ -621,7 +624,7 @@ struct GLCommandQueue : IGraphicsCommandQueue self->m_pendingFmtDels.clear(); if (self->m_pendingFboAdds.size()) - for (GLTextureD* tex : self->m_pendingFboAdds) + for (GLTextureR* tex : self->m_pendingFboAdds) ConfigureFBO(tex); self->m_pendingFboAdds.clear(); @@ -641,8 +644,11 @@ struct GLCommandQueue : IGraphicsCommandQueue break; case Command::OpSetRenderTarget: { - const GLTextureD* tex = static_cast(cmd.target); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_fbo); + const GLTextureR* tex = static_cast(cmd.target); + if (!tex) + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + else + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_fbo); break; } case Command::OpSetViewport: @@ -671,8 +677,18 @@ struct GLCommandQueue : IGraphicsCommandQueue glDrawElementsInstanced(prim, cmd.count, GL_UNSIGNED_INT, (void*)cmd.start, cmd.instCount); break; case Command::OpPresent: + { + const GLTextureR* tex = static_cast(cmd.source); + if (tex) + { + glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, tex->m_width, tex->m_height, 0, 0, + tex->m_width, tex->m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } self->m_parent->present(); break; + } default: break; } } @@ -702,16 +718,14 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.emplace_back(Command::OpSetShaderDataBinding); cmds.back().binding = binding; } - void setRenderTarget(ITextureD* target) + + void setRenderTarget(ITextureR* target) { std::vector& cmds = m_cmdBufs[m_fillBuf]; cmds.emplace_back(Command::OpSetRenderTarget); cmds.back().target = target; } - void setRenderTarget(IWindow* target) - { - /* TODO: Do */ - } + void setViewport(const SWindowRect& rect) { std::vector& cmds = m_cmdBufs[m_fillBuf]; @@ -728,6 +742,7 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().rgba[2] = rgba[2]; cmds.back().rgba[3] = rgba[3]; } + void clearTarget(bool render=true, bool depth=true) { std::vector& cmds = m_cmdBufs[m_fillBuf]; @@ -748,6 +763,7 @@ struct GLCommandQueue : IGraphicsCommandQueue else if (prim == PrimitiveTriStrips) cmds.back().prim = GL_TRIANGLE_STRIP; } + void draw(size_t start, size_t count) { std::vector& cmds = m_cmdBufs[m_fillBuf]; @@ -755,6 +771,7 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().start = start; cmds.back().count = count; } + void drawIndexed(size_t start, size_t count) { std::vector& cmds = m_cmdBufs[m_fillBuf]; @@ -762,6 +779,7 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().start = start; cmds.back().count = count; } + void drawInstances(size_t start, size_t count, size_t instCount) { std::vector& cmds = m_cmdBufs[m_fillBuf]; @@ -770,6 +788,7 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().count = count; cmds.back().instCount = instCount; } + void drawInstancesIndexed(size_t start, size_t count, size_t instCount) { std::vector& cmds = m_cmdBufs[m_fillBuf]; @@ -779,10 +798,11 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().instCount = instCount; } - void present() + void resolveDisplay(ITextureR* source) { std::vector& cmds = m_cmdBufs[m_fillBuf]; cmds.emplace_back(Command::OpPresent); + cmds.back().source = source; } void addVertexFormat(GLVertexFormat* fmt) @@ -797,13 +817,13 @@ struct GLCommandQueue : IGraphicsCommandQueue m_pendingFmtDels.push_back(fmt->m_vao); } - void addFBO(GLTextureD* tex) + void addFBO(GLTextureR* tex) { std::unique_lock lk(m_mt); m_pendingFboAdds.push_back(tex); } - void delFBO(GLTextureD* tex) + void delFBO(GLTextureR* tex) { std::unique_lock lk(m_mt); m_pendingFboDels.push_back(tex->m_fbo); @@ -863,18 +883,44 @@ GLDataFactory::newDynamicBuffer(BufferUse use, size_t stride, size_t count) } GLTextureD::GLTextureD(GLCommandQueue* q, size_t width, size_t height, TextureFormat fmt) -: m_q(q) +: m_q(q), m_width(width), m_height(height) { - m_width = width; - m_height = height; - glGenTextures(2, m_texs); + glGenTextures(3, 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D, m_texs[2]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); +} +GLTextureD::~GLTextureD() {glDeleteTextures(3, m_texs);} + +void GLTextureD::load(const void* data, size_t sz) +{ + glBindTexture(GL_TEXTURE_2D, m_texs[m_q->m_fillBuf]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); +} +void* GLTextureD::map(size_t sz) +{ + if (m_mappedBuf) + free(m_mappedBuf); + m_mappedBuf = malloc(sz); + m_mappedSize = sz; + return m_mappedBuf; +} +void GLTextureD::unmap() +{ + glBindTexture(GL_TEXTURE_2D, m_texs[m_q->m_fillBuf]); + 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 GLTextureD::bind(size_t idx) const +{ + glActiveTexture(GL_TEXTURE0 + idx); + glBindTexture(GL_TEXTURE_2D, m_texs[0]); } -GLTextureD::~GLTextureD() {glDeleteTextures(2, m_texs); m_q->delFBO(this);} ITextureD* GLDataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) @@ -885,6 +931,27 @@ GLDataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) return retval; } +GLTextureR::GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t samples) +: m_q(q), m_width(width), m_height(height), m_samples(samples) +{ + 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); +} +GLTextureR::~GLTextureR() {glDeleteTextures(2, m_texs); m_q->delFBO(this);} + +ITextureR* +GLDataFactory::newRenderTexture(size_t width, size_t height, size_t samples) +{ + GLCommandQueue* q = static_cast(m_parent->getCommandQueue()); + GLTextureR* retval = new GLTextureR(q, width, height, samples); + static_cast(m_deferredData)->m_RTexs.emplace_back(retval); + return retval; +} + GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount, const VertexElementDescriptor* elements) : m_q(q), diff --git a/lib/graphicsdev/glew.c b/lib/graphicsdev/glew.c index 3ea70f8..a65e27d 100644 --- a/lib/graphicsdev/glew.c +++ b/lib/graphicsdev/glew.c @@ -3948,12 +3948,14 @@ static GLboolean _glewInit_GL_VERSION_3_2 (GLEW_CONTEXT_ARG_DEF_INIT) #ifdef GL_VERSION_3_3 static GLboolean _glewInit_GL_ARB_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT); +static GLboolean _glewInit_GL_ARB_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT); static GLboolean _glewInit_GL_VERSION_3_3 (GLEW_CONTEXT_ARG_DEF_INIT) { GLboolean r = GL_FALSE; r = ((glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisor")) == NULL) || r; _glewInit_GL_ARB_vertex_array_object(); + _glewInit_GL_ARB_framebuffer_object(); return r; } diff --git a/lib/x11/WindowXlib.cpp b/lib/x11/WindowXlib.cpp index e4514c1..ea7cf0d 100644 --- a/lib/x11/WindowXlib.cpp +++ b/lib/x11/WindowXlib.cpp @@ -343,9 +343,9 @@ public: m_loadCtx = glXCreateContextAttribsARB(m_xDisp, m_fbconfig, m_glxCtx, True, ContextAttribs); if (!m_loadCtx) Log.report(LogVisor::FatalError, "unable to make load GLX context"); - if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_loadCtx)) - Log.report(LogVisor::FatalError, "unable to make load GLX context current"); } + if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_loadCtx)) + Log.report(LogVisor::FatalError, "unable to make load GLX context current"); return getDataFactory(); } diff --git a/test/main.cpp b/test/main.cpp index ab0f226..a774ab7 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -285,14 +285,20 @@ struct TestApplicationCallback : IApplicationCallback devFinder.startScanning(); IGraphicsCommandQueue* gfxQ = mainWindow->getCommandQueue(); + IGraphicsDataFactory* gfxF = mainWindow->getDataFactory(); + + ITextureR* renderTarget = gfxF->newRenderTexture(640, 480, 1); + gfxF->commit(); + std::thread loaderThread(LoaderProc, this); size_t frameIdx = 0; size_t lastCheck = 0; - gfxQ->setViewport({{0, 0}, {640, 480}}); while (running) { mainWindow->waitForRetrace(); + gfxQ->setRenderTarget(renderTarget); + gfxQ->setViewport({{0, 0}, {640, 480}}); float rgba[] = {sinf(frameIdx / 60.0), cosf(frameIdx / 60.0), 0.0, 1.0}; gfxQ->setClearColor(rgba); gfxQ->clearTarget(); @@ -302,7 +308,7 @@ struct TestApplicationCallback : IApplicationCallback gfxQ->setShaderDataBinding(m_binding); gfxQ->draw(0, 4); } - gfxQ->present(); + gfxQ->resolveDisplay(renderTarget); gfxQ->execute(); //fprintf(stderr, "%zu\n", frameIdx);