libkwineffects: Add support for depth/stencil attachments

It's needed so we can allocate fbos suitable for qtquick.
master
Vlad Zahorodnii 1 year ago
parent 76335880bf
commit 9911b6b54c

@ -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…
Cancel
Save