Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2018-04-12 09:13:18
    Hash : cc129377
    Message : ImageIndex: Consolidate layer/cube face. In terms of the Texture or Image resource, a cube face refers to a layer of a 2D texture. This layer has a special meaning for cube textures, but it is represented as a layer with a layer index. Cube array textures are no different, they just use a different indexing scheme for the array layers. This also cleans up the ImageIndex helper to have a class structure with private data, and cleans up a few cases to use generic Make functions and iterators where they were setting properties of the index directly. This will make it easier to have ImageIndexes address entire levels of a Cube map in the future, and makes the layer count logic in Vulkan cleaner. Bug: angleproject:2318 Change-Id: Iea9842e233f974a9896282ca224cb001f7882bd1 Reviewed-on: https://chromium-review.googlesource.com/987525 Reviewed-by: Luc Ferron <lucferron@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/renderer/gl/ClearMultiviewGL.cpp
  • //
    // Copyright 2017 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.
    //
    // ClearMultiviewGL:
    //   A helper for clearing multiview side-by-side and layered framebuffers.
    //
    
    #include "libANGLE/renderer/gl/ClearMultiviewGL.h"
    #include "libANGLE/renderer/gl/FunctionsGL.h"
    #include "libANGLE/renderer/gl/StateManagerGL.h"
    #include "libANGLE/renderer/gl/TextureGL.h"
    
    #include "libANGLE/Framebuffer.h"
    
    namespace rx
    {
    
    ClearMultiviewGL::ClearMultiviewGL(const FunctionsGL *functions, StateManagerGL *stateManager)
        : mFunctions(functions), mStateManager(stateManager), mFramebuffer(0u)
    {
    }
    
    ClearMultiviewGL::~ClearMultiviewGL()
    {
        if (mFramebuffer != 0u)
        {
            mFunctions->deleteFramebuffers(1, &mFramebuffer);
        }
    }
    
    void ClearMultiviewGL::clearMultiviewFBO(const gl::FramebufferState &state,
                                             const gl::Rectangle &scissorBase,
                                             ClearCommandType clearCommandType,
                                             GLbitfield mask,
                                             GLenum buffer,
                                             GLint drawbuffer,
                                             const uint8_t *values,
                                             GLfloat depth,
                                             GLint stencil)
    {
        const gl::FramebufferAttachment *firstAttachment = state.getFirstNonNullAttachment();
        switch (firstAttachment->getMultiviewLayout())
        {
            case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
                clearLayeredFBO(state, clearCommandType, mask, buffer, drawbuffer, values, depth,
                                stencil);
                break;
            case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
                clearSideBySideFBO(state, scissorBase, clearCommandType, mask, buffer, drawbuffer,
                                   values, depth, stencil);
                break;
            default:
                UNREACHABLE();
        }
    }
    
    void ClearMultiviewGL::clearLayeredFBO(const gl::FramebufferState &state,
                                           ClearCommandType clearCommandType,
                                           GLbitfield mask,
                                           GLenum buffer,
                                           GLint drawbuffer,
                                           const uint8_t *values,
                                           GLfloat depth,
                                           GLint stencil)
    {
        initializeResources();
    
        mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
    
        const gl::FramebufferAttachment *firstAttachment = state.getFirstNonNullAttachment();
        ASSERT(firstAttachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE);
    
        const auto &drawBuffers = state.getDrawBufferStates();
        mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
    
        // Attach the new attachments and clear.
        int numViews      = firstAttachment->getNumViews();
        int baseViewIndex = firstAttachment->getBaseViewIndex();
        for (int i = 0; i < numViews; ++i)
        {
            attachTextures(state, baseViewIndex + i);
            genericClear(clearCommandType, mask, buffer, drawbuffer, values, depth, stencil);
        }
    
        detachTextures(state);
    }
    
    void ClearMultiviewGL::clearSideBySideFBO(const gl::FramebufferState &state,
                                              const gl::Rectangle &scissorBase,
                                              ClearCommandType clearCommandType,
                                              GLbitfield mask,
                                              GLenum buffer,
                                              GLint drawbuffer,
                                              const uint8_t *values,
                                              GLfloat depth,
                                              GLint stencil)
    {
        const gl::FramebufferAttachment *firstAttachment = state.getFirstNonNullAttachment();
        ASSERT(firstAttachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
    
        const auto &viewportOffsets = firstAttachment->getMultiviewViewportOffsets();
        for (size_t i = 0u; i < viewportOffsets.size(); ++i)
        {
            gl::Rectangle scissor(scissorBase.x + viewportOffsets[i].x,
                                  scissorBase.y + viewportOffsets[i].y, scissorBase.width,
                                  scissorBase.height);
            mStateManager->setScissorIndexed(0u, scissor);
            genericClear(clearCommandType, mask, buffer, drawbuffer, values, depth, stencil);
        }
    }
    
    void ClearMultiviewGL::genericClear(ClearCommandType clearCommandType,
                                        GLbitfield mask,
                                        GLenum buffer,
                                        GLint drawbuffer,
                                        const uint8_t *values,
                                        GLfloat depth,
                                        GLint stencil)
    {
        switch (clearCommandType)
        {
            case ClearCommandType::Clear:
                mFunctions->clear(mask);
                break;
            case ClearCommandType::ClearBufferfv:
                mFunctions->clearBufferfv(buffer, drawbuffer,
                                          reinterpret_cast<const GLfloat *>(values));
                break;
            case ClearCommandType::ClearBufferuiv:
                mFunctions->clearBufferuiv(buffer, drawbuffer,
                                           reinterpret_cast<const GLuint *>(values));
                break;
            case ClearCommandType::ClearBufferiv:
                mFunctions->clearBufferiv(buffer, drawbuffer, reinterpret_cast<const GLint *>(values));
                break;
            case ClearCommandType::ClearBufferfi:
                mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
                break;
            default:
                UNREACHABLE();
        }
    }
    
    void ClearMultiviewGL::attachTextures(const gl::FramebufferState &state, int layer)
    {
        for (auto drawBufferId : state.getEnabledDrawBuffers())
        {
            const gl::FramebufferAttachment *attachment = state.getColorAttachment(drawBufferId);
            if (attachment == nullptr)
            {
                continue;
            }
    
            const auto &imageIndex = attachment->getTextureImageIndex();
            ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
    
            GLenum colorAttachment =
                static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + static_cast<int>(drawBufferId));
            const TextureGL *textureGL = GetImplAs<TextureGL>(attachment->getTexture());
            mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment,
                                                textureGL->getTextureID(), imageIndex.getLevelIndex(),
                                                layer);
        }
    
        const gl::FramebufferAttachment *depthStencilAttachment = state.getDepthStencilAttachment();
        const gl::FramebufferAttachment *depthAttachment        = state.getDepthAttachment();
        const gl::FramebufferAttachment *stencilAttachment      = state.getStencilAttachment();
        if (depthStencilAttachment != nullptr)
        {
            const auto &imageIndex = depthStencilAttachment->getTextureImageIndex();
            ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
    
            const TextureGL *textureGL = GetImplAs<TextureGL>(depthStencilAttachment->getTexture());
            mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
                                                textureGL->getTextureID(), imageIndex.getLevelIndex(),
                                                layer);
        }
        else if (depthAttachment != nullptr)
        {
            const auto &imageIndex = depthAttachment->getTextureImageIndex();
            ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
    
            const TextureGL *textureGL = GetImplAs<TextureGL>(depthAttachment->getTexture());
            mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                                                textureGL->getTextureID(), imageIndex.getLevelIndex(),
                                                layer);
        }
        else if (stencilAttachment != nullptr)
        {
            const auto &imageIndex = stencilAttachment->getTextureImageIndex();
            ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
    
            const TextureGL *textureGL = GetImplAs<TextureGL>(stencilAttachment->getTexture());
            mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                                                textureGL->getTextureID(), imageIndex.getLevelIndex(),
                                                layer);
        }
    }
    
    void ClearMultiviewGL::detachTextures(const gl::FramebufferState &state)
    {
        for (auto drawBufferId : state.getEnabledDrawBuffers())
        {
            const gl::FramebufferAttachment *attachment = state.getColorAttachment(drawBufferId);
            if (attachment == nullptr)
            {
                continue;
            }
    
            GLenum colorAttachment =
                static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + static_cast<int>(drawBufferId));
            mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment, 0, 0, 0);
        }
    
        const gl::FramebufferAttachment *depthStencilAttachment = state.getDepthStencilAttachment();
        const gl::FramebufferAttachment *depthAttachment        = state.getDepthAttachment();
        const gl::FramebufferAttachment *stencilAttachment      = state.getStencilAttachment();
        if (depthStencilAttachment != nullptr)
        {
            mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0,
                                                0);
        }
        else if (depthAttachment != nullptr)
        {
            mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, 0, 0);
        }
        else if (stencilAttachment != nullptr)
        {
            mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, 0, 0, 0);
        }
    }
    
    void ClearMultiviewGL::initializeResources()
    {
        if (mFramebuffer == 0u)
        {
            mFunctions->genFramebuffers(1, &mFramebuffer);
        }
        ASSERT(mFramebuffer != 0u);
    }
    
    }  // namespace rx