summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp')
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp463
1 files changed, 463 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
new file mode 100644
index 0000000000..1a4734b269
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -0,0 +1,463 @@
+//
+// Copyright 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.
+//
+
+// FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes.
+
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+namespace rx
+{
+
+namespace
+{
+
+ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
+{
+ ClearParameters clearParams;
+ memset(&clearParams, 0, sizeof(ClearParameters));
+
+ const auto &blendState = state.getBlendState();
+
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = false;
+ }
+ clearParams.colorFClearValue = state.getColorClearValue();
+ clearParams.colorClearType = GL_FLOAT;
+ clearParams.colorMaskRed = blendState.colorMaskRed;
+ clearParams.colorMaskGreen = blendState.colorMaskGreen;
+ clearParams.colorMaskBlue = blendState.colorMaskBlue;
+ clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
+ clearParams.clearDepth = false;
+ clearParams.depthClearValue = state.getDepthClearValue();
+ clearParams.clearStencil = false;
+ clearParams.stencilClearValue = state.getStencilClearValue();
+ clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
+ clearParams.scissorEnabled = state.isScissorTestEnabled();
+ clearParams.scissor = state.getScissor();
+
+ const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ if (framebufferObject->hasEnabledColorAttachment())
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = true;
+ }
+ }
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
+ {
+ clearParams.clearDepth = true;
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ if (framebufferObject->getStencilbuffer() != NULL &&
+ framebufferObject->getStencilbuffer()->getStencilSize() > 0)
+ {
+ clearParams.clearStencil = true;
+ }
+ }
+
+ return clearParams;
+}
+
+}
+
+FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
+ : FramebufferImpl(data),
+ mRenderer(renderer),
+ mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr),
+ mInvalidateColorAttachmentCache(true)
+{
+ ASSERT(mRenderer != nullptr);
+}
+
+FramebufferD3D::~FramebufferD3D()
+{
+}
+
+void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *)
+{
+ mInvalidateColorAttachmentCache = true;
+}
+
+void FramebufferD3D::setDepthAttachment(const gl::FramebufferAttachment *)
+{
+}
+
+void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *)
+{
+}
+
+void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *)
+{
+}
+
+void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
+{
+ mInvalidateColorAttachmentCache = true;
+}
+
+void FramebufferD3D::setReadBuffer(GLenum)
+{
+}
+
+gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
+{
+ // No-op in D3D
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+{
+ // No-op in D3D
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask)
+{
+ const gl::State &state = *data.state;
+ ClearParameters clearParams = GetClearParameters(state, mask);
+ return clear(state, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
+{
+ // glClearBufferfv can be called to clear the color buffer or depth buffer
+ ClearParameters clearParams = GetClearParameters(state, 0);
+
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_FLOAT;
+ }
+
+ if (buffer == GL_DEPTH)
+ {
+ clearParams.clearDepth = true;
+ clearParams.depthClearValue = values[0];
+ }
+
+ return clear(state, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
+{
+ // glClearBufferuiv can only be called to clear a color buffer
+ ClearParameters clearParams = GetClearParameters(state, 0);
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_UNSIGNED_INT;
+
+ return clear(state, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
+{
+ // glClearBufferiv can be called to clear the color buffer or stencil buffer
+ ClearParameters clearParams = GetClearParameters(state, 0);
+
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_INT;
+ }
+
+ if (buffer == GL_STENCIL)
+ {
+ clearParams.clearStencil = true;
+ clearParams.stencilClearValue = values[1];
+ }
+
+ return clear(state, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ // glClearBufferfi can only be called to clear a depth stencil buffer
+ ClearParameters clearParams = GetClearParameters(state, 0);
+ clearParams.clearDepth = true;
+ clearParams.depthClearValue = depth;
+ clearParams.clearStencil = true;
+ clearParams.stencilClearValue = stencil;
+
+ return clear(state, clearParams);
+}
+
+GLenum FramebufferD3D::getImplementationColorReadFormat() const
+{
+ const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
+
+ if (readAttachment == nullptr)
+ {
+ return GL_NONE;
+ }
+
+ RenderTargetD3D *attachmentRenderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
+ if (error.isError())
+ {
+ return GL_NONE;
+ }
+
+ GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
+ const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
+
+ return implementationFormatInfo.format;
+}
+
+GLenum FramebufferD3D::getImplementationColorReadType() const
+{
+ const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
+
+ if (readAttachment == nullptr)
+ {
+ return GL_NONE;
+ }
+
+ RenderTargetD3D *attachmentRenderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
+ if (error.isError())
+ {
+ return GL_NONE;
+ }
+
+ GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
+ const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
+
+ return implementationFormatInfo.type;
+}
+
+gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
+{
+ const gl::PixelPackState &packState = state.getPackState();
+
+ if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
+ }
+
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
+ const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
+ GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0);
+
+ return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels));
+}
+
+gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
+ GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
+{
+ bool blitRenderTarget = false;
+ if ((mask & GL_COLOR_BUFFER_BIT) &&
+ sourceFramebuffer->getReadColorbuffer() != nullptr &&
+ mData.getFirstColorAttachment() != nullptr)
+ {
+ blitRenderTarget = true;
+ }
+
+ bool blitStencil = false;
+ if ((mask & GL_STENCIL_BUFFER_BIT) &&
+ sourceFramebuffer->getStencilbuffer() != nullptr &&
+ mData.mStencilAttachment != nullptr)
+ {
+ blitStencil = true;
+ }
+
+ bool blitDepth = false;
+ if ((mask & GL_DEPTH_BUFFER_BIT) &&
+ sourceFramebuffer->getDepthbuffer() != nullptr &&
+ mData.mDepthAttachment != nullptr)
+ {
+ blitDepth = true;
+ }
+
+ if (blitRenderTarget || blitDepth || blitStencil)
+ {
+ const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
+ gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
+ filter, sourceFramebuffer);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLenum FramebufferD3D::checkStatus() const
+{
+ // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
+ for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++)
+ {
+ const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment];
+ if (attachment != nullptr)
+ {
+ for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
+ {
+ const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment];
+ if (prevAttachment != nullptr &&
+ (attachment->id() == prevAttachment->id() &&
+ attachment->type() == prevAttachment->type()))
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+ }
+ }
+
+ return GL_FRAMEBUFFER_COMPLETE;
+}
+
+const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const
+{
+ if (!workarounds.mrtPerfWorkaround)
+ {
+ return mData.mColorAttachments;
+ }
+
+ if (!mInvalidateColorAttachmentCache)
+ {
+ return mColorAttachmentsForRender;
+ }
+
+ // Does not actually free memory
+ mColorAttachmentsForRender.clear();
+
+ for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex)
+ {
+ GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex];
+ gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex];
+
+ if (colorAttachment != nullptr && drawBufferState != GL_NONE)
+ {
+ ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
+ mColorAttachmentsForRender.push_back(colorAttachment);
+ }
+ }
+
+ mInvalidateColorAttachmentCache = false;
+ return mColorAttachmentsForRender;
+}
+
+gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT)
+{
+ if (attachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *texture = attachment->getTexture();
+ ASSERT(texture);
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ const gl::ImageIndex *index = attachment->getTextureImageIndex();
+ ASSERT(index);
+ return textureD3D->getRenderTarget(*index, outRT);
+ }
+ else if (attachment->type() == GL_RENDERBUFFER)
+ {
+ gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+ ASSERT(renderbuffer);
+ RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
+ *outRT = renderbufferD3D->getRenderTarget();
+ return gl::Error(GL_NO_ERROR);
+ }
+ else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
+ {
+ const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
+ const egl::Surface *surface = defaultAttachment->getSurface();
+ ASSERT(surface);
+ const SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ASSERT(surfaceD3D);
+
+ if (defaultAttachment->getBinding() == GL_BACK)
+ {
+ *outRT = surfaceD3D->getSwapChain()->getColorRenderTarget();
+ }
+ else
+ {
+ *outRT = surfaceD3D->getSwapChain()->getDepthStencilRenderTarget();
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+}
+
+// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
+unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
+{
+ if (attachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *texture = attachment->getTexture();
+ ASSERT(texture);
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ const gl::ImageIndex *index = attachment->getTextureImageIndex();
+ ASSERT(index);
+ return textureD3D->getRenderTargetSerial(*index);
+ }
+ else if (attachment->type() == GL_RENDERBUFFER)
+ {
+ gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+ ASSERT(renderbuffer);
+ RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
+ return renderbufferD3D->getRenderTargetSerial();
+ }
+ else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
+ {
+ const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
+ const egl::Surface *surface = defaultAttachment->getSurface();
+ ASSERT(surface);
+ const SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ASSERT(surfaceD3D);
+
+ if (defaultAttachment->getBinding() == GL_BACK)
+ {
+ return surfaceD3D->getSwapChain()->getColorRenderTarget()->getSerial();
+ }
+ else
+ {
+ return surfaceD3D->getSwapChain()->getDepthStencilRenderTarget()->getSerial();
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+}