Hash :
888081d5
        
        Author :
  
        
        Date :
2018-02-27T00:24:46
        
      
D3D11: Refactor dependent Framebuffer state changes. Previously, when a state change would cause a Texture to recreate its storage specific to D3D11, we would use a dependent notification from RenderTarget11 to Framebuffer11 to re-check internal dirty bits. In this new method, we instead set dirty bits on the gl::Frambuffer directly. This also means we use fewer internal objects for these notifications, because we share the same structures between the D3D11 back-end notifications and the top-level notifications we use for Robust init and Framebuffer completeness. This also allows us to get rid of one "if" that we check on every draw call in D3D11. This also introduces a dirty bits guard concept - a shadow set of dirty bits that is checked in dependent state changes to ensure that extra bits aren't set inside syncState. This also implements Framebuffer dirty bits for the D3D9 back-end. This has the side effect of cleaning up the "null colorbuffer" D3D9 workaround. Bug: angleproject:2372 Change-Id: Ie346d39030f4f6df583d735685b0babea4e745a8 Reviewed-on: https://chromium-review.googlesource.com/936691 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
//
// Copyright (c) 2014 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.
//
// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl
#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/Image.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
namespace rx
{
RenderbufferD3D::RenderbufferD3D(const gl::RenderbufferState &state, RendererD3D *renderer)
    : RenderbufferImpl(state), mRenderer(renderer), mRenderTarget(nullptr), mImage(nullptr)
{
}
RenderbufferD3D::~RenderbufferD3D()
{
    SafeDelete(mRenderTarget);
    mImage = nullptr;
}
gl::Error RenderbufferD3D::onDestroy(const gl::Context *context)
{
    deleteRenderTarget(context);
    return gl::NoError();
}
gl::Error RenderbufferD3D::setStorage(const gl::Context *context,
                                      GLenum internalformat,
                                      size_t width,
                                      size_t height)
{
    return setStorageMultisample(context, 0, internalformat, width, height);
}
gl::Error RenderbufferD3D::setStorageMultisample(const gl::Context *context,
                                                 size_t samples,
                                                 GLenum internalformat,
                                                 size_t width,
                                                 size_t height)
{
    // If the renderbuffer parameters are queried, the calling function
    // will expect one of the valid renderbuffer formats for use in
    // glRenderbufferStorage, but we should create depth and stencil buffers
    // as DEPTH24_STENCIL8
    GLenum creationFormat = internalformat;
    if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8)
    {
        creationFormat = GL_DEPTH24_STENCIL8_OES;
    }
    // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
    // the specified storage.
    // Because ES 3.0 already knows the exact number of supported samples, it would already have been
    // validated and generated GL_INVALID_VALUE.
    const gl::TextureCaps &formatCaps = mRenderer->getNativeTextureCaps().get(creationFormat);
    if (samples > formatCaps.getMaxSamples())
    {
        return gl::OutOfMemory() << "Renderbuffer format does not support " << samples
                                 << " samples, " << formatCaps.getMaxSamples()
                                 << " is the maximum.";
    }
    RenderTargetD3D *newRT = nullptr;
    ANGLE_TRY(mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height),
                                            creationFormat, static_cast<GLsizei>(samples), &newRT));
    deleteRenderTarget(context);
    mImage        = nullptr;
    mRenderTarget = newRT;
    return gl::NoError();
}
gl::Error RenderbufferD3D::setStorageEGLImageTarget(const gl::Context *context, egl::Image *image)
{
    mImage = GetImplAs<EGLImageD3D>(image);
    deleteRenderTarget(context);
    return gl::NoError();
}
gl::Error RenderbufferD3D::getRenderTarget(const gl::Context *context,
                                           RenderTargetD3D **outRenderTarget)
{
    if (mImage)
    {
        return mImage->getRenderTarget(context, outRenderTarget);
    }
    else
    {
        *outRenderTarget = mRenderTarget;
        return gl::NoError();
    }
}
gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::Context *context,
                                                     GLenum /*binding*/,
                                                     const gl::ImageIndex & /*imageIndex*/,
                                                     FramebufferAttachmentRenderTarget **rtOut)
{
    return getRenderTarget(context, reinterpret_cast<RenderTargetD3D **>(rtOut));
}
void RenderbufferD3D::deleteRenderTarget(const gl::Context *context)
{
    onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
    if (mRenderTarget)
    {
        SafeDelete(mRenderTarget);
    }
}
gl::Error RenderbufferD3D::initializeContents(const gl::Context *context,
                                              const gl::ImageIndex &imageIndex)
{
    RenderTargetD3D *renderTarget = nullptr;
    ANGLE_TRY(getRenderTarget(context, &renderTarget));
    return mRenderer->initRenderTarget(renderTarget);
}
}  // namespace rx