libkwineffects: Add support for depth/stencil attachments
It's needed so we can allocate fbos suitable for qtquick.
This commit is contained in:
parent
76335880bf
commit
9911b6b54c
2 changed files with 130 additions and 77 deletions
|
@ -1046,6 +1046,8 @@ std::unique_ptr<GLShader> ShaderManager::loadShaderFromCode(const QByteArray &ve
|
|||
|
||||
/*** GLFramebuffer ***/
|
||||
bool GLFramebuffer::sSupported = false;
|
||||
bool GLFramebuffer::sSupportsPackedDepthStencil = false;
|
||||
bool GLFramebuffer::sSupportsDepth24 = false;
|
||||
bool GLFramebuffer::s_blitSupported = false;
|
||||
QStack<GLFramebuffer *> GLFramebuffer::s_fbos = QStack<GLFramebuffer *>();
|
||||
|
||||
|
@ -1053,10 +1055,12 @@ void GLFramebuffer::initStatic()
|
|||
{
|
||||
if (GLPlatform::instance()->isGLES()) {
|
||||
sSupported = true;
|
||||
sSupportsPackedDepthStencil = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_OES_packed_depth_stencil"));
|
||||
sSupportsDepth24 = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_OES_depth24"));
|
||||
s_blitSupported = hasGLVersion(3, 0);
|
||||
} else {
|
||||
sSupported = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_ARB_framebuffer_object")) || hasGLExtension(QByteArrayLiteral("GL_EXT_framebuffer_object"));
|
||||
|
||||
sSupportsPackedDepthStencil = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_ARB_framebuffer_object")) || hasGLExtension(QByteArrayLiteral("GL_EXT_packed_depth_stencil"));
|
||||
s_blitSupported = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_ARB_framebuffer_object")) || hasGLExtension(QByteArrayLiteral("GL_EXT_framebuffer_blit"));
|
||||
}
|
||||
}
|
||||
|
@ -1107,47 +1111,6 @@ GLFramebuffer::GLFramebuffer()
|
|||
{
|
||||
}
|
||||
|
||||
GLFramebuffer::GLFramebuffer(GLTexture *colorAttachment)
|
||||
: mSize(colorAttachment->size())
|
||||
, m_colorAttachment(colorAttachment)
|
||||
{
|
||||
// Make sure FBO is supported
|
||||
if (sSupported && !colorAttachment->isNull()) {
|
||||
initFBO(colorAttachment);
|
||||
} else {
|
||||
qCCritical(LIBKWINGLUTILS) << "Framebuffer objects aren't supported!";
|
||||
}
|
||||
}
|
||||
|
||||
GLFramebuffer::GLFramebuffer(GLuint handle, const QSize &size)
|
||||
: mFramebuffer(handle)
|
||||
, mSize(size)
|
||||
, mValid(true)
|
||||
, mForeign(true)
|
||||
, m_colorAttachment(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
GLFramebuffer::~GLFramebuffer()
|
||||
{
|
||||
if (!mForeign && mValid) {
|
||||
glDeleteFramebuffers(1, &mFramebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLFramebuffer::bind()
|
||||
{
|
||||
if (!valid()) {
|
||||
qCCritical(LIBKWINGLUTILS) << "Can't enable invalid framebuffer object!";
|
||||
return false;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, handle());
|
||||
glViewport(0, 0, mSize.width(), mSize.height());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static QString formatFramebufferStatus(GLenum status)
|
||||
{
|
||||
switch (status) {
|
||||
|
@ -1180,13 +1143,14 @@ static QString formatFramebufferStatus(GLenum status)
|
|||
}
|
||||
}
|
||||
|
||||
void GLFramebuffer::initFBO(GLTexture *colorAttachment)
|
||||
GLFramebuffer::GLFramebuffer(GLTexture *colorAttachment, Attachment attachment)
|
||||
: mSize(colorAttachment->size())
|
||||
, m_colorAttachment(colorAttachment)
|
||||
{
|
||||
#if DEBUG_GLFRAMEBUFFER
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR)
|
||||
qCCritical(LIBKWINGLUTILS) << "Error status when entering GLFramebuffer::initFBO: " << formatGLError(err);
|
||||
#endif
|
||||
if (!sSupported) {
|
||||
qCCritical(LIBKWINGLUTILS) << "Framebuffer objects aren't supported!";
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint prevFbo = 0;
|
||||
if (const GLFramebuffer *current = currentFramebuffer()) {
|
||||
|
@ -1194,38 +1158,14 @@ void GLFramebuffer::initFBO(GLTexture *colorAttachment)
|
|||
}
|
||||
|
||||
glGenFramebuffers(1, &mFramebuffer);
|
||||
|
||||
#if DEBUG_GLFRAMEBUFFER
|
||||
if ((err = glGetError()) != GL_NO_ERROR) {
|
||||
qCCritical(LIBKWINGLUTILS) << "glGenFramebuffers failed: " << formatGLError(err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
|
||||
#if DEBUG_GLFRAMEBUFFER
|
||||
if ((err = glGetError()) != GL_NO_ERROR) {
|
||||
qCCritical(LIBKWINGLUTILS) << "glBindFramebuffer failed: " << formatGLError(err);
|
||||
glDeleteFramebuffers(1, &mFramebuffer);
|
||||
return;
|
||||
initColorAttachment(colorAttachment);
|
||||
if (attachment == Attachment::CombinedDepthStencil) {
|
||||
initDepthStencilAttachment();
|
||||
}
|
||||
#endif
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
colorAttachment->target(), colorAttachment->texture(), 0);
|
||||
|
||||
#if DEBUG_GLFRAMEBUFFER
|
||||
if ((err = glGetError()) != GL_NO_ERROR) {
|
||||
qCCritical(LIBKWINGLUTILS) << "glFramebufferTexture2D failed: " << formatGLError(err);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, prevFbo);
|
||||
glDeleteFramebuffers(1, &mFramebuffer);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, prevFbo);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
|
@ -1242,6 +1182,109 @@ void GLFramebuffer::initFBO(GLTexture *colorAttachment)
|
|||
mValid = true;
|
||||
}
|
||||
|
||||
GLFramebuffer::GLFramebuffer(GLuint handle, const QSize &size)
|
||||
: mFramebuffer(handle)
|
||||
, mSize(size)
|
||||
, mValid(true)
|
||||
, mForeign(true)
|
||||
, m_colorAttachment(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
GLFramebuffer::~GLFramebuffer()
|
||||
{
|
||||
if (!mForeign && mValid) {
|
||||
glDeleteFramebuffers(1, &mFramebuffer);
|
||||
}
|
||||
if (mDepthBuffer) {
|
||||
glDeleteRenderbuffers(1, &mDepthBuffer);
|
||||
}
|
||||
if (mStencilBuffer && mStencilBuffer != mDepthBuffer) {
|
||||
glDeleteRenderbuffers(1, &mStencilBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLFramebuffer::bind()
|
||||
{
|
||||
if (!valid()) {
|
||||
qCCritical(LIBKWINGLUTILS) << "Can't enable invalid framebuffer object!";
|
||||
return false;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, handle());
|
||||
glViewport(0, 0, mSize.width(), mSize.height());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLFramebuffer::initColorAttachment(GLTexture *colorAttachment)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
colorAttachment->target(), colorAttachment->texture(), 0);
|
||||
}
|
||||
|
||||
void GLFramebuffer::initDepthStencilAttachment()
|
||||
{
|
||||
GLuint buffer = 0;
|
||||
|
||||
// Try to attach a depth/stencil combined attachment.
|
||||
if (sSupportsPackedDepthStencil) {
|
||||
glGenRenderbuffers(1, &buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mSize.width(), mSize.height());
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
glDeleteRenderbuffers(1, &buffer);
|
||||
} else {
|
||||
mDepthBuffer = buffer;
|
||||
mStencilBuffer = buffer;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to attach a depth attachment separately.
|
||||
GLenum depthFormat;
|
||||
if (GLPlatform::instance()->isGLES()) {
|
||||
if (sSupportsDepth24) {
|
||||
depthFormat = GL_DEPTH_COMPONENT24;
|
||||
} else {
|
||||
depthFormat = GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
} else {
|
||||
depthFormat = GL_DEPTH_COMPONENT;
|
||||
}
|
||||
|
||||
glGenRenderbuffers(1, &buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, mSize.width(), mSize.height());
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer);
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
glDeleteRenderbuffers(1, &buffer);
|
||||
} else {
|
||||
mDepthBuffer = buffer;
|
||||
}
|
||||
|
||||
// Try to attach a stencil attachment separately.
|
||||
GLenum stencilFormat;
|
||||
if (GLPlatform::instance()->isGLES()) {
|
||||
stencilFormat = GL_STENCIL_INDEX8;
|
||||
} else {
|
||||
stencilFormat = GL_STENCIL_INDEX;
|
||||
}
|
||||
|
||||
glGenRenderbuffers(1, &buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, stencilFormat, mSize.width(), mSize.height());
|
||||
glFramebufferRenderbuffer(GL_RENDERBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer);
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
glDeleteRenderbuffers(1, &buffer);
|
||||
} else {
|
||||
mStencilBuffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void GLFramebuffer::blitFromFramebuffer(const QRect &source, const QRect &destination, GLenum filter, bool flipX, bool flipY)
|
||||
{
|
||||
if (!valid()) {
|
||||
|
|
|
@ -408,6 +408,11 @@ inline GLShader *ShaderBinder::shader()
|
|||
class KWINGLUTILS_EXPORT GLFramebuffer
|
||||
{
|
||||
public:
|
||||
enum Attachment {
|
||||
NoAttachment,
|
||||
CombinedDepthStencil,
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a GLFramebuffer
|
||||
* @since 5.13
|
||||
|
@ -420,7 +425,7 @@ public:
|
|||
*
|
||||
* @param colorAttachment texture where the scene will be rendered onto
|
||||
*/
|
||||
explicit GLFramebuffer(GLTexture *colorAttachment);
|
||||
explicit GLFramebuffer(GLTexture *colorAttachment, Attachment attachment = NoAttachment);
|
||||
|
||||
/**
|
||||
* Constructs a wrapper for an already created framebuffer object. The GLFramebuffer
|
||||
|
@ -504,7 +509,8 @@ public:
|
|||
GLTexture *colorAttachment() const;
|
||||
|
||||
protected:
|
||||
void initFBO(GLTexture *colorAttachment);
|
||||
void initColorAttachment(GLTexture *colorAttachment);
|
||||
void initDepthStencilAttachment();
|
||||
|
||||
private:
|
||||
bool bind();
|
||||
|
@ -512,10 +518,14 @@ private:
|
|||
friend void KWin::cleanupGL();
|
||||
static void cleanup();
|
||||
static bool sSupported;
|
||||
static bool sSupportsPackedDepthStencil;
|
||||
static bool sSupportsDepth24;
|
||||
static bool s_blitSupported;
|
||||
static QStack<GLFramebuffer *> s_fbos;
|
||||
|
||||
GLuint mFramebuffer = 0;
|
||||
GLuint mDepthBuffer = 0;
|
||||
GLuint mStencilBuffer = 0;
|
||||
QSize mSize;
|
||||
bool mValid = false;
|
||||
bool mForeign = false;
|
||||
|
|
Loading…
Reference in a new issue