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 @@
'libGLESv2/constants.h',
'libGLESv2/Context.cpp',
'libGLESv2/Context.h',
'libGLESv2/angletypes.cpp',
'libGLESv2/angletypes.h',
'libGLESv2/Fence.cpp',
'libGLESv2/Fence.h',
......
......@@ -3613,185 +3613,6 @@ const char *Context::getRendererString() const
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,
GLbitfield mask, GLenum filter)
{
......@@ -3814,17 +3635,12 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
blitDepth = true;
}
gl::Rectangle sourceClippedRect, destClippedRect;
bool partialCopy;
if (!clipBlitFramebufferCoordinates(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
&sourceClippedRect, &destClippedRect, &partialCopy))
{
return;
}
gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
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);
}
}
......
......@@ -432,11 +432,6 @@ class Context
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,
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
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
{
int x;
......
......@@ -241,6 +241,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="angletypes.cpp" />
<ClCompile Include="Buffer.cpp" />
<ClCompile Include="Context.cpp" />
<ClCompile Include="..\common\debug.cpp">
......
......@@ -263,6 +263,9 @@
<ClCompile Include="renderer\Clear11.cpp">
<Filter>Source Files\Renderer11</Filter>
</ClCompile>
<ClCompile Include="angletypes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="BinaryStream.h">
......@@ -704,4 +707,4 @@
<ItemGroup>
<ResourceCompile Include="libGLESv2.rc" />
</ItemGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -53,7 +53,8 @@ namespace rx
Blit11::Blit11(rx::Renderer11 *renderer)
: 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),
mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL)
{
......@@ -120,13 +121,18 @@ Blit11::Blit11(rx::Renderer11 *renderer)
rasterDesc.SlopeScaledDepthBias = 0.0f;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = TRUE;
rasterDesc.ScissorEnable = FALSE;
rasterDesc.MultisampleEnable = FALSE;
rasterDesc.AntialiasedLineEnable = FALSE;
result = device->CreateRasterizerState(&rasterDesc, &mRasterizerState);
rasterDesc.ScissorEnable = TRUE;
result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState);
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mRasterizerState, "Blit11 rasterizer state");
d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
rasterDesc.ScissorEnable = FALSE;
result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
depthStencilDesc.DepthEnable = true;
......@@ -193,7 +199,8 @@ Blit11::~Blit11()
SafeRelease(mVertexBuffer);
SafeRelease(mPointSampler);
SafeRelease(mLinearSampler);
SafeRelease(mRasterizerState);
SafeRelease(mScissorEnabledRasterizerState);
SafeRelease(mScissorDisabledRasterizerState);
SafeRelease(mDepthStencilState);
SafeRelease(mQuad2DIL);
......@@ -209,18 +216,8 @@ Blit11::~Blit11()
bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
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;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
......@@ -269,7 +266,22 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
// Apply state
deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
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
deviceContext->IASetInputLayout(shader.mInputLayout);
......@@ -326,32 +338,32 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
return true;
}
static ID3D11Resource *createStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context,
ID3D11Resource *source, unsigned int subresource,
const gl::Extents &size, unsigned int cpuAccessFlags)
static DXGI_FORMAT getTextureFormat(ID3D11Resource *resource)
{
ID3D11Texture2D *sourceTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(source);
if (!sourceTexture)
ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
if (!texture)
{
return NULL;
return DXGI_FORMAT_UNKNOWN;
}
D3D11_TEXTURE2D_DESC sourceDesc;
sourceTexture->GetDesc(&sourceDesc);
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
if (sourceDesc.SampleDesc.Count > 1)
{
// Creating a staging texture of a multisampled texture is not supported
SafeRelease(sourceTexture);
return NULL;
}
SafeRelease(texture);
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;
stagingDesc.Width = size.width;
stagingDesc.Height = size.height;
stagingDesc.MipLevels = 1;
stagingDesc.ArraySize = 1;
stagingDesc.Format = sourceDesc.Format;
stagingDesc.Format = getTextureFormat(source);
stagingDesc.SampleDesc.Count = 1;
stagingDesc.SampleDesc.Quality = 0;
stagingDesc.Usage = D3D11_USAGE_STAGING;
......@@ -359,30 +371,17 @@ static ID3D11Resource *createStagingTexture(ID3D11Device *device, ID3D11DeviceCo
stagingDesc.MiscFlags = 0;
stagingDesc.BindFlags = 0;
SafeRelease(sourceTexture);
ID3D11Texture2D *stagingTexture = NULL;
HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture);
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)
if (FAILED(result))
{
return DXGI_FORMAT_UNKNOWN;
ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result);
return NULL;
}
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
SafeRelease(texture);
context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL);
return desc.Format;
return stagingTexture;
}
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
}
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,
dest, destSubresource, destArea, destSize,
true);
scissor, true);
}
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;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
......@@ -488,7 +489,22 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr
// Apply state
deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
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
deviceContext->IASetInputLayout(mQuad2DIL);
......@@ -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,
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,
dest, destSubresource, destArea, destSize,
false);
scissor, false);
}
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,
bool stencilOnly)
const gl::Rectangle *scissor, bool stencilOnly)
{
ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
......@@ -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 *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);
ASSERT(format == getTextureFormat(dest));
......@@ -568,7 +592,7 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso
copySize = d3d11::GetStencilBits(format) / 8;
// 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 &&
d3d11::GetStencilOffset(format) % 8 == 0);
}
......@@ -577,34 +601,66 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso
deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping);
deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping);
int startDestY = std::min(destArea.y, destArea.y + destArea.height);
int endDestY = std::max(destArea.y, destArea.y + destArea.height);
if (!sourceMapping.pData || !destMapping.pData)
{
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);
int endDestX = std::max(destArea.x, destArea.x + destArea.width);
// Clip dest area to the destination size
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);
unsigned int readRow = sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f);
gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea);
}
// 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;
if (sourceArea.width == destArea.width && copySize == pixelSize)
if (wholeRowCopy)
{
void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) +
readRow * sourceMapping.RowPitch;
readRow * sourceMapping.RowPitch +
sourceArea.x * pixelSize;
void *destRow = reinterpret_cast<char*>(destMapping.pData) +
writeRow * destMapping.RowPitch;
writeRow * destMapping.RowPitch +
destArea.x * pixelSize;
memcpy(destRow, sourceRow, pixelSize * destArea.width);
}
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);
unsigned int readColumn = sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f);
float xPerc = static_cast<float>(x - destArea.x) / (destArea.width - 1);
// 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;
void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) +
......
......@@ -30,16 +30,19 @@ class Blit11
bool copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
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,
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,
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,
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:
rx::Renderer11 *mRenderer;
......@@ -53,7 +56,7 @@ class Blit11
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,
bool stencilOnly);
const gl::Rectangle *scissor, bool stencilOnly);
static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b);
......@@ -84,7 +87,8 @@ class Blit11
ID3D11Buffer *mVertexBuffer;
ID3D11SamplerState *mPointSampler;
ID3D11SamplerState *mLinearSampler;
ID3D11RasterizerState *mRasterizerState;
ID3D11RasterizerState *mScissorEnabledRasterizerState;
ID3D11RasterizerState *mScissorDisabledRasterizerState;
ID3D11DepthStencilState *mDepthStencilState;
ID3D11InputLayout *mQuad2DIL;
......
......@@ -225,7 +225,7 @@ class Renderer
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,
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,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0;
......
......@@ -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
// 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);
return ret;
......@@ -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
// 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);
return ret;
......@@ -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
// 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);
return ret;
......@@ -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
// 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);
return ret;
......@@ -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 blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
{
if (blitRenderTarget)
{
......@@ -2822,7 +2822,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read
RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter,
if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
blitRenderTarget, false, false))
{
return false;
......@@ -2851,7 +2851,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read
RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter,
if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
false, blitDepth, blitStencil))
{
return false;
......@@ -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,
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,
// 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
return gl::error(GL_OUT_OF_MEMORY, false);
}
bool wholeBufferCopy = readRect.x == 0 && readRect.width == readRenderTarget11->getWidth() &&
readRect.y == 0 && readRect.height == readRenderTarget11->getHeight() &&
drawRect.x == 0 && drawRect.width == drawRenderTarget->getWidth() &&
drawRect.y == 0 && drawRect.height == drawRenderTarget->getHeight();
gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
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 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() &&
!stretchRequired && (!(depthBlit || stencilBlit) || wholeBufferCopy))
!stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
(!(depthBlit || stencilBlit) || wholeBufferCopy))
{
UINT dstX = drawRect.x;
UINT dstY = drawRect.y;
D3D11_BOX readBox;
readBox.left = readRect.x;
readBox.right = readRect.x + readRect.width;
......@@ -3166,40 +3188,66 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
readBox.front = 0;
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
// We also require complete framebuffer copies for depth-stencil blit.
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);
result = true;
}
else
{
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::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
if (depthBlit && stencilBlit)
{
result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
drawTexture, drawSubresource, drawArea, drawSize);
drawTexture, drawSubresource, drawArea, drawSize,
scissor);
}
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)
{
result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize,
drawTexture, drawSubresource, drawArea, drawSize);
drawTexture, drawSubresource, drawArea, drawSize,
scissor);
}
else
{
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
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,
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,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
......@@ -225,7 +225,8 @@ class Renderer11 : public Renderer
rx::Range getViewportBounds() const;
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);
HMODULE mD3d11Module;
......
......@@ -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 blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
{
ASSERT(filter == GL_NEAREST);
......@@ -2754,6 +2754,9 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
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;
srcRect.left = readRect.x;
srcRect.right = readRect.x + readRect.width;
......@@ -2766,6 +2769,75 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
dstRect.top = drawRect.y;
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);
SafeRelease(readSurface);
......
......@@ -186,7 +186,7 @@ class Renderer9 : public Renderer
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,
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,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
......
......@@ -140,7 +140,8 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign
Blit11 *blitter = mRenderer->getBlitter();
return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
dstTexture, dstSubresource, copyArea, texSize);
dstTexture, dstSubresource, copyArea, texSize,
NULL);
}
else
{
......@@ -180,7 +181,7 @@ void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget1
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_LINEAR);
}
......
......@@ -98,6 +98,31 @@ bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum ta
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,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
GLenum filter, bool fromAngleExtension)
......@@ -164,14 +189,6 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
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;
GLuint clientVersion = context->getClientVersion();
......@@ -249,8 +266,9 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
}
}
}
if (partialCopy && readFramebuffer->getSamples() != 0)
if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1))
{
return gl::error(GL_INVALID_OPERATION, false);
}
......@@ -277,7 +295,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
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.");
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
gl::Renderbuffer *readStencilBuffer = readFramebuffer->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->getActualFormat() != drawStencilBuffer->getActualFormat())
......@@ -316,7 +329,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
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.");
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