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() ...@@ -39,7 +39,7 @@ Framebuffer::~Framebuffer()
mStencilbufferPointer = nullptr; mStencilbufferPointer = nullptr;
} }
Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const
{ {
Context *context = getContext(); Context *context = getContext();
Renderbuffer *buffer = nullptr; Renderbuffer *buffer = nullptr;
...@@ -54,29 +54,29 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const ...@@ -54,29 +54,29 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
} }
else if(IsTextureTarget(type)) else if(IsTextureTarget(type))
{ {
buffer = context->getTexture(handle)->getRenderbuffer(type); buffer = context->getTexture(handle)->getRenderbuffer(type, level);
} }
else UNREACHABLE(type); else UNREACHABLE(type);
return buffer; 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; 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; 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; mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE_OES;
mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer); mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level);
} }
void Framebuffer::detachTexture(GLuint texture) void Framebuffer::detachTexture(GLuint texture)
......
...@@ -38,9 +38,9 @@ public: ...@@ -38,9 +38,9 @@ public:
virtual ~Framebuffer(); virtual ~Framebuffer();
void setColorbuffer(GLenum type, GLuint colorbuffer); void setColorbuffer(GLenum type, GLuint colorbuffer, GLint level = 0);
void setDepthbuffer(GLenum type, GLuint depthbuffer); void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level = 0);
void setStencilbuffer(GLenum type, GLuint stencilbuffer); void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level = 0);
void detachTexture(GLuint texture); void detachTexture(GLuint texture);
void detachRenderbuffer(GLuint renderbuffer); void detachRenderbuffer(GLuint renderbuffer);
...@@ -80,7 +80,7 @@ protected: ...@@ -80,7 +80,7 @@ protected:
gl::BindingPointer<Renderbuffer> mStencilbufferPointer; gl::BindingPointer<Renderbuffer> mStencilbufferPointer;
private: private:
Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const; Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const;
}; };
class DefaultFramebuffer : public Framebuffer class DefaultFramebuffer : public Framebuffer
......
...@@ -71,7 +71,7 @@ GLuint RenderbufferInterface::getStencilSize() const ...@@ -71,7 +71,7 @@ GLuint RenderbufferInterface::getStencilSize() const
///// RenderbufferTexture2D Implementation //////// ///// RenderbufferTexture2D Implementation ////////
RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture) RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : mLevel(level)
{ {
mTexture2D = texture; mTexture2D = texture;
} }
...@@ -190,6 +190,11 @@ GLsizei Renderbuffer::getHeight() const ...@@ -190,6 +190,11 @@ GLsizei Renderbuffer::getHeight() const
return mInstance->getHeight(); return mInstance->getHeight();
} }
GLint Renderbuffer::getLevel() const
{
return mInstance->getLevel();
}
GLenum Renderbuffer::getFormat() const GLenum Renderbuffer::getFormat() const
{ {
return mInstance->getFormat(); return mInstance->getFormat();
...@@ -230,6 +235,11 @@ GLsizei Renderbuffer::getSamples() const ...@@ -230,6 +235,11 @@ GLsizei Renderbuffer::getSamples() const
return mInstance->getSamples(); return mInstance->getSamples();
} }
void Renderbuffer::setLevel(GLint level)
{
return mInstance->setLevel(level);
}
void Renderbuffer::setStorage(RenderbufferStorage *newStorage) void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
{ {
ASSERT(newStorage); ASSERT(newStorage);
......
...@@ -48,9 +48,12 @@ public: ...@@ -48,9 +48,12 @@ public:
virtual GLsizei getWidth() const = 0; virtual GLsizei getWidth() const = 0;
virtual GLsizei getHeight() const = 0; virtual GLsizei getHeight() const = 0;
virtual GLint getLevel() const { return 0; }
virtual GLint getFormat() const = 0; virtual GLint getFormat() const = 0;
virtual GLsizei getSamples() const = 0; virtual GLsizei getSamples() const = 0;
virtual void setLevel(GLint) {}
GLuint getRedSize() const; GLuint getRedSize() const;
GLuint getGreenSize() const; GLuint getGreenSize() const;
GLuint getBlueSize() const; GLuint getBlueSize() const;
...@@ -62,24 +65,28 @@ public: ...@@ -62,24 +65,28 @@ public:
class RenderbufferTexture2D : public RenderbufferInterface class RenderbufferTexture2D : public RenderbufferInterface
{ {
public: public:
RenderbufferTexture2D(Texture2D *texture); RenderbufferTexture2D(Texture2D *texture, GLint level);
virtual ~RenderbufferTexture2D(); ~RenderbufferTexture2D() override;
virtual void addProxyRef(const Renderbuffer *proxy); void addProxyRef(const Renderbuffer *proxy) override;
virtual void releaseProxy(const Renderbuffer *proxy); void releaseProxy(const Renderbuffer *proxy) override;
virtual egl::Image *getRenderTarget(); egl::Image *getRenderTarget() override;
virtual egl::Image *createSharedImage(); egl::Image *createSharedImage() override;
virtual bool isShared() const; 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; void setLevel(GLint level) override { mLevel = level; }
virtual GLsizei getHeight() const;
virtual GLint getFormat() const;
virtual GLsizei getSamples() const;
private: private:
gl::BindingPointer<Texture2D> mTexture2D; gl::BindingPointer<Texture2D> mTexture2D;
GLint mLevel;
}; };
// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage // A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
...@@ -90,16 +97,16 @@ class RenderbufferStorage : public RenderbufferInterface ...@@ -90,16 +97,16 @@ class RenderbufferStorage : public RenderbufferInterface
public: public:
RenderbufferStorage(); RenderbufferStorage();
virtual ~RenderbufferStorage() = 0; ~RenderbufferStorage() override = 0;
virtual egl::Image *getRenderTarget() = 0; egl::Image *getRenderTarget() override = 0;
virtual egl::Image *createSharedImage() = 0; egl::Image *createSharedImage() override = 0;
virtual bool isShared() const = 0; bool isShared() const override = 0;
virtual GLsizei getWidth() const; GLsizei getWidth() const override;
virtual GLsizei getHeight() const; GLsizei getHeight() const override;
virtual GLint getFormat() const; GLint getFormat() const override;
virtual GLsizei getSamples() const; GLsizei getSamples() const override;
protected: protected:
GLsizei mWidth; GLsizei mWidth;
...@@ -131,6 +138,7 @@ public: ...@@ -131,6 +138,7 @@ public:
GLsizei getWidth() const; GLsizei getWidth() const;
GLsizei getHeight() const; GLsizei getHeight() const;
GLint getLevel() const;
GLenum getFormat() const; GLenum getFormat() const;
GLuint getRedSize() const; GLuint getRedSize() const;
GLuint getGreenSize() const; GLuint getGreenSize() const;
...@@ -140,6 +148,7 @@ public: ...@@ -140,6 +148,7 @@ public:
GLuint getStencilSize() const; GLuint getStencilSize() const;
GLsizei getSamples() const; GLsizei getSamples() const;
void setLevel(GLint level);
void setStorage(RenderbufferStorage *newStorage); void setStorage(RenderbufferStorage *newStorage);
private: private:
...@@ -152,11 +161,11 @@ public: ...@@ -152,11 +161,11 @@ public:
explicit Colorbuffer(egl::Image *renderTarget); explicit Colorbuffer(egl::Image *renderTarget);
Colorbuffer(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); Colorbuffer(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
virtual ~Colorbuffer(); ~Colorbuffer() override;
virtual egl::Image *getRenderTarget(); egl::Image *getRenderTarget() override;
virtual egl::Image *createSharedImage(); egl::Image *createSharedImage() override;
virtual bool isShared() const; bool isShared() const override;
private: private:
egl::Image *mRenderTarget; egl::Image *mRenderTarget;
...@@ -170,9 +179,9 @@ public: ...@@ -170,9 +179,9 @@ public:
~DepthStencilbuffer(); ~DepthStencilbuffer();
virtual egl::Image *getRenderTarget(); egl::Image *getRenderTarget() override;
virtual egl::Image *createSharedImage(); egl::Image *createSharedImage() override;
virtual bool isShared() const; bool isShared() const override;
protected: protected:
egl::Image *mDepthStencil; egl::Image *mDepthStencil;
...@@ -184,7 +193,7 @@ public: ...@@ -184,7 +193,7 @@ public:
explicit Depthbuffer(egl::Image *depthStencil); explicit Depthbuffer(egl::Image *depthStencil);
Depthbuffer(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); Depthbuffer(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
virtual ~Depthbuffer(); ~Depthbuffer() override;
}; };
class Stencilbuffer : public DepthStencilbuffer class Stencilbuffer : public DepthStencilbuffer
...@@ -193,7 +202,7 @@ public: ...@@ -193,7 +202,7 @@ public:
explicit Stencilbuffer(egl::Image *depthStencil); explicit Stencilbuffer(egl::Image *depthStencil);
Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples); Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
virtual ~Stencilbuffer(); ~Stencilbuffer() override;
}; };
} }
......
...@@ -678,7 +678,7 @@ egl::Image *Texture2D::getImage(unsigned int level) ...@@ -678,7 +678,7 @@ egl::Image *Texture2D::getImage(unsigned int level)
return image[level]; return image[level];
} }
Renderbuffer *Texture2D::getRenderbuffer(GLenum target) Renderbuffer *Texture2D::getRenderbuffer(GLenum target, GLint level)
{ {
if(target != GL_TEXTURE_2D) if(target != GL_TEXTURE_2D)
{ {
...@@ -687,7 +687,11 @@ Renderbuffer *Texture2D::getRenderbuffer(GLenum target) ...@@ -687,7 +687,11 @@ Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
if(!mColorbufferProxy) if(!mColorbufferProxy)
{ {
mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this)); mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this, level));
}
else
{
mColorbufferProxy->setLevel(level);
} }
return mColorbufferProxy; return mColorbufferProxy;
......
...@@ -83,7 +83,7 @@ public: ...@@ -83,7 +83,7 @@ public:
virtual bool isCompressed(GLenum target, GLint level) const = 0; virtual bool isCompressed(GLenum target, GLint level) const = 0;
virtual bool isDepth(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; virtual egl::Image *getRenderTarget(GLenum target, unsigned int level) = 0;
egl::Image *createSharedImage(GLenum target, unsigned int level); egl::Image *createSharedImage(GLenum target, unsigned int level);
virtual bool isShared(GLenum target, unsigned int level) const = 0; virtual bool isShared(GLenum target, unsigned int level) const = 0;
...@@ -153,7 +153,7 @@ public: ...@@ -153,7 +153,7 @@ public:
void generateMipmaps() override; void generateMipmaps() override;
void autoGenerateMipmaps() 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; egl::Image *getRenderTarget(GLenum target, unsigned int level) override;
bool isShared(GLenum target, unsigned int level) const override; bool isShared(GLenum target, unsigned int level) const override;
......
...@@ -1507,7 +1507,7 @@ void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, ...@@ -1507,7 +1507,7 @@ void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget,
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
if(level != 0) if((level < 0) || (level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
{ {
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
...@@ -1528,9 +1528,9 @@ void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, ...@@ -1528,9 +1528,9 @@ void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget,
switch(attachment) switch(attachment)
{ {
case GL_COLOR_ATTACHMENT0_OES: framebuffer->setColorbuffer(textarget, texture); break; case GL_COLOR_ATTACHMENT0_OES: framebuffer->setColorbuffer(textarget, texture, level); break;
case GL_DEPTH_ATTACHMENT_OES: framebuffer->setDepthbuffer(textarget, texture); break; case GL_DEPTH_ATTACHMENT_OES: framebuffer->setDepthbuffer(textarget, texture, level); break;
case GL_STENCIL_ATTACHMENT_OES: framebuffer->setStencilbuffer(textarget, texture); break; case GL_STENCIL_ATTACHMENT_OES: framebuffer->setStencilbuffer(textarget, texture, level); break;
} }
} }
} }
...@@ -2082,19 +2082,23 @@ void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GL ...@@ -2082,19 +2082,23 @@ void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GL
GLenum attachmentType; GLenum attachmentType;
GLuint attachmentHandle; GLuint attachmentHandle;
Renderbuffer *renderbuffer = nullptr;
switch(attachment) switch(attachment)
{ {
case GL_COLOR_ATTACHMENT0_OES: case GL_COLOR_ATTACHMENT0_OES:
attachmentType = framebuffer->getColorbufferType(); attachmentType = framebuffer->getColorbufferType();
attachmentHandle = framebuffer->getColorbufferName(); attachmentHandle = framebuffer->getColorbufferName();
renderbuffer = framebuffer->getColorbuffer();
break; break;
case GL_DEPTH_ATTACHMENT_OES: case GL_DEPTH_ATTACHMENT_OES:
attachmentType = framebuffer->getDepthbufferType(); attachmentType = framebuffer->getDepthbufferType();
attachmentHandle = framebuffer->getDepthbufferName(); attachmentHandle = framebuffer->getDepthbufferName();
renderbuffer = framebuffer->getDepthbuffer();
break; break;
case GL_STENCIL_ATTACHMENT_OES: case GL_STENCIL_ATTACHMENT_OES:
attachmentType = framebuffer->getStencilbufferType(); attachmentType = framebuffer->getStencilbufferType();
attachmentHandle = framebuffer->getStencilbufferName(); attachmentHandle = framebuffer->getStencilbufferName();
renderbuffer = framebuffer->getStencilbuffer();
break; break;
default: default:
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
...@@ -2129,7 +2133,7 @@ void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GL ...@@ -2129,7 +2133,7 @@ void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GL
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES: case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES:
if(attachmentObjectType == GL_TEXTURE) 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 else
{ {
...@@ -2268,6 +2272,7 @@ const GLubyte* GetString(GLenum name) ...@@ -2268,6 +2272,7 @@ const GLubyte* GetString(GLenum name)
"GL_OES_EGL_image_external " "GL_OES_EGL_image_external "
"GL_OES_EGL_sync " "GL_OES_EGL_sync "
"GL_OES_element_index_uint " "GL_OES_element_index_uint "
"GL_OES_fbo_render_mipmap "
"GL_OES_framebuffer_object " "GL_OES_framebuffer_object "
"GL_OES_packed_depth_stencil " "GL_OES_packed_depth_stencil "
"GL_OES_read_format " "GL_OES_read_format "
......
...@@ -4405,6 +4405,7 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const ...@@ -4405,6 +4405,7 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const
"GL_OES_EGL_image_external", "GL_OES_EGL_image_external",
"GL_OES_EGL_sync", "GL_OES_EGL_sync",
"GL_OES_element_index_uint", "GL_OES_element_index_uint",
"GL_OES_fbo_render_mipmap",
"GL_OES_framebuffer_object", "GL_OES_framebuffer_object",
"GL_OES_packed_depth_stencil", "GL_OES_packed_depth_stencil",
"GL_OES_rgb8_rgba8", "GL_OES_rgb8_rgba8",
......
...@@ -78,7 +78,7 @@ RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : ...@@ -78,7 +78,7 @@ RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) :
RenderbufferTexture2D::~RenderbufferTexture2D() RenderbufferTexture2D::~RenderbufferTexture2D()
{ {
mTexture2D = NULL; mTexture2D = nullptr;
} }
// Textures need to maintain their own reference count for references via // Textures need to maintain their own reference count for references via
...@@ -441,7 +441,7 @@ void Renderbuffer::setLevel(GLint level) ...@@ -441,7 +441,7 @@ void Renderbuffer::setLevel(GLint level)
void Renderbuffer::setStorage(RenderbufferStorage *newStorage) void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
{ {
ASSERT(newStorage != NULL); ASSERT(newStorage);
delete mInstance; delete mInstance;
mInstance = newStorage; mInstance = newStorage;
......
...@@ -6006,11 +6006,6 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, ...@@ -6006,11 +6006,6 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget,
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if(tex->isCompressed(textarget, level))
{
return error(GL_INVALID_OPERATION);
}
switch(textarget) switch(textarget)
{ {
case GL_TEXTURE_3D: case GL_TEXTURE_3D:
...@@ -6023,10 +6018,15 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, ...@@ -6023,10 +6018,15 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget,
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
if(level != 0) if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
{ {
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
if(tex->isCompressed(textarget, level))
{
return error(GL_INVALID_OPERATION);
}
} }
es2::Framebuffer *framebuffer = nullptr; es2::Framebuffer *framebuffer = nullptr;
...@@ -6049,14 +6049,14 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, ...@@ -6049,14 +6049,14 @@ void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget,
switch(attachment) switch(attachment)
{ {
case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
default: default:
if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS) if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
{ {
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0); framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
break; 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