summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp')
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp416
1 files changed, 416 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
new file mode 100644
index 0000000000..f90fefac20
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -0,0 +1,416 @@
+//
+// 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.
+//
+
+// Framebuffer9.cpp: Implements the Framebuffer9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer)
+ : FramebufferD3D(data, renderer), mRenderer(renderer)
+{
+ ASSERT(mRenderer != nullptr);
+}
+
+Framebuffer9::~Framebuffer9() {}
+
+angle::Result Framebuffer9::discard(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Framebuffer9::invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Framebuffer9::invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Framebuffer9::clearImpl(const gl::Context *context,
+ const ClearParameters &clearParams)
+{
+ ANGLE_TRY(mRenderer->applyRenderTarget(context, mRenderTargetCache.getColors()[0],
+ mRenderTargetCache.getDepthStencil()));
+
+ const gl::State &glState = context->getState();
+ float nearZ = glState.getNearPlane();
+ float farZ = glState.getFarPlane();
+ mRenderer->setViewport(glState.getViewport(), nearZ, farZ, gl::PrimitiveMode::Triangles,
+ glState.getRasterizerState().frontFace, true);
+
+ mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+
+ mRenderer->clear(clearParams, mRenderTargetCache.getColors()[0],
+ mRenderTargetCache.getDepthStencil());
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer9::readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBuffer,
+ uint8_t *pixels)
+{
+ const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0);
+ ASSERT(colorbuffer);
+
+ RenderTarget9 *renderTarget = nullptr;
+ ANGLE_TRY(colorbuffer->getRenderTarget(context, 0, &renderTarget));
+ ASSERT(renderTarget);
+
+ IDirect3DSurface9 *surface = renderTarget->getSurface();
+ ASSERT(surface);
+
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+ {
+ UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render
+ // target
+ SafeRelease(surface);
+ ANGLE_TRY_HR(context9, E_OUTOFMEMORY,
+ "ReadPixels is unimplemented for multisampled framebuffer attachments.");
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ ASSERT(device);
+
+ HRESULT result;
+ IDirect3DSurface9 *systemSurface = nullptr;
+ bool directToPixels =
+ !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() &&
+ area.x == 0 && area.y == 0 && static_cast<UINT>(area.width) == desc.Width &&
+ static_cast<UINT>(area.height) == desc.Height && desc.Format == D3DFMT_A8R8G8B8 &&
+ format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
+ if (directToPixels)
+ {
+ // Use the pixels ptr as a shared handle to write directly into client's memory
+ result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface,
+ reinterpret_cast<void **>(&pixels));
+ if (FAILED(result))
+ {
+ // Try again without the shared handle
+ directToPixels = false;
+ }
+ }
+
+ if (!directToPixels)
+ {
+ result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface, nullptr);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ SafeRelease(surface);
+ ANGLE_TRY_HR(context9, E_OUTOFMEMORY,
+ "Failed to allocate internal texture for ReadPixels.");
+ }
+ }
+
+ result = device->GetRenderTargetData(surface, systemSurface);
+ SafeRelease(surface);
+
+ if (FAILED(result))
+ {
+ SafeRelease(systemSurface);
+
+ // It turns out that D3D will sometimes produce more error
+ // codes than those documented.
+ if (d3d9::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ ANGLE_TRY_HR(context9, E_OUTOFMEMORY, "Failed to read internal render target data.");
+ }
+
+ if (directToPixels)
+ {
+ SafeRelease(systemSurface);
+ return angle::Result::Continue;
+ }
+
+ RECT rect;
+ rect.left = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width));
+ rect.top = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height));
+ rect.right = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width));
+ rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height));
+
+ D3DLOCKED_RECT lock;
+ result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
+
+ if (FAILED(result))
+ {
+ UNREACHABLE();
+ SafeRelease(systemSurface);
+
+ ANGLE_TRY_HR(context9, E_OUTOFMEMORY, "Failed to lock internal render target.");
+ }
+
+ uint8_t *source = static_cast<uint8_t *>(lock.pBits);
+ int inputPitch = lock.Pitch;
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+
+ gl::FormatType formatType(format, type);
+
+ PackPixelsParams packParams;
+ packParams.area.x = rect.left;
+ packParams.area.y = rect.top;
+ packParams.area.width = rect.right - rect.left;
+ packParams.area.height = rect.bottom - rect.top;
+ packParams.destFormat = &GetFormatFromFormatType(format, type);
+ packParams.outputPitch = static_cast<GLuint>(outputPitch);
+ packParams.reverseRowOrder = pack.reverseRowOrder;
+
+ PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels);
+
+ systemSurface->UnlockRect();
+ SafeRelease(systemSurface);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer9::blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer)
+{
+ ASSERT(filter == GL_NEAREST);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ ASSERT(device);
+
+ mRenderer->endScene();
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ if (blitRenderTarget)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorAttachment(0);
+ ASSERT(readBuffer);
+
+ RenderTarget9 *readRenderTarget = nullptr;
+ ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readRenderTarget));
+ ASSERT(readRenderTarget);
+
+ const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0);
+ ASSERT(drawBuffer);
+
+ RenderTarget9 *drawRenderTarget = nullptr;
+ ANGLE_TRY(
+ drawBuffer->getRenderTarget(context, drawBuffer->getSamples(), &drawRenderTarget));
+ ASSERT(drawRenderTarget);
+
+ // The getSurface calls do an AddRef so save them until after no errors are possible
+ IDirect3DSurface9 *readSurface = readRenderTarget->getSurface();
+ ASSERT(readSurface);
+
+ IDirect3DSurface9 *drawSurface = drawRenderTarget->getSurface();
+ ASSERT(drawSurface);
+
+ gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+ gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+
+ RECT srcRect;
+ srcRect.left = sourceArea.x;
+ srcRect.right = sourceArea.x + sourceArea.width;
+ srcRect.top = sourceArea.y;
+ srcRect.bottom = sourceArea.y + sourceArea.height;
+
+ RECT dstRect;
+ dstRect.left = destArea.x;
+ dstRect.right = destArea.x + destArea.width;
+ dstRect.top = destArea.y;
+ dstRect.bottom = destArea.y + destArea.height;
+
+ // Clip the rectangles to the scissor rectangle
+ if (scissor)
+ {
+ if (dstRect.left < scissor->x)
+ {
+ srcRect.left += (scissor->x - dstRect.left);
+ dstRect.left = scissor->x;
+ }
+ if (dstRect.top < scissor->y)
+ {
+ srcRect.top += (scissor->y - dstRect.top);
+ dstRect.top = scissor->y;
+ }
+ if (dstRect.right > scissor->x + scissor->width)
+ {
+ srcRect.right -= (dstRect.right - (scissor->x + scissor->width));
+ dstRect.right = scissor->x + scissor->width;
+ }
+ if (dstRect.bottom > scissor->y + scissor->height)
+ {
+ srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height));
+ dstRect.bottom = scissor->y + scissor->height;
+ }
+ }
+
+ // Clip the rectangles to the destination size
+ if (dstRect.left < 0)
+ {
+ srcRect.left += -dstRect.left;
+ dstRect.left = 0;
+ }
+ if (dstRect.right > dstSize.width)
+ {
+ srcRect.right -= (dstRect.right - dstSize.width);
+ dstRect.right = dstSize.width;
+ }
+ if (dstRect.top < 0)
+ {
+ srcRect.top += -dstRect.top;
+ dstRect.top = 0;
+ }
+ if (dstRect.bottom > dstSize.height)
+ {
+ srcRect.bottom -= (dstRect.bottom - dstSize.height);
+ dstRect.bottom = dstSize.height;
+ }
+
+ // Clip the rectangles to the source size
+ if (srcRect.left < 0)
+ {
+ dstRect.left += -srcRect.left;
+ srcRect.left = 0;
+ }
+ if (srcRect.right > srcSize.width)
+ {
+ dstRect.right -= (srcRect.right - srcSize.width);
+ srcRect.right = srcSize.width;
+ }
+ if (srcRect.top < 0)
+ {
+ dstRect.top += -srcRect.top;
+ srcRect.top = 0;
+ }
+ if (srcRect.bottom > srcSize.height)
+ {
+ dstRect.bottom -= (srcRect.bottom - srcSize.height);
+ srcRect.bottom = srcSize.height;
+ }
+
+ HRESULT result =
+ device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
+
+ SafeRelease(readSurface);
+ SafeRelease(drawSurface);
+
+ ANGLE_TRY_HR(context9, result, "Internal blit failed.");
+ }
+
+ if (blitDepth || blitStencil)
+ {
+ const gl::FramebufferAttachment *readBuffer =
+ sourceFramebuffer->getDepthOrStencilAttachment();
+ ASSERT(readBuffer);
+
+ RenderTarget9 *readDepthStencil = nullptr;
+ ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readDepthStencil));
+ ASSERT(readDepthStencil);
+
+ const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
+ ASSERT(drawBuffer);
+
+ RenderTarget9 *drawDepthStencil = nullptr;
+ ANGLE_TRY(
+ drawBuffer->getRenderTarget(context, drawBuffer->getSamples(), &drawDepthStencil));
+ ASSERT(drawDepthStencil);
+
+ // The getSurface calls do an AddRef so save them until after no errors are possible
+ IDirect3DSurface9 *readSurface = readDepthStencil->getSurface();
+ ASSERT(readDepthStencil);
+
+ IDirect3DSurface9 *drawSurface = drawDepthStencil->getSurface();
+ ASSERT(drawDepthStencil);
+
+ HRESULT result =
+ device->StretchRect(readSurface, nullptr, drawSurface, nullptr, D3DTEXF_NONE);
+
+ SafeRelease(readSurface);
+ SafeRelease(drawSurface);
+
+ ANGLE_TRY_HR(context9, result, "Internal blit failed.");
+ }
+
+ return angle::Result::Continue;
+}
+
+const gl::InternalFormat &Framebuffer9::getImplementationColorReadFormat(
+ const gl::Context *context) const
+{
+ GLenum sizedFormat = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
+ const d3d9::TextureFormat &textureFormat = d3d9::GetTextureFormatInfo(sizedFormat);
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(textureFormat.renderFormat);
+ const angle::Format &angleFormat = angle::Format::Get(d3dFormatInfo.formatID);
+ return gl::GetSizedInternalFormatInfo(angleFormat.fboImplementationInternalFormat);
+}
+
+angle::Result Framebuffer9::getSamplePosition(const gl::Context *context,
+ size_t index,
+ GLfloat *xy) const
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Framebuffer9::syncState(const gl::Context *context,
+ GLenum binding,
+ const gl::Framebuffer::DirtyBits &dirtyBits,
+ gl::Command command)
+{
+ ANGLE_TRY(FramebufferD3D::syncState(context, binding, dirtyBits, command));
+ ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
+ return angle::Result::Continue;
+}
+} // namespace rx