Edit

kc3-lang/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp

Branch :

  • Show log

    Commit

  • Author : Austin Kinross
    Date : 2015-05-05 13:35:47
    Hash : 08332634
    Message : Implement EXT_discard_framebuffer in D3D11 renderer Change-Id: I52bcf0cfb1aa123e085a35730fdefb006b617c3c Reviewed-on: https://chromium-review.googlesource.com/269232 Tested-by: Austin Kinross <aukinros@microsoft.com> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • src/libANGLE/renderer/gl/FramebufferGL.cpp
  • //
    // Copyright 2015 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // FramebufferGL.cpp: Implements the class methods for FramebufferGL.
    
    #include "libANGLE/renderer/gl/FramebufferGL.h"
    
    #include "common/debug.h"
    #include "libANGLE/Data.h"
    #include "libANGLE/State.h"
    #include "libANGLE/FramebufferAttachment.h"
    #include "libANGLE/angletypes.h"
    #include "libANGLE/formatutils.h"
    #include "libANGLE/renderer/gl/FunctionsGL.h"
    #include "libANGLE/renderer/gl/RenderbufferGL.h"
    #include "libANGLE/renderer/gl/StateManagerGL.h"
    #include "libANGLE/renderer/gl/TextureGL.h"
    
    namespace rx
    {
    
    FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data, const FunctionsGL *functions, StateManagerGL *stateManager, bool isDefault)
        : FramebufferImpl(data),
          mFunctions(functions),
          mStateManager(stateManager),
          mFramebufferID(0)
    {
        if (!isDefault)
        {
            mFunctions->genFramebuffers(1, &mFramebufferID);
        }
    }
    
    FramebufferGL::~FramebufferGL()
    {
        mStateManager->deleteFramebuffer(mFramebufferID);
        mFramebufferID = 0;
    }
    
    static void BindFramebufferAttachment(const FunctionsGL *functions, GLenum attachmentPoint,
                                          const gl::FramebufferAttachment *attachment)
    {
        if (attachment)
        {
            if (attachment->type() == GL_TEXTURE)
            {
                const gl::Texture *texture = attachment->getTexture();
                const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
    
                if (texture->getTarget() == GL_TEXTURE_2D)
                {
                    functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
                                                    textureGL->getTextureID(), attachment->mipLevel());
                }
                else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
                {
                    functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
                                                    textureGL->getTextureID(), attachment->mipLevel());
                }
                else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
                {
                    functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
                                                       attachment->mipLevel(), attachment->layer());
                }
                else
                {
                    UNREACHABLE();
                }
            }
            else if (attachment->type() == GL_RENDERBUFFER)
            {
                const gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
                const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
    
                functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
                                                   renderbufferGL->getRenderbufferID());
            }
            else
            {
                UNREACHABLE();
            }
        }
        else
        {
            // Unbind this attachment
            functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
        }
    }
    
    void FramebufferGL::onUpdateColorAttachment(size_t index)
    {
        if (mFramebufferID != 0)
        {
            mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
            BindFramebufferAttachment(mFunctions,
                                      GL_COLOR_ATTACHMENT0 + index,
                                      mData.getColorAttachment(static_cast<unsigned int>(index)));
        }
    }
    
    void FramebufferGL::onUpdateDepthAttachment()
    {
        if (mFramebufferID != 0)
        {
            mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
            BindFramebufferAttachment(mFunctions,
                                      GL_DEPTH_ATTACHMENT,
                                      mData.getDepthAttachment());
        }
    }
    
    void FramebufferGL::onUpdateStencilAttachment()
    {
        if (mFramebufferID != 0)
        {
            mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
            BindFramebufferAttachment(mFunctions,
                                      GL_STENCIL_ATTACHMENT,
                                      mData.getStencilAttachment());
        }
    }
    
    void FramebufferGL::onUpdateDepthStencilAttachment()
    {
        if (mFramebufferID != 0)
        {
            mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
            BindFramebufferAttachment(mFunctions,
                                      GL_DEPTH_STENCIL_ATTACHMENT,
                                      mData.getDepthStencilAttachment());
        }
    }
    
    void FramebufferGL::setDrawBuffers(size_t count, const GLenum *buffers)
    {
        if (mFramebufferID != 0)
        {
            mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
            mFunctions->drawBuffers(count, buffers);
        }
    }
    
    void FramebufferGL::setReadBuffer(GLenum buffer)
    {
        if (mFramebufferID != 0)
        {
            mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
            mFunctions->readBuffer(buffer);
        }
    }
    
    gl::Error FramebufferGL::discard(size_t count, const GLenum *attachments)
    {
        UNIMPLEMENTED();
        return gl::Error(GL_INVALID_OPERATION);
    }
    
    gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
    {
        // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
        if (mFunctions->invalidateFramebuffer)
        {
            mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
            mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
        }
    
        return gl::Error(GL_NO_ERROR);
    }
    
    gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
    {
        // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
        if (mFunctions->invalidateSubFramebuffer)
        {
            mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
            mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, count, attachments, area.x, area.y, area.width, area.height);
        }
    
        return gl::Error(GL_NO_ERROR);
    }
    
    gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
    {
        mStateManager->setClearState(*data.state, mask);
        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
        mFunctions->clear(mask);
    
        return gl::Error(GL_NO_ERROR);
    }
    
    static GLbitfield GetClearBufferMask(GLenum buffer)
    {
        switch (buffer)
        {
          case GL_COLOR:          return GL_COLOR_BUFFER_BIT;
          case GL_DEPTH:          return GL_DEPTH_BUFFER_BIT;
          case GL_STENCIL:        return GL_STENCIL_BUFFER_BIT;
          case GL_DEPTH_STENCIL:  return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
          default: UNREACHABLE(); return 0;
        }
    }
    
    gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
    {
        mStateManager->setClearState(state, GetClearBufferMask(buffer));
        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
        mFunctions->clearBufferfv(buffer, drawbuffer, values);
    
        return gl::Error(GL_NO_ERROR);
    }
    
    gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
    {
        mStateManager->setClearState(state, GetClearBufferMask(buffer));
        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
        mFunctions->clearBufferuiv(buffer, drawbuffer, values);
    
        return gl::Error(GL_NO_ERROR);
    }
    
    gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
    {
        mStateManager->setClearState(state, GetClearBufferMask(buffer));
        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
        mFunctions->clearBufferiv(buffer, drawbuffer, values);
    
        return gl::Error(GL_NO_ERROR);
    }
    
    gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
    {
        mStateManager->setClearState(state, GetClearBufferMask(buffer));
        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
        mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
    
        return gl::Error(GL_NO_ERROR);
    }
    
    GLenum FramebufferGL::getImplementationColorReadFormat() const
    {
        const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
        GLenum internalFormat = readAttachment->getInternalFormat();
        const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
        return internalFormatInfo.format;
    }
    
    GLenum FramebufferGL::getImplementationColorReadType() const
    {
        const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
        GLenum internalFormat = readAttachment->getInternalFormat();
        const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
        return internalFormatInfo.type;
    }
    
    gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
    {
        const gl::PixelPackState &packState = state.getPackState();
    
        // TODO: set pack state
        if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
        {
            UNIMPLEMENTED();
            return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
        }
    
        mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
        mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
    
        return gl::Error(GL_NO_ERROR);
    }
    
    gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
                                  GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
    {
        const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
    
        mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
        mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
    
        mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
                                    destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
                                    mask, filter);
    
        return gl::Error(GL_NO_ERROR);
    }
    
    GLenum FramebufferGL::checkStatus() const
    {
        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
        return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
    }
    
    GLuint FramebufferGL::getFramebufferID() const
    {
        return mFramebufferID;
    }
    
    }