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
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 8fdac3f..eb38902 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -3613,185 +3613,6 @@
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 @@
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);
}
}
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index ea79da5..96bdd7e 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -432,11 +432,6 @@
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);
diff --git a/src/libGLESv2/angletypes.cpp b/src/libGLESv2/angletypes.cpp
new file mode 100644
index 0000000..fdef4f4
--- /dev/null
+++ b/src/libGLESv2/angletypes.cpp
@@ -0,0 +1,65 @@
+#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;
+ }
+}
+
+}
diff --git a/src/libGLESv2/angletypes.h b/src/libGLESv2/angletypes.h
index c377f4e..035c5f3 100644
--- a/src/libGLESv2/angletypes.h
+++ b/src/libGLESv2/angletypes.h
@@ -58,6 +58,8 @@
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;
diff --git a/src/libGLESv2/libGLESv2.vcxproj b/src/libGLESv2/libGLESv2.vcxproj
index 366824b..d1ba1cd 100644
--- a/src/libGLESv2/libGLESv2.vcxproj
+++ b/src/libGLESv2/libGLESv2.vcxproj
@@ -241,6 +241,7 @@
<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">
diff --git a/src/libGLESv2/libGLESv2.vcxproj.filters b/src/libGLESv2/libGLESv2.vcxproj.filters
index eb29d3a..0276ba3 100644
--- a/src/libGLESv2/libGLESv2.vcxproj.filters
+++ b/src/libGLESv2/libGLESv2.vcxproj.filters
@@ -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>
diff --git a/src/libGLESv2/renderer/Blit11.cpp b/src/libGLESv2/renderer/Blit11.cpp
index 2256117..7279f52 100644
--- a/src/libGLESv2/renderer/Blit11.cpp
+++ b/src/libGLESv2/renderer/Blit11.cpp
@@ -53,7 +53,8 @@
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 @@
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 @@
SafeRelease(mVertexBuffer);
SafeRelease(mPointSampler);
SafeRelease(mLinearSampler);
- SafeRelease(mRasterizerState);
+ SafeRelease(mScissorEnabledRasterizerState);
+ SafeRelease(mScissorDisabledRasterizerState);
SafeRelease(mDepthStencilState);
SafeRelease(mQuad2DIL);
@@ -209,18 +216,8 @@
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 @@
// 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,49 +338,6 @@
return true;
}
-static ID3D11Resource *createStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context,
- ID3D11Resource *source, unsigned int subresource,
- const gl::Extents &size, unsigned int cpuAccessFlags)
-{
- ID3D11Texture2D *sourceTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(source);
- if (!sourceTexture)
- {
- return NULL;
- }
-
- D3D11_TEXTURE2D_DESC sourceDesc;
- sourceTexture->GetDesc(&sourceDesc);
-
- if (sourceDesc.SampleDesc.Count > 1)
- {
- // Creating a staging texture of a multisampled texture is not supported
- SafeRelease(sourceTexture);
- return NULL;
- }
-
- D3D11_TEXTURE2D_DESC stagingDesc;
- stagingDesc.Width = size.width;
- stagingDesc.Height = size.height;
- stagingDesc.MipLevels = 1;
- stagingDesc.ArraySize = 1;
- stagingDesc.Format = sourceDesc.Format;
- stagingDesc.SampleDesc.Count = 1;
- stagingDesc.SampleDesc.Quality = 0;
- stagingDesc.Usage = D3D11_USAGE_STAGING;
- stagingDesc.CPUAccessFlags = cpuAccessFlags;
- 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);
@@ -385,6 +354,36 @@
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 = getTextureFormat(source);
+ stagingDesc.SampleDesc.Count = 1;
+ stagingDesc.SampleDesc.Quality = 0;
+ stagingDesc.Usage = D3D11_USAGE_STAGING;
+ stagingDesc.CPUAccessFlags = cpuAccessFlags;
+ stagingDesc.MiscFlags = 0;
+ stagingDesc.BindFlags = 0;
+
+ ID3D11Texture2D *stagingTexture = NULL;
+ HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture);
+ if (FAILED(result))
+ {
+ ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL);
+
+ return stagingTexture;
+}
+
inline static void generateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize,
const gl::Box &destArea, const gl::Extents &destSize,
float *x1, float *y1, float *x2, float *y2,
@@ -450,15 +449,17 @@
}
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 @@
// 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::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 @@
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 @@
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 @@
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);
-
- int startDestX = std::min(destArea.x, destArea.x + destArea.width);
- int endDestX = std::max(destArea.x, destArea.x + destArea.width);
-
- for (int y = startDestY; y < endDestY; y++)
+ if (!sourceMapping.pData || !destMapping.pData)
{
- float yPerc = static_cast<float>(y - startDestY) / (endDestY - startDestY - 1);
- unsigned int readRow = sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f);
+ 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);
+
+ // Clip dest area to the destination size
+ gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea);
+
+ // Clip dest area to the scissor
+ if (scissor)
+ {
+ 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) +
diff --git a/src/libGLESv2/renderer/Blit11.h b/src/libGLESv2/renderer/Blit11.h
index 49468df..0e5eb77 100644
--- a/src/libGLESv2/renderer/Blit11.h
+++ b/src/libGLESv2/renderer/Blit11.h
@@ -30,16 +30,19 @@
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 @@
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 @@
ID3D11Buffer *mVertexBuffer;
ID3D11SamplerState *mPointSampler;
ID3D11SamplerState *mLinearSampler;
- ID3D11RasterizerState *mRasterizerState;
+ ID3D11RasterizerState *mScissorEnabledRasterizerState;
+ ID3D11RasterizerState *mScissorDisabledRasterizerState;
ID3D11DepthStencilState *mDepthStencilState;
ID3D11InputLayout *mQuad2DIL;
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 41b28d5..d3c9dda 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -225,7 +225,7 @@
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;
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 837be4b..3872e71 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -2416,7 +2416,7 @@
// 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 @@
// 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 @@
// 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 @@
// 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::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 @@
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 @@
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 @@
}
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 @@
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 @@
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);
}
}
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index e41b12a..c280f2e 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -169,7 +169,7 @@
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 @@
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;
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 522700b..c699fc9 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -2715,7 +2715,7 @@
}
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 @@
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 @@
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);
diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h
index 99902d7..0a4c2b2 100644
--- a/src/libGLESv2/renderer/Renderer9.h
+++ b/src/libGLESv2/renderer/Renderer9.h
@@ -186,7 +186,7 @@
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);
diff --git a/src/libGLESv2/renderer/TextureStorage11.cpp b/src/libGLESv2/renderer/TextureStorage11.cpp
index 5a7054e..ed73525 100644
--- a/src/libGLESv2/renderer/TextureStorage11.cpp
+++ b/src/libGLESv2/renderer/TextureStorage11.cpp
@@ -140,7 +140,8 @@
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 @@
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);
}
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index eacdd9b..93edd45 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -98,6 +98,31 @@
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 @@
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 @@
}
}
}
-
- 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 @@
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 @@
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 @@
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