Window resizing stability fixes

This commit is contained in:
Jack Andersen 2015-11-16 20:41:32 -10:00
parent 49da287791
commit 4d133edd2c
7 changed files with 83 additions and 21 deletions

View File

@ -53,6 +53,9 @@ public:
virtual IGraphicsCommandQueue* getCommandQueue()=0; virtual IGraphicsCommandQueue* getCommandQueue()=0;
virtual IGraphicsDataFactory* getDataFactory()=0; virtual IGraphicsDataFactory* getDataFactory()=0;
/* Creates a new context on current thread!! Call from main client thread */
virtual IGraphicsDataFactory* getMainContextDataFactory()=0;
/* Creates a new context on current thread!! Call from client loading thread */ /* Creates a new context on current thread!! Call from client loading thread */
virtual IGraphicsDataFactory* getLoadContextDataFactory()=0; virtual IGraphicsDataFactory* getLoadContextDataFactory()=0;

View File

@ -196,6 +196,9 @@ public:
virtual IGraphicsCommandQueue* getCommandQueue()=0; virtual IGraphicsCommandQueue* getCommandQueue()=0;
virtual IGraphicsDataFactory* getDataFactory()=0; virtual IGraphicsDataFactory* getDataFactory()=0;
/* Creates a new context on current thread!! Call from main client thread */
virtual IGraphicsDataFactory* getMainContextDataFactory()=0;
/* Creates a new context on current thread!! Call from client loading thread */ /* Creates a new context on current thread!! Call from client loading thread */
virtual IGraphicsDataFactory* getLoadContextDataFactory()=0; virtual IGraphicsDataFactory* getLoadContextDataFactory()=0;

View File

@ -25,6 +25,7 @@ struct IGraphicsCommandQueue
virtual void setViewport(const SWindowRect& rect)=0; virtual void setViewport(const SWindowRect& rect)=0;
virtual void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)=0; virtual void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)=0;
virtual void flushBufferUpdates()=0;
virtual void setClearColor(const float rgba[4])=0; virtual void setClearColor(const float rgba[4])=0;
virtual void clearTarget(bool render=true, bool depth=true)=0; virtual void clearTarget(bool render=true, bool depth=true)=0;

View File

@ -552,7 +552,6 @@ struct GLCommandQueue : IGraphicsCommandQueue
OpSetShaderDataBinding, OpSetShaderDataBinding,
OpSetRenderTarget, OpSetRenderTarget,
OpSetViewport, OpSetViewport,
OpResizeRenderTexture,
OpSetClearColor, OpSetClearColor,
OpClearTarget, OpClearTarget,
OpSetDrawPrimitive, OpSetDrawPrimitive,
@ -577,12 +576,6 @@ struct GLCommandQueue : IGraphicsCommandQueue
size_t count; size_t count;
size_t instCount; size_t instCount;
}; };
struct
{
ITextureR* tex;
size_t width;
size_t height;
} resize;
}; };
Command(Op op) : m_op(op) {} Command(Op op) : m_op(op) {}
}; };
@ -599,7 +592,15 @@ struct GLCommandQueue : IGraphicsCommandQueue
std::unique_lock<std::mutex> m_initlk; std::unique_lock<std::mutex> m_initlk;
std::thread m_thr; std::thread m_thr;
struct RenderTextureResize
{
GLTextureR* tex;
size_t width;
size_t height;
};
/* These members are locked for multithreaded access */ /* These members are locked for multithreaded access */
std::vector<RenderTextureResize> m_pendingResizes;
std::vector<GLVertexFormat*> m_pendingFmtAdds; std::vector<GLVertexFormat*> m_pendingFmtAdds;
std::vector<GLuint> m_pendingFmtDels; std::vector<GLuint> m_pendingFmtDels;
std::vector<GLTextureR*> m_pendingFboAdds; std::vector<GLTextureR*> m_pendingFboAdds;
@ -673,25 +674,40 @@ struct GLCommandQueue : IGraphicsCommandQueue
break; break;
self->m_drawBuf = self->m_completeBuf; self->m_drawBuf = self->m_completeBuf;
if (self->m_pendingResizes.size())
{
for (const RenderTextureResize& resize : self->m_pendingResizes)
resize.tex->resize(resize.width, resize.height);
self->m_pendingResizes.clear();
}
if (self->m_pendingFmtAdds.size()) if (self->m_pendingFmtAdds.size())
{
for (GLVertexFormat* fmt : self->m_pendingFmtAdds) for (GLVertexFormat* fmt : self->m_pendingFmtAdds)
ConfigureVertexFormat(fmt); ConfigureVertexFormat(fmt);
self->m_pendingFmtAdds.clear(); self->m_pendingFmtAdds.clear();
}
if (self->m_pendingFmtDels.size()) if (self->m_pendingFmtDels.size())
{
for (GLuint fmt : self->m_pendingFmtDels) for (GLuint fmt : self->m_pendingFmtDels)
glDeleteVertexArrays(1, &fmt); glDeleteVertexArrays(1, &fmt);
self->m_pendingFmtDels.clear(); self->m_pendingFmtDels.clear();
}
if (self->m_pendingFboAdds.size()) if (self->m_pendingFboAdds.size())
{
for (GLTextureR* tex : self->m_pendingFboAdds) for (GLTextureR* tex : self->m_pendingFboAdds)
ConfigureFBO(tex); ConfigureFBO(tex);
self->m_pendingFboAdds.clear(); self->m_pendingFboAdds.clear();
}
if (self->m_pendingFboDels.size()) if (self->m_pendingFboDels.size())
{
for (GLuint fbo : self->m_pendingFboDels) for (GLuint fbo : self->m_pendingFboDels)
glDeleteFramebuffers(1, &fbo); glDeleteFramebuffers(1, &fbo);
self->m_pendingFboDels.clear(); self->m_pendingFboDels.clear();
}
} }
std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf]; std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf];
GLenum prim = GL_TRIANGLES; GLenum prim = GL_TRIANGLES;
@ -715,11 +731,6 @@ struct GLCommandQueue : IGraphicsCommandQueue
glViewport(cmd.rect.location[0], cmd.rect.location[1], glViewport(cmd.rect.location[0], cmd.rect.location[1],
cmd.rect.size[0], cmd.rect.size[1]); cmd.rect.size[0], cmd.rect.size[1]);
break; break;
case Command::OpResizeRenderTexture:
{
GLTextureR* tex = static_cast<GLTextureR*>(cmd.resize.tex);
tex->resize(cmd.resize.width, cmd.resize.height);
}
case Command::OpSetClearColor: case Command::OpSetClearColor:
glClearColor(cmd.rgba[0], cmd.rgba[1], cmd.rgba[2], cmd.rgba[3]); glClearColor(cmd.rgba[0], cmd.rgba[1], cmd.rgba[2], cmd.rgba[3]);
break; break;
@ -800,11 +811,14 @@ struct GLCommandQueue : IGraphicsCommandQueue
void resizeRenderTexture(ITextureR* tex, size_t width, size_t height) void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)
{ {
std::vector<Command>& cmds = m_cmdBufs[m_fillBuf]; std::unique_lock<std::mutex> lk(m_mt);
cmds.emplace_back(Command::OpResizeRenderTexture); GLTextureR* texgl = static_cast<GLTextureR*>(tex);
cmds.back().resize.tex = tex; m_pendingResizes.push_back({texgl, width, height});
cmds.back().resize.width = width; }
cmds.back().resize.height = height;
void flushBufferUpdates()
{
glFlush();
} }
void setClearColor(const float rgba[4]) void setClearColor(const float rgba[4])
@ -1022,6 +1036,7 @@ GLDataFactory::newRenderTexture(size_t width, size_t height, size_t samples)
{ {
GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent->getCommandQueue()); GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent->getCommandQueue());
GLTextureR* retval = new GLTextureR(q, width, height, samples); GLTextureR* retval = new GLTextureR(q, width, height, samples);
q->resizeRenderTexture(retval, width, height);
static_cast<GLData*>(m_deferredData)->m_RTexs.emplace_back(retval); static_cast<GLData*>(m_deferredData)->m_RTexs.emplace_back(retval);
return retval; return retval;
} }

View File

@ -17,6 +17,8 @@ DBusConnection* RegisterDBus(const char* appName, bool& isFirst);
#include <sys/param.h> #include <sys/param.h>
#include <thread> #include <thread>
#include <mutex>
#include <condition_variable>
namespace boo namespace boo
{ {
@ -239,11 +241,18 @@ public:
/* Spawn client thread */ /* Spawn client thread */
int clientReturn = INT_MIN; int clientReturn = INT_MIN;
std::mutex initmt;
std::condition_variable initcv;
std::unique_lock<std::mutex> outerLk(initmt);
std::thread clientThread([&]() std::thread clientThread([&]()
{ {
std::unique_lock<std::mutex> innerLk(initmt);
innerLk.unlock();
initcv.notify_one();
clientReturn = m_callback.appMain(this); clientReturn = m_callback.appMain(this);
pthread_kill(mainThread, SIGTERM); pthread_kill(mainThread, SIGTERM);
}); });
initcv.wait(outerLk);
/* Begin application event loop */ /* Begin application event loop */
while (clientReturn == INT_MIN) while (clientReturn == INT_MIN)

View File

@ -72,6 +72,11 @@ public:
return nullptr; return nullptr;
} }
IGraphicsDataFactory* getMainContextDataFactory()
{
return nullptr;
}
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory()
{ {
return nullptr; return nullptr;
@ -196,6 +201,11 @@ struct WindowWayland : IWindow
return m_gfxCtx.getDataFactory(); return m_gfxCtx.getDataFactory();
} }
IGraphicsDataFactory* getMainContextDataFactory()
{
return m_gfxCtx.getMainContextDataFactory();
}
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory()
{ {
return m_gfxCtx.getLoadContextDataFactory(); return m_gfxCtx.getLoadContextDataFactory();

View File

@ -185,6 +185,7 @@ struct GraphicsContextGLX : IGraphicsContext
IGraphicsCommandQueue* m_commandQueue = nullptr; IGraphicsCommandQueue* m_commandQueue = nullptr;
IGraphicsDataFactory* m_dataFactory = nullptr; IGraphicsDataFactory* m_dataFactory = nullptr;
GLXContext m_mainCtx = 0;
GLXContext m_loadCtx = 0; GLXContext m_loadCtx = 0;
std::thread m_vsyncThread; std::thread m_vsyncThread;
@ -396,6 +397,21 @@ public:
return m_dataFactory; return m_dataFactory;
} }
IGraphicsDataFactory* getMainContextDataFactory()
{
XLockDisplay(m_xDisp);
if (!m_mainCtx)
{
m_mainCtx = glXCreateContextAttribsARB(m_xDisp, m_fbconfig, m_glxCtx, True, ContextAttribs);
if (!m_mainCtx)
Log.report(LogVisor::FatalError, "unable to make main GLX context");
}
if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_mainCtx))
Log.report(LogVisor::FatalError, "unable to make main GLX context current");
XUnlockDisplay(m_xDisp);
return getDataFactory();
}
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory()
{ {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
@ -1180,6 +1196,11 @@ public:
return m_gfxCtx.getDataFactory(); return m_gfxCtx.getDataFactory();
} }
IGraphicsDataFactory* getMainContextDataFactory()
{
return m_gfxCtx.getMainContextDataFactory();
}
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory()
{ {
return m_gfxCtx.getLoadContextDataFactory(); return m_gfxCtx.getLoadContextDataFactory();