From 0ccc71d2da022e0f1bf2e1d5145512960b5db016 Mon Sep 17 00:00:00 2001 From: Nicolas Capens Date: Fri, 23 Mar 2018 10:13:06 -0400 Subject: [PATCH] Implement GL_OES_fbo_render_mipmap. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This enables binding any texture mipmap level as a framebuffer attachment. Bug swiftshader:104 Change-Id: I3d4ea637ddd38bb62ca1363fe2c69c569eea36e9 Reviewed-on: https://swiftshader-review.googlesource.com/18008 Reviewed-by: Alexis Hétu Reviewed-by: Lingfeng Yang Tested-by: Nicolas Capens --- src/OpenGL/libGLES_CM/Framebuffer.cpp | 16 ++++----- src/OpenGL/libGLES_CM/Framebuffer.h | 8 ++--- src/OpenGL/libGLES_CM/Renderbuffer.cpp | 12 ++++++- src/OpenGL/libGLES_CM/Renderbuffer.h | 65 +++++++++++++++++++--------------- src/OpenGL/libGLES_CM/Texture.cpp | 8 +++-- src/OpenGL/libGLES_CM/Texture.h | 4 +-- src/OpenGL/libGLES_CM/libGLES_CM.cpp | 15 +++++--- src/OpenGL/libGLESv2/Context.cpp | 1 + src/OpenGL/libGLESv2/Renderbuffer.cpp | 4 +-- src/OpenGL/libGLESv2/libGLESv2.cpp | 18 +++++----- 10 files changed, 90 insertions(+), 61 deletions(-) diff --git a/src/OpenGL/libGLES_CM/Framebuffer.cpp b/src/OpenGL/libGLES_CM/Framebuffer.cpp index 097c6a2c5..6fcb9df71 100644 --- a/src/OpenGL/libGLES_CM/Framebuffer.cpp +++ b/src/OpenGL/libGLES_CM/Framebuffer.cpp @@ -39,7 +39,7 @@ Framebuffer::~Framebuffer() mStencilbufferPointer = nullptr; } -Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const +Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const { Context *context = getContext(); Renderbuffer *buffer = nullptr; @@ -54,29 +54,29 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const } else if(IsTextureTarget(type)) { - buffer = context->getTexture(handle)->getRenderbuffer(type); + buffer = context->getTexture(handle)->getRenderbuffer(type, level); } else UNREACHABLE(type); return buffer; } -void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer) +void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLint level) { mColorbufferType = (colorbuffer != 0) ? type : GL_NONE_OES; - mColorbufferPointer = lookupRenderbuffer(type, colorbuffer); + mColorbufferPointer = lookupRenderbuffer(type, colorbuffer, level); } -void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer) +void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level) { mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE_OES; - mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer); + mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level); } -void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer) +void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level) { mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE_OES; - mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer); + mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level); } void Framebuffer::detachTexture(GLuint texture) diff --git a/src/OpenGL/libGLES_CM/Framebuffer.h b/src/OpenGL/libGLES_CM/Framebuffer.h index 39f227c34..9c44129ac 100644 --- a/src/OpenGL/libGLES_CM/Framebuffer.h +++ b/src/OpenGL/libGLES_CM/Framebuffer.h @@ -38,9 +38,9 @@ public: virtual ~Framebuffer(); - void setColorbuffer(GLenum type, GLuint colorbuffer); - void setDepthbuffer(GLenum type, GLuint depthbuffer); - void setStencilbuffer(GLenum type, GLuint stencilbuffer); + void setColorbuffer(GLenum type, GLuint colorbuffer, GLint level = 0); + void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level = 0); + void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level = 0); void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); @@ -80,7 +80,7 @@ protected: gl::BindingPointer mStencilbufferPointer; private: - Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const; + Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const; }; class DefaultFramebuffer : public Framebuffer diff --git a/src/OpenGL/libGLES_CM/Renderbuffer.cpp b/src/OpenGL/libGLES_CM/Renderbuffer.cpp index c83244354..68094d887 100644 --- a/src/OpenGL/libGLES_CM/Renderbuffer.cpp +++ b/src/OpenGL/libGLES_CM/Renderbuffer.cpp @@ -71,7 +71,7 @@ GLuint RenderbufferInterface::getStencilSize() const ///// RenderbufferTexture2D Implementation //////// -RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture) +RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : mLevel(level) { mTexture2D = texture; } @@ -190,6 +190,11 @@ GLsizei Renderbuffer::getHeight() const return mInstance->getHeight(); } +GLint Renderbuffer::getLevel() const +{ + return mInstance->getLevel(); +} + GLenum Renderbuffer::getFormat() const { return mInstance->getFormat(); @@ -230,6 +235,11 @@ GLsizei Renderbuffer::getSamples() const return mInstance->getSamples(); } +void Renderbuffer::setLevel(GLint level) +{ + return mInstance->setLevel(level); +} + void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { ASSERT(newStorage); diff --git a/src/OpenGL/libGLES_CM/Renderbuffer.h b/src/OpenGL/libGLES_CM/Renderbuffer.h index 4405b9349..09a739119 100644 --- a/src/OpenGL/libGLES_CM/Renderbuffer.h +++ b/src/OpenGL/libGLES_CM/Renderbuffer.h @@ -48,9 +48,12 @@ public: virtual GLsizei getWidth() const = 0; virtual GLsizei getHeight() const = 0; + virtual GLint getLevel() const { return 0; } virtual GLint getFormat() const = 0; virtual GLsizei getSamples() const = 0; + virtual void setLevel(GLint) {} + GLuint getRedSize() const; GLuint getGreenSize() const; GLuint getBlueSize() const; @@ -62,24 +65,28 @@ public: class RenderbufferTexture2D : public RenderbufferInterface { public: - RenderbufferTexture2D(Texture2D *texture); + RenderbufferTexture2D(Texture2D *texture, GLint level); - virtual ~RenderbufferTexture2D(); + ~RenderbufferTexture2D() override; - virtual void addProxyRef(const Renderbuffer *proxy); - virtual void releaseProxy(const Renderbuffer *proxy); + void addProxyRef(const Renderbuffer *proxy) override; + void releaseProxy(const Renderbuffer *proxy) override; - virtual egl::Image *getRenderTarget(); - virtual egl::Image *createSharedImage(); - virtual bool isShared() const; + egl::Image *getRenderTarget() override; + egl::Image *createSharedImage() override; + bool isShared() const override; + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLint getLevel() const override { return mLevel; } + GLint getFormat() const override; + GLsizei getSamples() const override; - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLint getFormat() const; - virtual GLsizei getSamples() const; + void setLevel(GLint level) override { mLevel = level; } private: gl::BindingPointer mTexture2D; + GLint mLevel; }; // A class derived from RenderbufferStorage is created whenever glRenderbufferStorage @@ -90,16 +97,16 @@ class RenderbufferStorage : public RenderbufferInterface public: RenderbufferStorage(); - virtual ~RenderbufferStorage() = 0; + ~RenderbufferStorage() override = 0; - virtual egl::Image *getRenderTarget() = 0; - virtual egl::Image *createSharedImage() = 0; - virtual bool isShared() const = 0; + egl::Image *getRenderTarget() override = 0; + egl::Image *createSharedImage() override = 0; + bool isShared() const override = 0; - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLint getFormat() const; - virtual GLsizei getSamples() const; + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLint getFormat() const override; + GLsizei getSamples() const override; protected: GLsizei mWidth; @@ -131,6 +138,7 @@ public: GLsizei getWidth() const; GLsizei getHeight() const; + GLint getLevel() const; GLenum getFormat() const; GLuint getRedSize() const; GLuint getGreenSize() const; @@ -140,6 +148,7 @@ public: GLuint getStencilSize() const; GLsizei getSamples() const; + void setLevel(GLint level); void setStorage(RenderbufferStorage *newStorage); private: @@ -152,11 +161,11 @@ public: explicit Colorbuffer(egl::Image *renderTarget); Colorbuffer(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); - virtual ~Colorbuffer(); + ~Colorbuffer() override; - virtual egl::Image *getRenderTarget(); - virtual egl::Image *createSharedImage(); - virtual bool isShared() const; + egl::Image *getRenderTarget() override; + egl::Image *createSharedImage() override; + bool isShared() const override; private: egl::Image *mRenderTarget; @@ -170,9 +179,9 @@ public: ~DepthStencilbuffer(); - virtual egl::Image *getRenderTarget(); - virtual egl::Image *createSharedImage(); - virtual bool isShared() const; + egl::Image *getRenderTarget() override; + egl::Image *createSharedImage() override; + bool isShared() const override; protected: egl::Image *mDepthStencil; @@ -184,7 +193,7 @@ public: explicit Depthbuffer(egl::Image *depthStencil); Depthbuffer(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); - virtual ~Depthbuffer(); + ~Depthbuffer() override; }; class Stencilbuffer : public DepthStencilbuffer @@ -193,7 +202,7 @@ public: explicit Stencilbuffer(egl::Image *depthStencil); Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples); - virtual ~Stencilbuffer(); + ~Stencilbuffer() override; }; } diff --git a/src/OpenGL/libGLES_CM/Texture.cpp b/src/OpenGL/libGLES_CM/Texture.cpp index 10439188d..4d8b75a18 100644 --- a/src/OpenGL/libGLES_CM/Texture.cpp +++ b/src/OpenGL/libGLES_CM/Texture.cpp @@ -678,7 +678,7 @@ egl::Image *Texture2D::getImage(unsigned int level) return image[level]; } -Renderbuffer *Texture2D::getRenderbuffer(GLenum target) +Renderbuffer *Texture2D::getRenderbuffer(GLenum target, GLint level) { if(target != GL_TEXTURE_2D) { @@ -687,7 +687,11 @@ Renderbuffer *Texture2D::getRenderbuffer(GLenum target) if(!mColorbufferProxy) { - mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this)); + mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this, level)); + } + else + { + mColorbufferProxy->setLevel(level); } return mColorbufferProxy; diff --git a/src/OpenGL/libGLES_CM/Texture.h b/src/OpenGL/libGLES_CM/Texture.h index 0439039df..e287c152a 100644 --- a/src/OpenGL/libGLES_CM/Texture.h +++ b/src/OpenGL/libGLES_CM/Texture.h @@ -83,7 +83,7 @@ public: virtual bool isCompressed(GLenum target, GLint level) const = 0; virtual bool isDepth(GLenum target, GLint level) const = 0; - virtual Renderbuffer *getRenderbuffer(GLenum target) = 0; + virtual Renderbuffer *getRenderbuffer(GLenum target, GLint level) = 0; virtual egl::Image *getRenderTarget(GLenum target, unsigned int level) = 0; egl::Image *createSharedImage(GLenum target, unsigned int level); virtual bool isShared(GLenum target, unsigned int level) const = 0; @@ -153,7 +153,7 @@ public: void generateMipmaps() override; void autoGenerateMipmaps() override; - Renderbuffer *getRenderbuffer(GLenum target) override; + Renderbuffer *getRenderbuffer(GLenum target, GLint level) override; egl::Image *getRenderTarget(GLenum target, unsigned int level) override; bool isShared(GLenum target, unsigned int level) const override; diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.cpp b/src/OpenGL/libGLES_CM/libGLES_CM.cpp index b1f5e80b6..7e5247c49 100644 --- a/src/OpenGL/libGLES_CM/libGLES_CM.cpp +++ b/src/OpenGL/libGLES_CM/libGLES_CM.cpp @@ -1507,7 +1507,7 @@ void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, return error(GL_INVALID_ENUM); } - if(level != 0) + if((level < 0) || (level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) { return error(GL_INVALID_VALUE); } @@ -1528,9 +1528,9 @@ void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, switch(attachment) { - case GL_COLOR_ATTACHMENT0_OES: framebuffer->setColorbuffer(textarget, texture); break; - case GL_DEPTH_ATTACHMENT_OES: framebuffer->setDepthbuffer(textarget, texture); break; - case GL_STENCIL_ATTACHMENT_OES: framebuffer->setStencilbuffer(textarget, texture); break; + case GL_COLOR_ATTACHMENT0_OES: framebuffer->setColorbuffer(textarget, texture, level); break; + case GL_DEPTH_ATTACHMENT_OES: framebuffer->setDepthbuffer(textarget, texture, level); break; + case GL_STENCIL_ATTACHMENT_OES: framebuffer->setStencilbuffer(textarget, texture, level); break; } } } @@ -2082,19 +2082,23 @@ void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GL GLenum attachmentType; GLuint attachmentHandle; + Renderbuffer *renderbuffer = nullptr; switch(attachment) { case GL_COLOR_ATTACHMENT0_OES: attachmentType = framebuffer->getColorbufferType(); attachmentHandle = framebuffer->getColorbufferName(); + renderbuffer = framebuffer->getColorbuffer(); break; case GL_DEPTH_ATTACHMENT_OES: attachmentType = framebuffer->getDepthbufferType(); attachmentHandle = framebuffer->getDepthbufferName(); + renderbuffer = framebuffer->getDepthbuffer(); break; case GL_STENCIL_ATTACHMENT_OES: attachmentType = framebuffer->getStencilbufferType(); attachmentHandle = framebuffer->getStencilbufferName(); + renderbuffer = framebuffer->getStencilbuffer(); break; default: return error(GL_INVALID_ENUM); @@ -2129,7 +2133,7 @@ void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GL case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES: if(attachmentObjectType == GL_TEXTURE) { - *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0 + *params = renderbuffer->getLevel(); } else { @@ -2268,6 +2272,7 @@ const GLubyte* GetString(GLenum name) "GL_OES_EGL_image_external " "GL_OES_EGL_sync " "GL_OES_element_index_uint " + "GL_OES_fbo_render_mipmap " "GL_OES_framebuffer_object " "GL_OES_packed_depth_stencil " "GL_OES_read_format " diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp index 5a5a6b3d9..e257174eb 100644 --- a/src/OpenGL/libGLESv2/Context.cpp +++ b/src/OpenGL/libGLESv2/Context.cpp @@ -4405,6 +4405,7 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const "GL_OES_EGL_image_external", "GL_OES_EGL_sync", "GL_OES_element_index_uint", + "GL_OES_fbo_render_mipmap", "GL_OES_framebuffer_object", "GL_OES_packed_depth_stencil", "GL_OES_rgb8_rgba8", diff --git a/src/OpenGL/libGLESv2/Renderbuffer.cpp b/src/OpenGL/libGLESv2/Renderbuffer.cpp index a970dcf42..fdbb61717 100644 --- a/src/OpenGL/libGLESv2/Renderbuffer.cpp +++ b/src/OpenGL/libGLESv2/Renderbuffer.cpp @@ -78,7 +78,7 @@ RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : RenderbufferTexture2D::~RenderbufferTexture2D() { - mTexture2D = NULL; + mTexture2D = nullptr; } // Textures need to maintain their own reference count for references via @@ -441,7 +441,7 @@ void Renderbuffer::setLevel(GLint level) void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { - ASSERT(newStorage != NULL); + ASSERT(newStorage); delete mInstance; mInstance = newStorage; diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp index 1577569a9..4be1261fc 100644 --- a/src/OpenGL/libGLESv2/libGLESv2.cpp +++ b/src/OpenGL/libGLESv2/libGLESv2.cpp @@ -6006,11 +6006,6 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, return error(GL_INVALID_OPERATION); } - if(tex->isCompressed(textarget, level)) - { - return error(GL_INVALID_OPERATION); - } - switch(textarget) { case GL_TEXTURE_3D: @@ -6023,10 +6018,15 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, return error(GL_INVALID_ENUM); } - if(level != 0) + if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) { return error(GL_INVALID_VALUE); } + + if(tex->isCompressed(textarget, level)) + { + return error(GL_INVALID_OPERATION); + } } es2::Framebuffer *framebuffer = nullptr; @@ -6049,14 +6049,14 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, switch(attachment) { - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break; default: if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS) { return error(GL_INVALID_ENUM); } - framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0); + framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level); break; } } -- 2.11.0