Commit 0ccc71d2 by Nicolas Capens Committed by Nicolas Capens

Implement GL_OES_fbo_render_mipmap.

This enables binding any texture mipmap level as a framebuffer attachment. Bug swiftshader:104 Change-Id: I3d4ea637ddd38bb62ca1363fe2c69c569eea36e9 Reviewed-on: https://swiftshader-review.googlesource.com/18008Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarLingfeng Yang <lfy@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent fe5861bf
......@@ -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)
......
......@@ -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<Renderbuffer> mStencilbufferPointer;
private:
Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const;
Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const;
};
class DefaultFramebuffer : public Framebuffer
......
......@@ -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);
......
......@@ -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<Texture2D> 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;
};
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 "
......
......@@ -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",
......
......@@ -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;
......
......@@ -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;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment