Commit 125deab6 by Geoff Lang

Moved the clipping of blit rectangles to bounds or scissors into the Renderers…

Moved the clipping of blit rectangles to bounds or scissors into the Renderers since rounding to integers can cause errors when stretching in ES3. TRAC #23650 Author: Geoff Lang Signed-off-by: Jamie Madill Signed-off-by: Shannon Woods
parent c832516a
...@@ -254,6 +254,7 @@ ...@@ -254,6 +254,7 @@
'libGLESv2/constants.h', 'libGLESv2/constants.h',
'libGLESv2/Context.cpp', 'libGLESv2/Context.cpp',
'libGLESv2/Context.h', 'libGLESv2/Context.h',
'libGLESv2/angletypes.cpp',
'libGLESv2/angletypes.h', 'libGLESv2/angletypes.h',
'libGLESv2/Fence.cpp', 'libGLESv2/Fence.cpp',
'libGLESv2/Fence.h', 'libGLESv2/Fence.h',
......
...@@ -3613,185 +3613,6 @@ const char *Context::getRendererString() const ...@@ -3613,185 +3613,6 @@ const char *Context::getRendererString() const
return mRendererString; return mRendererString;
} }
bool Context::clipBlitFramebufferCoordinates(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
gl::Rectangle *outSourceRect, gl::Rectangle *outDestRect,
bool *outPartialCopy)
{
Framebuffer *readFramebuffer = getReadFramebuffer();
Framebuffer *drawFramebuffer = getDrawFramebuffer();
if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
!drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
return false;
}
Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
if (!readColorBuffer || !drawColorBuffer)
{
return false;
}
int readBufferWidth = readColorBuffer->getWidth();
int readBufferHeight = readColorBuffer->getHeight();
int drawBufferWidth = drawColorBuffer->getWidth();
int drawBufferHeight = drawColorBuffer->getHeight();
gl::Rectangle sourceRect;
gl::Rectangle destRect;
if (srcX0 < srcX1)
{
sourceRect.x = srcX0;
destRect.x = dstX0;
sourceRect.width = srcX1 - srcX0;
destRect.width = dstX1 - dstX0;
}
else
{
sourceRect.x = srcX1;
destRect.x = dstX1;
sourceRect.width = srcX0 - srcX1;
destRect.width = dstX0 - dstX1;
}
if (srcY0 < srcY1)
{
sourceRect.height = srcY1 - srcY0;
destRect.height = dstY1 - dstY0;
sourceRect.y = srcY0;
destRect.y = dstY0;
}
else
{
sourceRect.height = srcY0 - srcY1;
destRect.height = dstY0 - dstY1;
sourceRect.y = srcY1;
destRect.y = dstY1;
}
Rectangle sourceScissoredRect = sourceRect;
Rectangle destScissoredRect = destRect;
if (mState.scissorTest)
{
// Only write to parts of the destination framebuffer which pass the scissor test.
if (destRect.x < mState.scissor.x)
{
int xDiff = mState.scissor.x - destRect.x;
destScissoredRect.x = mState.scissor.x;
destScissoredRect.width -= xDiff;
sourceScissoredRect.x += xDiff;
sourceScissoredRect.width -= xDiff;
}
if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width)
{
int xDiff = (destRect.x + destRect.width) - (mState.scissor.x + mState.scissor.width);
destScissoredRect.width -= xDiff;
sourceScissoredRect.width -= xDiff;
}
if (destRect.y < mState.scissor.y)
{
int yDiff = mState.scissor.y - destRect.y;
destScissoredRect.y = mState.scissor.y;
destScissoredRect.height -= yDiff;
sourceScissoredRect.y += yDiff;
sourceScissoredRect.height -= yDiff;
}
if (destRect.y + destRect.height > mState.scissor.y + mState.scissor.height)
{
int yDiff = (destRect.y + destRect.height) - (mState.scissor.y + mState.scissor.height);
destScissoredRect.height -= yDiff;
sourceScissoredRect.height -= yDiff;
}
}
Rectangle sourceTrimmedRect = sourceScissoredRect;
Rectangle destTrimmedRect = destScissoredRect;
// The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
// the actual draw and read surfaces.
if (sourceTrimmedRect.x < 0)
{
int xDiff = 0 - sourceTrimmedRect.x;
sourceTrimmedRect.x = 0;
sourceTrimmedRect.width -= xDiff;
destTrimmedRect.x += xDiff;
destTrimmedRect.width -= xDiff;
}
if (sourceTrimmedRect.x + sourceTrimmedRect.width > readBufferWidth)
{
int xDiff = (sourceTrimmedRect.x + sourceTrimmedRect.width) - readBufferWidth;
sourceTrimmedRect.width -= xDiff;
destTrimmedRect.width -= xDiff;
}
if (sourceTrimmedRect.y < 0)
{
int yDiff = 0 - sourceTrimmedRect.y;
sourceTrimmedRect.y = 0;
sourceTrimmedRect.height -= yDiff;
destTrimmedRect.y += yDiff;
destTrimmedRect.height -= yDiff;
}
if (sourceTrimmedRect.y + sourceTrimmedRect.height > readBufferHeight)
{
int yDiff = (sourceTrimmedRect.y + sourceTrimmedRect.height) - readBufferHeight;
sourceTrimmedRect.height -= yDiff;
destTrimmedRect.height -= yDiff;
}
if (destTrimmedRect.x < 0)
{
int xDiff = 0 - destTrimmedRect.x;
destTrimmedRect.x = 0;
destTrimmedRect.width -= xDiff;
sourceTrimmedRect.x += xDiff;
sourceTrimmedRect.width -= xDiff;
}
if (destTrimmedRect.x + destTrimmedRect.width > drawBufferWidth)
{
int xDiff = (destTrimmedRect.x + destTrimmedRect.width) - drawBufferWidth;
destTrimmedRect.width -= xDiff;
sourceTrimmedRect.width -= xDiff;
}
if (destTrimmedRect.y < 0)
{
int yDiff = 0 - destTrimmedRect.y;
destTrimmedRect.y = 0;
destTrimmedRect.height -= yDiff;
sourceTrimmedRect.y += yDiff;
sourceTrimmedRect.height -= yDiff;
}
if (destTrimmedRect.y + destTrimmedRect.height > drawBufferHeight)
{
int yDiff = (destTrimmedRect.y + destTrimmedRect.height) - drawBufferHeight;
destTrimmedRect.height -= yDiff;
sourceTrimmedRect.height -= yDiff;
}
*outSourceRect = sourceTrimmedRect;
*outDestRect = destTrimmedRect;
*outPartialCopy = sourceTrimmedRect.height < readBufferHeight ||
sourceTrimmedRect.width < readBufferWidth ||
destTrimmedRect.height < drawBufferHeight ||
destTrimmedRect.width < drawBufferWidth ||
sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0 ||
sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0;
return true;
}
void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter) GLbitfield mask, GLenum filter)
{ {
...@@ -3814,17 +3635,12 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 ...@@ -3814,17 +3635,12 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
blitDepth = true; blitDepth = true;
} }
gl::Rectangle sourceClippedRect, destClippedRect; gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
bool partialCopy; gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
if (!clipBlitFramebufferCoordinates(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
&sourceClippedRect, &destClippedRect, &partialCopy))
{
return;
}
if (blitRenderTarget || blitDepth || blitStencil) if (blitRenderTarget || blitDepth || blitStencil)
{ {
mRenderer->blitRect(readFramebuffer, sourceClippedRect, drawFramebuffer, destClippedRect, const gl::Rectangle *scissor = mState.scissorTest ? &mState.scissor : NULL;
mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor,
blitRenderTarget, blitDepth, blitStencil, filter); blitRenderTarget, blitDepth, blitStencil, filter);
} }
} }
......
...@@ -432,11 +432,6 @@ class Context ...@@ -432,11 +432,6 @@ class Context
float getTextureMaxAnisotropy() const; float getTextureMaxAnisotropy() const;
bool clipBlitFramebufferCoordinates(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
gl::Rectangle *outSourceRect, gl::Rectangle *outDestRect,
bool *outPartialCopy);
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter); GLbitfield mask, GLenum filter);
......
#include "precompiled.h"
//
// Copyright (c) 2013 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.
//
// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
#include "libGLESv2/angletypes.h"
namespace gl
{
static void MinMax(int a, int b, int *minimum, int *maximum)
{
if (a < b)
{
*minimum = a;
*maximum = b;
}
else
{
*minimum = b;
*maximum = a;
}
}
bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection)
{
int minSourceX, maxSourceX, minSourceY, maxSourceY;
MinMax(source.x, source.x + source.width, &minSourceX, &maxSourceX);
MinMax(source.y, source.y + source.height, &minSourceY, &maxSourceY);
int minClipX, maxClipX, minClipY, maxClipY;
MinMax(clip.x, clip.x + clip.width, &minClipX, &maxClipX);
MinMax(clip.y, clip.y + clip.height, &minClipY, &maxClipY);
if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY || maxSourceY <= minClipY)
{
if (intersection)
{
intersection->x = minSourceX;
intersection->y = maxSourceY;
intersection->width = maxSourceX - minSourceX;
intersection->height = maxSourceY - minSourceY;
}
return false;
}
else
{
if (intersection)
{
intersection->x = std::max(minSourceX, minClipX);
intersection->y = std::max(minSourceY, minClipY);
intersection->width = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX);
intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY);
}
return true;
}
}
}
...@@ -58,6 +58,8 @@ struct Rectangle ...@@ -58,6 +58,8 @@ struct Rectangle
Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { } Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { }
}; };
bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
struct Box struct Box
{ {
int x; int x;
......
...@@ -241,6 +241,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" ...@@ -241,6 +241,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="angletypes.cpp" />
<ClCompile Include="Buffer.cpp" /> <ClCompile Include="Buffer.cpp" />
<ClCompile Include="Context.cpp" /> <ClCompile Include="Context.cpp" />
<ClCompile Include="..\common\debug.cpp"> <ClCompile Include="..\common\debug.cpp">
......
...@@ -263,6 +263,9 @@ ...@@ -263,6 +263,9 @@
<ClCompile Include="renderer\Clear11.cpp"> <ClCompile Include="renderer\Clear11.cpp">
<Filter>Source Files\Renderer11</Filter> <Filter>Source Files\Renderer11</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="angletypes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="BinaryStream.h"> <ClInclude Include="BinaryStream.h">
......
...@@ -53,7 +53,8 @@ namespace rx ...@@ -53,7 +53,8 @@ namespace rx
Blit11::Blit11(rx::Renderer11 *renderer) Blit11::Blit11(rx::Renderer11 *renderer)
: mRenderer(renderer), mShaderMap(compareBlitParameters), mVertexBuffer(NULL), : mRenderer(renderer), mShaderMap(compareBlitParameters), mVertexBuffer(NULL),
mPointSampler(NULL), mLinearSampler(NULL), mRasterizerState(NULL), mDepthStencilState(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL),
mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL),
mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL), mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL),
mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL) mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL)
{ {
...@@ -120,13 +121,18 @@ Blit11::Blit11(rx::Renderer11 *renderer) ...@@ -120,13 +121,18 @@ Blit11::Blit11(rx::Renderer11 *renderer)
rasterDesc.SlopeScaledDepthBias = 0.0f; rasterDesc.SlopeScaledDepthBias = 0.0f;
rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = TRUE; rasterDesc.DepthClipEnable = TRUE;
rasterDesc.ScissorEnable = FALSE;
rasterDesc.MultisampleEnable = FALSE; rasterDesc.MultisampleEnable = FALSE;
rasterDesc.AntialiasedLineEnable = FALSE; rasterDesc.AntialiasedLineEnable = FALSE;
result = device->CreateRasterizerState(&rasterDesc, &mRasterizerState); rasterDesc.ScissorEnable = TRUE;
result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState);
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
rasterDesc.ScissorEnable = FALSE;
result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mRasterizerState, "Blit11 rasterizer state"); d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
D3D11_DEPTH_STENCIL_DESC depthStencilDesc; D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
depthStencilDesc.DepthEnable = true; depthStencilDesc.DepthEnable = true;
...@@ -193,7 +199,8 @@ Blit11::~Blit11() ...@@ -193,7 +199,8 @@ Blit11::~Blit11()
SafeRelease(mVertexBuffer); SafeRelease(mVertexBuffer);
SafeRelease(mPointSampler); SafeRelease(mPointSampler);
SafeRelease(mLinearSampler); SafeRelease(mLinearSampler);
SafeRelease(mRasterizerState); SafeRelease(mScissorEnabledRasterizerState);
SafeRelease(mScissorDisabledRasterizerState);
SafeRelease(mDepthStencilState); SafeRelease(mDepthStencilState);
SafeRelease(mQuad2DIL); SafeRelease(mQuad2DIL);
...@@ -209,18 +216,8 @@ Blit11::~Blit11() ...@@ -209,18 +216,8 @@ Blit11::~Blit11()
bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
GLenum destFormat, GLenum filter) const gl::Rectangle *scissor, GLenum destFormat, GLenum filter)
{ {
if(sourceArea.x < 0 || sourceArea.x + sourceArea.width > sourceSize.width ||
sourceArea.y < 0 || sourceArea.y + sourceArea.height > sourceSize.height ||
sourceArea.z < 0 || sourceArea.z + sourceArea.depth > sourceSize.depth ||
destArea.x < 0 || destArea.x + destArea.width > destSize.width ||
destArea.y < 0 || destArea.y + destArea.height > destSize.height ||
destArea.z < 0 || destArea.z + destArea.depth > destSize.depth )
{
return false;
}
HRESULT result; HRESULT result;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
...@@ -269,7 +266,22 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source ...@@ -269,7 +266,22 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
// Apply state // Apply state
deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
deviceContext->RSSetState(mRasterizerState);
if (scissor)
{
D3D11_RECT scissorRect;
scissorRect.left = scissor->x;
scissorRect.right = scissor->x + scissor->width;
scissorRect.top = scissor->y;
scissorRect.bottom = scissor->y + scissor->height;
deviceContext->RSSetScissorRects(1, &scissorRect);
deviceContext->RSSetState(mScissorEnabledRasterizerState);
}
else
{
deviceContext->RSSetState(mScissorDisabledRasterizerState);
}
// Apply shaders // Apply shaders
deviceContext->IASetInputLayout(shader.mInputLayout); deviceContext->IASetInputLayout(shader.mInputLayout);
...@@ -326,32 +338,32 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source ...@@ -326,32 +338,32 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
return true; return true;
} }
static ID3D11Resource *createStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, static DXGI_FORMAT getTextureFormat(ID3D11Resource *resource)
ID3D11Resource *source, unsigned int subresource,
const gl::Extents &size, unsigned int cpuAccessFlags)
{ {
ID3D11Texture2D *sourceTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(source); ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
if (!sourceTexture) if (!texture)
{ {
return NULL; return DXGI_FORMAT_UNKNOWN;
} }
D3D11_TEXTURE2D_DESC sourceDesc; D3D11_TEXTURE2D_DESC desc;
sourceTexture->GetDesc(&sourceDesc); texture->GetDesc(&desc);
if (sourceDesc.SampleDesc.Count > 1) SafeRelease(texture);
{
// Creating a staging texture of a multisampled texture is not supported
SafeRelease(sourceTexture);
return NULL;
}
return desc.Format;
}
static ID3D11Resource *createStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context,
ID3D11Resource *source, unsigned int subresource,
const gl::Extents &size, unsigned int cpuAccessFlags)
{
D3D11_TEXTURE2D_DESC stagingDesc; D3D11_TEXTURE2D_DESC stagingDesc;
stagingDesc.Width = size.width; stagingDesc.Width = size.width;
stagingDesc.Height = size.height; stagingDesc.Height = size.height;
stagingDesc.MipLevels = 1; stagingDesc.MipLevels = 1;
stagingDesc.ArraySize = 1; stagingDesc.ArraySize = 1;
stagingDesc.Format = sourceDesc.Format; stagingDesc.Format = getTextureFormat(source);
stagingDesc.SampleDesc.Count = 1; stagingDesc.SampleDesc.Count = 1;
stagingDesc.SampleDesc.Quality = 0; stagingDesc.SampleDesc.Quality = 0;
stagingDesc.Usage = D3D11_USAGE_STAGING; stagingDesc.Usage = D3D11_USAGE_STAGING;
...@@ -359,30 +371,17 @@ static ID3D11Resource *createStagingTexture(ID3D11Device *device, ID3D11DeviceCo ...@@ -359,30 +371,17 @@ static ID3D11Resource *createStagingTexture(ID3D11Device *device, ID3D11DeviceCo
stagingDesc.MiscFlags = 0; stagingDesc.MiscFlags = 0;
stagingDesc.BindFlags = 0; stagingDesc.BindFlags = 0;
SafeRelease(sourceTexture);
ID3D11Texture2D *stagingTexture = NULL; ID3D11Texture2D *stagingTexture = NULL;
HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture); HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture);
if (FAILED(result))
context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL);
return stagingTexture;
}
static DXGI_FORMAT getTextureFormat(ID3D11Resource *resource)
{
ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
if (!texture)
{ {
return DXGI_FORMAT_UNKNOWN; ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result);
return NULL;
} }
D3D11_TEXTURE2D_DESC desc; context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL);
texture->GetDesc(&desc);
SafeRelease(texture);
return desc.Format; return stagingTexture;
} }
inline static void generateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize, inline static void generateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize,
...@@ -450,15 +449,17 @@ static void write3DVertices(const gl::Box &sourceArea, const gl::Extents &source ...@@ -450,15 +449,17 @@ static void write3DVertices(const gl::Box &sourceArea, const gl::Extents &source
} }
bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize) ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor)
{ {
return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
dest, destSubresource, destArea, destSize, dest, destSubresource, destArea, destSize,
true); scissor, true);
} }
bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize) ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor)
{ {
HRESULT result; HRESULT result;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
...@@ -488,7 +489,22 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr ...@@ -488,7 +489,22 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr
// Apply state // Apply state
deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF);
deviceContext->RSSetState(mRasterizerState);
if (scissor)
{
D3D11_RECT scissorRect;
scissorRect.left = scissor->x;
scissorRect.right = scissor->x + scissor->width;
scissorRect.top = scissor->y;
scissorRect.bottom = scissor->y + scissor->height;
deviceContext->RSSetScissorRects(1, &scissorRect);
deviceContext->RSSetState(mScissorEnabledRasterizerState);
}
else
{
deviceContext->RSSetState(mScissorDisabledRasterizerState);
}
// Apply shaders // Apply shaders
deviceContext->IASetInputLayout(mQuad2DIL); deviceContext->IASetInputLayout(mQuad2DIL);
...@@ -539,16 +555,17 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr ...@@ -539,16 +555,17 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr
} }
bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize) ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor)
{ {
return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
dest, destSubresource, destArea, destSize, dest, destSubresource, destArea, destSize,
false); scissor, false);
} }
bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
bool stencilOnly) const gl::Rectangle *scissor, bool stencilOnly)
{ {
ID3D11Device *device = mRenderer->getDevice(); ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
...@@ -556,6 +573,13 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso ...@@ -556,6 +573,13 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso
ID3D11Resource *sourceStaging = createStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ); ID3D11Resource *sourceStaging = createStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ);
ID3D11Resource *destStaging = createStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_WRITE); ID3D11Resource *destStaging = createStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_WRITE);
if (!sourceStaging || !destStaging)
{
SafeRelease(sourceStaging);
SafeRelease(destStaging);
return false;
}
DXGI_FORMAT format = getTextureFormat(source); DXGI_FORMAT format = getTextureFormat(source);
ASSERT(format == getTextureFormat(dest)); ASSERT(format == getTextureFormat(dest));
...@@ -568,7 +592,7 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso ...@@ -568,7 +592,7 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso
copySize = d3d11::GetStencilBits(format) / 8; copySize = d3d11::GetStencilBits(format) / 8;
// It would be expensive to have non-byte sized stencil sizes since it would // It would be expensive to have non-byte sized stencil sizes since it would
// require reading from the destination, currently there arn't any though. // require reading from the destination, currently there aren't any though.
ASSERT(d3d11::GetStencilBits(format) % 8 == 0 && ASSERT(d3d11::GetStencilBits(format) % 8 == 0 &&
d3d11::GetStencilOffset(format) % 8 == 0); d3d11::GetStencilOffset(format) % 8 == 0);
} }
...@@ -577,34 +601,66 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso ...@@ -577,34 +601,66 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso
deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping);
deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping);
int startDestY = std::min(destArea.y, destArea.y + destArea.height); if (!sourceMapping.pData || !destMapping.pData)
int endDestY = std::max(destArea.y, destArea.y + destArea.height); {
if (!sourceMapping.pData)
{
deviceContext->Unmap(sourceStaging, 0);
}
if (!destMapping.pData)
{
deviceContext->Unmap(destStaging, 0);
}
SafeRelease(sourceStaging);
SafeRelease(destStaging);
return false;
}
gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
int startDestX = std::min(destArea.x, destArea.x + destArea.width); // Clip dest area to the destination size
int endDestX = std::max(destArea.x, destArea.x + destArea.width); gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea);
for (int y = startDestY; y < endDestY; y++) // Clip dest area to the scissor
if (scissor)
{ {
float yPerc = static_cast<float>(y - startDestY) / (endDestY - startDestY - 1); gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea);
unsigned int readRow = sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f); }
// Determine if entire rows can be copied at once instead of each individual pixel, requires that there is
// no out of bounds lookups required, the entire pixel is copied and no stretching
bool wholeRowCopy = sourceArea.width == clippedDestArea.width &&
sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width &&
copySize == pixelSize;
for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
{
float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
// Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges
unsigned int readRow = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1);
unsigned int writeRow = y; unsigned int writeRow = y;
if (sourceArea.width == destArea.width && copySize == pixelSize) if (wholeRowCopy)
{ {
void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) + void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) +
readRow * sourceMapping.RowPitch; readRow * sourceMapping.RowPitch +
sourceArea.x * pixelSize;
void *destRow = reinterpret_cast<char*>(destMapping.pData) + void *destRow = reinterpret_cast<char*>(destMapping.pData) +
writeRow * destMapping.RowPitch; writeRow * destMapping.RowPitch +
destArea.x * pixelSize;
memcpy(destRow, sourceRow, pixelSize * destArea.width); memcpy(destRow, sourceRow, pixelSize * destArea.width);
} }
else else
{ {
for (int x = startDestX; x < endDestX; x++) for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++)
{ {
float xPerc = static_cast<float>(x - startDestX) / (endDestX - startDestX - 1); float xPerc = static_cast<float>(x - destArea.x) / (destArea.width - 1);
unsigned int readColumn = sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f);
// Interpolate the original source rectangle to determine which column to sample from while clamping to the edges
unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1);
unsigned int writeColumn = x; unsigned int writeColumn = x;
void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) + void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) +
......
...@@ -30,16 +30,19 @@ class Blit11 ...@@ -30,16 +30,19 @@ class Blit11
bool copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
GLenum destFormat, GLenum filter); const gl::Rectangle *scissor, GLenum destFormat, GLenum filter);
bool copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize); ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor);
bool copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize); ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor);
bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize); ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor);
private: private:
rx::Renderer11 *mRenderer; rx::Renderer11 *mRenderer;
...@@ -53,7 +56,7 @@ class Blit11 ...@@ -53,7 +56,7 @@ class Blit11
bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
bool stencilOnly); const gl::Rectangle *scissor, bool stencilOnly);
static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b); static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b);
...@@ -84,7 +87,8 @@ class Blit11 ...@@ -84,7 +87,8 @@ class Blit11
ID3D11Buffer *mVertexBuffer; ID3D11Buffer *mVertexBuffer;
ID3D11SamplerState *mPointSampler; ID3D11SamplerState *mPointSampler;
ID3D11SamplerState *mLinearSampler; ID3D11SamplerState *mLinearSampler;
ID3D11RasterizerState *mRasterizerState; ID3D11RasterizerState *mScissorEnabledRasterizerState;
ID3D11RasterizerState *mScissorDisabledRasterizerState;
ID3D11DepthStencilState *mDepthStencilState; ID3D11DepthStencilState *mDepthStencilState;
ID3D11InputLayout *mQuad2DIL; ID3D11InputLayout *mQuad2DIL;
......
...@@ -225,7 +225,7 @@ class Renderer ...@@ -225,7 +225,7 @@ class Renderer
GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) = 0; GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) = 0;
virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) = 0; const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) = 0;
virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0; GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0;
......
...@@ -2416,7 +2416,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so ...@@ -2416,7 +2416,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
// Use nearest filtering because source and destination are the same size for the direct // Use nearest filtering because source and destination are the same size for the direct
// copy // copy
bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
destFormat, GL_NEAREST); destFormat, GL_NEAREST);
return ret; return ret;
...@@ -2475,7 +2475,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so ...@@ -2475,7 +2475,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
// Use nearest filtering because source and destination are the same size for the direct // Use nearest filtering because source and destination are the same size for the direct
// copy // copy
bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
destFormat, GL_NEAREST); destFormat, GL_NEAREST);
return ret; return ret;
...@@ -2534,7 +2534,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so ...@@ -2534,7 +2534,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
// Use nearest filtering because source and destination are the same size for the direct // Use nearest filtering because source and destination are the same size for the direct
// copy // copy
bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
destFormat, GL_NEAREST); destFormat, GL_NEAREST);
return ret; return ret;
...@@ -2595,7 +2595,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so ...@@ -2595,7 +2595,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
// Use nearest filtering because source and destination are the same size for the direct // Use nearest filtering because source and destination are the same size for the direct
// copy // copy
bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
destFormat, GL_NEAREST); destFormat, GL_NEAREST);
return ret; return ret;
...@@ -2794,7 +2794,7 @@ bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned ...@@ -2794,7 +2794,7 @@ bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned
} }
bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
{ {
if (blitRenderTarget) if (blitRenderTarget)
{ {
...@@ -2822,7 +2822,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read ...@@ -2822,7 +2822,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read
RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
blitRenderTarget, false, false)) blitRenderTarget, false, false))
{ {
return false; return false;
...@@ -2851,7 +2851,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read ...@@ -2851,7 +2851,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read
RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
false, blitDepth, blitStencil)) false, blitDepth, blitStencil))
{ {
return false; return false;
...@@ -3080,7 +3080,8 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou ...@@ -3080,7 +3080,8 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou
} }
bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
RenderTarget *drawRenderTarget, GLenum filter, bool colorBlit, bool depthBlit, bool stencilBlit) RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
bool colorBlit, bool depthBlit, bool stencilBlit)
{ {
// Since blitRenderbufferRect is called for each render buffer that needs to be blitted, // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
// it should never be the case that both color and depth/stencil need to be blitted at // it should never be the case that both color and depth/stencil need to be blitted at
...@@ -3148,16 +3149,37 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R ...@@ -3148,16 +3149,37 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
return gl::error(GL_OUT_OF_MEMORY, false); return gl::error(GL_OUT_OF_MEMORY, false);
} }
bool wholeBufferCopy = readRect.x == 0 && readRect.width == readRenderTarget11->getWidth() && gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
readRect.y == 0 && readRect.height == readRenderTarget11->getHeight() && gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
drawRect.x == 0 && drawRect.width == drawRenderTarget->getWidth() &&
drawRect.y == 0 && drawRect.height == drawRenderTarget->getHeight(); bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL);
bool wholeBufferCopy = !scissorNeeded &&
readRect.x == 0 && readRect.width == readSize.width &&
readRect.y == 0 && readRect.height == readSize.height &&
drawRect.x == 0 && drawRect.width == drawSize.width &&
drawRect.y == 0 && drawRect.height == drawSize.height;
bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
bool flipRequired = readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || readRect.height < 0;
bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
bool hasDepth = gl::GetDepthBits(drawRenderTarget11->getActualFormat(), getCurrentClientVersion()) > 0;
bool hasStencil = gl::GetStencilBits(drawRenderTarget11->getActualFormat(), getCurrentClientVersion()) > 0;
bool partialDSBlit = (hasDepth && depthBlit) != (hasStencil && stencilBlit);
if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() &&
!stretchRequired && (!(depthBlit || stencilBlit) || wholeBufferCopy)) !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
(!(depthBlit || stencilBlit) || wholeBufferCopy))
{ {
UINT dstX = drawRect.x;
UINT dstY = drawRect.y;
D3D11_BOX readBox; D3D11_BOX readBox;
readBox.left = readRect.x; readBox.left = readRect.x;
readBox.right = readRect.x + readRect.width; readBox.right = readRect.x + readRect.width;
...@@ -3166,40 +3188,66 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R ...@@ -3166,40 +3188,66 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
readBox.front = 0; readBox.front = 0;
readBox.back = 1; readBox.back = 1;
if (scissorNeeded)
{
// drawRect is guaranteed to have positive width and height because stretchRequired is false.
ASSERT(drawRect.width >= 0 || drawRect.height >= 0);
if (drawRect.x < scissor->x)
{
dstX = scissor->x;
readBox.left += (scissor->x - drawRect.x);
}
if (drawRect.y < scissor->y)
{
dstY = scissor->y;
readBox.top += (scissor->y - drawRect.y);
}
if (drawRect.x + drawRect.width > scissor->x + scissor->width)
{
readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width));
}
if (drawRect.y + drawRect.height > scissor->y + scissor->height)
{
readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height));
}
}
// D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
// We also require complete framebuffer copies for depth-stencil blit. // We also require complete framebuffer copies for depth-stencil blit.
D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0, mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0,
readTexture, readSubresource, pSrcBox); readTexture, readSubresource, pSrcBox);
result = true; result = true;
} }
else else
{ {
gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1); gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1);
gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1); gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1);
gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
if (depthBlit && stencilBlit) if (depthBlit && stencilBlit)
{ {
result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
drawTexture, drawSubresource, drawArea, drawSize); drawTexture, drawSubresource, drawArea, drawSize,
scissor);
} }
else if (depthBlit) else if (depthBlit)
{ {
result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize); result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize,
scissor);
} }
else if (stencilBlit) else if (stencilBlit)
{ {
result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize,
drawTexture, drawSubresource, drawArea, drawSize); drawTexture, drawSubresource, drawArea, drawSize,
scissor);
} }
else else
{ {
GLenum format = gl::GetFormat(drawRenderTarget->getInternalFormat(), getCurrentClientVersion()); GLenum format = gl::GetFormat(drawRenderTarget->getInternalFormat(), getCurrentClientVersion());
result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, format, filter); result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
scissor, format, filter);
} }
} }
......
...@@ -169,7 +169,7 @@ class Renderer11 : public Renderer ...@@ -169,7 +169,7 @@ class Renderer11 : public Renderer
GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level); GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level);
virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter);
virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
...@@ -225,7 +225,8 @@ class Renderer11 : public Renderer ...@@ -225,7 +225,8 @@ class Renderer11 : public Renderer
rx::Range getViewportBounds() const; rx::Range getViewportBounds() const;
bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
RenderTarget *drawRenderTarget, GLenum filter, bool colorBlit, bool depthBlit, bool stencilBlit); RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
bool colorBlit, bool depthBlit, bool stencilBlit);
ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
HMODULE mD3d11Module; HMODULE mD3d11Module;
......
...@@ -2715,7 +2715,7 @@ bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sou ...@@ -2715,7 +2715,7 @@ bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sou
} }
bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
{ {
ASSERT(filter == GL_NEAREST); ASSERT(filter == GL_NEAREST);
...@@ -2754,6 +2754,9 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & ...@@ -2754,6 +2754,9 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
return gl::error(GL_OUT_OF_MEMORY, false); return gl::error(GL_OUT_OF_MEMORY, false);
} }
gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
RECT srcRect; RECT srcRect;
srcRect.left = readRect.x; srcRect.left = readRect.x;
srcRect.right = readRect.x + readRect.width; srcRect.right = readRect.x + readRect.width;
...@@ -2766,6 +2769,75 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & ...@@ -2766,6 +2769,75 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
dstRect.top = drawRect.y; dstRect.top = drawRect.y;
dstRect.bottom = drawRect.y + drawRect.height; dstRect.bottom = drawRect.y + drawRect.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 = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
SafeRelease(readSurface); SafeRelease(readSurface);
......
...@@ -186,7 +186,7 @@ class Renderer9 : public Renderer ...@@ -186,7 +186,7 @@ class Renderer9 : public Renderer
GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level); GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level);
virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter);
virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
......
...@@ -140,7 +140,8 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign ...@@ -140,7 +140,8 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign
Blit11 *blitter = mRenderer->getBlitter(); Blit11 *blitter = mRenderer->getBlitter();
return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
dstTexture, dstSubresource, copyArea, texSize); dstTexture, dstSubresource, copyArea, texSize,
NULL);
} }
else else
{ {
...@@ -180,7 +181,7 @@ void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget1 ...@@ -180,7 +181,7 @@ void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget1
Blit11 *blitter = mRenderer->getBlitter(); Blit11 *blitter = mRenderer->getBlitter();
blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
gl::GetFormat(source->getInternalFormat(), mRenderer->getCurrentClientVersion()), gl::GetFormat(source->getInternalFormat(), mRenderer->getCurrentClientVersion()),
GL_LINEAR); GL_LINEAR);
} }
......
...@@ -98,6 +98,31 @@ bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum ta ...@@ -98,6 +98,31 @@ bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum ta
return true; return true;
} }
static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
{
if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
{
return true;
}
else if (context->isScissorTestEnabled())
{
int scissorX, scissorY, scissorWidth, scissorHeight;
context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight);
return scissorX > 0 || scissorY > 0 ||
scissorWidth < writeBuffer->getWidth() ||
scissorHeight < writeBuffer->getHeight();
}
else
{
return false;
}
}
bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
GLenum filter, bool fromAngleExtension) GLenum filter, bool fromAngleExtension)
...@@ -164,14 +189,6 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint ...@@ -164,14 +189,6 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
gl::Rectangle sourceClippedRect, destClippedRect;
bool partialCopy;
if (!context->clipBlitFramebufferCoordinates(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
&sourceClippedRect, &destClippedRect, &partialCopy))
{
return gl::error(GL_INVALID_OPERATION, false);
}
bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1; bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
GLuint clientVersion = context->getClientVersion(); GLuint clientVersion = context->getClientVersion();
...@@ -249,8 +266,9 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint ...@@ -249,8 +266,9 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
} }
} }
} }
if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
if (partialCopy && readFramebuffer->getSamples() != 0) srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1))
{ {
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
...@@ -277,7 +295,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint ...@@ -277,7 +295,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
if (fromAngleExtension) if (fromAngleExtension)
{ {
if (partialCopy) if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
{ {
ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
...@@ -296,12 +315,6 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint ...@@ -296,12 +315,6 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer(); gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer(); gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
if (fromAngleExtension && partialCopy)
{
ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
}
if (readStencilBuffer && drawStencilBuffer) if (readStencilBuffer && drawStencilBuffer)
{ {
if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat()) if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
...@@ -316,7 +329,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint ...@@ -316,7 +329,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
if (fromAngleExtension) if (fromAngleExtension)
{ {
if (partialCopy) if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
{ {
ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment