Adding multisampling to texture3D test
Required adding X and Y flipping to blitter.
Change-Id: Icaac4045ae9419296112464d7ccdde7babb76eb3
Reviewed-on: https://swiftshader-review.googlesource.com/2180
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 14808e7..253264a 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -2877,38 +2877,54 @@
sw::SliceRect sourceRect;
sw::SliceRect destRect;
+ bool flipX = (srcX0 < srcX1) ^ (dstX0 < dstX1);
+ bool flipy = (srcY0 < srcY1) ^ (dstY0 < dstY1);
if(srcX0 < srcX1)
{
sourceRect.x0 = srcX0;
sourceRect.x1 = srcX1;
- destRect.x0 = dstX0;
- destRect.x1 = dstX1;
}
else
{
sourceRect.x0 = srcX1;
- destRect.x0 = dstX1;
sourceRect.x1 = srcX0;
- destRect.x1 = dstX0;
}
+ if(dstX0 < dstX1)
+ {
+ destRect.x0 = dstX0;
+ destRect.x1 = dstX1;
+ }
+ else
+ {
+ destRect.x0 = dstX1;
+ destRect.x1 = dstX0;
+ }
+
if(srcY0 < srcY1)
{
sourceRect.y0 = srcY0;
- destRect.y0 = dstY0;
sourceRect.y1 = srcY1;
- destRect.y1 = dstY1;
}
else
{
sourceRect.y0 = srcY1;
- destRect.y0 = dstY1;
sourceRect.y1 = srcY0;
- destRect.y1 = dstY0;
}
- sw::Rect sourceScissoredRect = sourceRect;
+ if(dstY0 < dstY1)
+ {
+ destRect.y0 = dstY0;
+ destRect.y1 = dstY1;
+ }
+ else
+ {
+ destRect.y0 = dstY1;
+ destRect.y1 = dstY0;
+ }
+
+ sw::Rect sourceScissoredRect = sourceRect;
sw::Rect destScissoredRect = destRect;
if(mState.scissorTest) // Only write to parts of the destination framebuffer which pass the scissor test
@@ -3023,10 +3039,8 @@
readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
- if(!validReadType || !validDrawType ||
- readFramebuffer->getColorbuffer()->getInternalFormat() != drawFramebuffer->getColorbuffer()->getInternalFormat())
+ if(!validReadType || !validDrawType)
{
- ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
return error(GL_INVALID_OPERATION);
}
@@ -3050,8 +3064,7 @@
{
if(readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
{
- if(readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
- readFramebuffer->getDepthbuffer()->getInternalFormat() != drawFramebuffer->getDepthbuffer()->getInternalFormat())
+ if(readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType())
{
return error(GL_INVALID_OPERATION);
}
@@ -3066,8 +3079,7 @@
{
if(readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
{
- if(readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
- readFramebuffer->getStencilbuffer()->getInternalFormat() != drawFramebuffer->getStencilbuffer()->getInternalFormat())
+ if(readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType())
{
return error(GL_INVALID_OPERATION);
}
@@ -3098,6 +3110,15 @@
egl::Image *readRenderTarget = readFramebuffer->getRenderTarget();
egl::Image *drawRenderTarget = drawFramebuffer->getRenderTarget();
+ if(flipX)
+ {
+ swap(destRect.x0, destRect.x1);
+ }
+ if(flipy)
+ {
+ swap(destRect.y0, destRect.y1);
+ }
+
bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, false);
readRenderTarget->release();
@@ -3105,7 +3126,7 @@
if(!success)
{
- ERR("BlitFramebufferANGLE failed.");
+ ERR("BlitFramebuffer failed.");
return;
}
}
@@ -3116,7 +3137,7 @@
if(!success)
{
- ERR("BlitFramebufferANGLE failed.");
+ ERR("BlitFramebuffer failed.");
return;
}
}
diff --git a/src/OpenGL/libGLESv2/Device.cpp b/src/OpenGL/libGLESv2/Device.cpp
index edeb0d7..e9d8fbe 100644
--- a/src/OpenGL/libGLESv2/Device.cpp
+++ b/src/OpenGL/libGLESv2/Device.cpp
@@ -470,9 +470,58 @@
this->viewport = viewport;
}
+ void Device::copyBuffer(sw::byte *sourceBuffer, sw::byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY)
+ {
+ unsigned int widthB = width * bytes;
+ unsigned int widthMaxB = widthB - 1;
+
+ if(flipX)
+ {
+ if(flipY)
+ {
+ sourceBuffer += (height - 1) * sourcePitch;
+ for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
+ {
+ for(unsigned int x = 0; x < widthB; ++x)
+ {
+ destBuffer[x] = sourceBuffer[widthMaxB - x];
+ }
+ }
+ }
+ else
+ {
+ for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
+ {
+ for(unsigned int x = 0; x < widthB; ++x)
+ {
+ destBuffer[x] = sourceBuffer[widthMaxB - x];
+ }
+ }
+ }
+ }
+ else
+ {
+ if(flipY)
+ {
+ sourceBuffer += (height - 1) * sourcePitch;
+ for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
+ {
+ memcpy(destBuffer, sourceBuffer, widthB);
+ }
+ }
+ else
+ {
+ for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
+ {
+ memcpy(destBuffer, sourceBuffer, widthB);
+ }
+ }
+ }
+ }
+
bool Device::stretchRect(egl::Image *source, const sw::SliceRect *sourceRect, egl::Image *dest, const sw::SliceRect *destRect, bool filter)
{
- if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
+ if(!source || !dest)
{
ERR("Invalid parameters");
return false;
@@ -483,12 +532,40 @@
int dWidth = dest->getExternalWidth();
int dHeight = dest->getExternalHeight();
+ bool flipX = false;
+ bool flipY = false;
+ if(sourceRect && destRect)
+ {
+ flipX = (sourceRect->x0 < sourceRect->x1) ^ (destRect->x0 < destRect->x1);
+ flipY = (sourceRect->y0 < sourceRect->y1) ^ (destRect->y0 < destRect->y1);
+ }
+ else if(sourceRect)
+ {
+ flipX = (sourceRect->x0 > sourceRect->x1);
+ flipY = (sourceRect->y0 > sourceRect->y1);
+ }
+ else if(destRect)
+ {
+ flipX = (destRect->x0 > destRect->x1);
+ flipY = (destRect->y0 > destRect->y1);
+ }
+
SliceRect sRect;
SliceRect dRect;
if(sourceRect)
{
sRect = *sourceRect;
+
+ if(sRect.x0 > sRect.x1)
+ {
+ swap(sRect.x0, sRect.x1);
+ }
+
+ if(sRect.y0 > sRect.y1)
+ {
+ swap(sRect.y0, sRect.y1);
+ }
}
else
{
@@ -501,6 +578,16 @@
if(destRect)
{
dRect = *destRect;
+
+ if(dRect.x0 > dRect.x1)
+ {
+ swap(dRect.x0, dRect.x1);
+ }
+
+ if(dRect.y0 > dRect.y1)
+ {
+ swap(dRect.y0, dRect.y1);
+ }
}
else
{
@@ -510,6 +597,12 @@
dRect.x1 = dWidth;
}
+ if(!validRectangle(&sRect, source) || !validRectangle(&dRect, dest))
+ {
+ ERR("Invalid parameters");
+ return false;
+ }
+
bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
bool depthStencil = Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat());
@@ -529,17 +622,7 @@
sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sourceRect->slice, LOCK_READONLY, PUBLIC);
sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, destRect->slice, LOCK_DISCARD, PUBLIC);
- unsigned int width = source->getInternalWidth();
- unsigned int height = source->getInternalHeight();
- unsigned int pitch = source->getInternalPitchB();
-
- for(unsigned int y = 0; y < height; y++)
- {
- memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes
-
- sourceBuffer += pitch;
- destBuffer += pitch;
- }
+ copyBuffer(sourceBuffer, destBuffer, source->getInternalWidth(), source->getInternalHeight(), source->getInternalPitchB(), dest->getInternalPitchB(), Image::bytes(source->getInternalFormat()), flipX, flipY);
source->unlockInternal();
dest->unlockInternal();
@@ -550,17 +633,7 @@
sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC);
sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC);
- unsigned int width = source->getInternalWidth();
- unsigned int height = source->getInternalHeight();
- unsigned int pitch = source->getStencilPitchB();
-
- for(unsigned int y = 0; y < height; y++)
- {
- memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes
-
- sourceBuffer += pitch;
- destBuffer += pitch;
- }
+ copyBuffer(sourceBuffer, destBuffer, source->getInternalWidth(), source->getInternalHeight(), source->getInternalPitchB(), dest->getInternalPitchB(), Image::bytes(source->getInternalFormat()), flipX, flipY);
source->unlockStencil();
dest->unlockStencil();
@@ -575,22 +648,18 @@
unsigned int width = dRect.x1 - dRect.x0;
unsigned int height = dRect.y1 - dRect.y0;
- unsigned int bytes = width * Image::bytes(source->getInternalFormat());
- for(unsigned int y = 0; y < height; y++)
+ copyBuffer(sourceBytes, destBytes, width, height, sourcePitch, destPitch, Image::bytes(source->getInternalFormat()), flipX, flipY);
+
+ if(alpha0xFF)
{
- memcpy(destBytes, sourceBytes, bytes);
-
- if(alpha0xFF)
+ for(unsigned int y = 0; y < height; ++y, destBytes += destPitch)
{
- for(unsigned int x = 0; x < width; x++)
+ for(unsigned int x = 0; x < width; ++x)
{
destBytes[4 * x + 3] = 0xFF;
}
}
-
- sourceBytes += sourcePitch;
- destBytes += destPitch;
}
source->unlockInternal();
@@ -598,6 +667,14 @@
}
else
{
+ if(flipX)
+ {
+ swap(dRect.x0, dRect.x1);
+ }
+ if(flipY)
+ {
+ swap(dRect.y0, dRect.y1);
+ }
blit(source, sRect, dest, dRect, scaling && filter);
}
diff --git a/src/OpenGL/libGLESv2/Device.hpp b/src/OpenGL/libGLESv2/Device.hpp
index 4dbe2e5..cbdb8bb 100644
--- a/src/OpenGL/libGLESv2/Device.hpp
+++ b/src/OpenGL/libGLESv2/Device.hpp
@@ -81,6 +81,8 @@
bool validRectangle(const sw::Rect *rect, egl::Image *surface);
+ void copyBuffer(sw::byte *sourceBuffer, sw::byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY);
+
Viewport viewport;
sw::Rect scissorRect;
bool scissorEnable;
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 951a019..7e1526a 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -2974,6 +2974,7 @@
"GL_EXT_texture_filter_anisotropic "
"GL_EXT_texture_format_BGRA8888 "
"GL_ANGLE_framebuffer_blit "
+ "GL_NV_framebuffer_blit "
"GL_ANGLE_framebuffer_multisample "
#if (S3TC_SUPPORT)
"GL_ANGLE_texture_compression_dxt3 "
@@ -5129,8 +5130,7 @@
}
}
-void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
+void GL_APIENTRY glBlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
"GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
@@ -5150,12 +5150,6 @@
return error(GL_INVALID_VALUE);
}
- if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
- {
- ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
- return error(GL_INVALID_OPERATION);
- }
-
es2::Context *context = es2::getContext();
if(context)
@@ -5170,6 +5164,18 @@
}
}
+void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
+ {
+ ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
+ return error(GL_INVALID_OPERATION);
+ }
+
+ glBlitFramebufferNV(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+}
+
void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
@@ -5614,6 +5620,7 @@
EXTENSION(glTexImage3DOES),
EXTENSION(glBlitFramebufferANGLE),
+ EXTENSION(glBlitFramebufferNV),
EXTENSION(glRenderbufferStorageMultisampleANGLE),
EXTENSION(glDeleteFencesNV),
EXTENSION(glGenFencesNV),
diff --git a/src/OpenGL/libGLESv2/mathutil.h b/src/OpenGL/libGLESv2/mathutil.h
index 6ac1f37..8e62a06 100644
--- a/src/OpenGL/libGLESv2/mathutil.h
+++ b/src/OpenGL/libGLESv2/mathutil.h
@@ -51,6 +51,14 @@
return x < min ? min : (x > max ? max : x);
}
+template<class T>
+inline void swap(T &a, T &b)
+{
+ T t = a;
+ a = b;
+ b = t;
+}
+
inline float clamp01(float x)
{
return clamp(x, 0.0f, 1.0f);
diff --git a/src/Renderer/Blitter.cpp b/src/Renderer/Blitter.cpp
index 3bf1f39..6b893fc 100644
--- a/src/Renderer/Blitter.cpp
+++ b/src/Renderer/Blitter.cpp
@@ -26,24 +26,42 @@
delete blitCache;
}
- void Blitter::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter)
+ void Blitter::blit(Surface *source, const SliceRect &sourceRect, Surface *dest, const SliceRect &destRect, bool filter)
{
- if(blitReactor(source, sRect, dest, dRect, filter))
+ if(blitReactor(source, sourceRect, dest, destRect, filter))
{
return;
}
+ SliceRect sRect = sourceRect;
+ SliceRect dRect = destRect;
+
+ bool flipX = destRect.x0 > destRect.x1;
+ bool flipY = destRect.y0 > destRect.y1;
+
+ if(flipX)
+ {
+ swap(dRect.x0, dRect.x1);
+ swap(sRect.x0, sRect.x1);
+ }
+ if(flipY)
+ {
+ swap(dRect.y0, dRect.y1);
+ swap(sRect.y0, sRect.y1);
+ }
+
source->lockInternal(sRect.x0, sRect.y0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
float w = 1.0f / (dRect.x1 - dRect.x0) * (sRect.x1 - sRect.x0);
float h = 1.0f / (dRect.y1 - dRect.y0) * (sRect.y1 - sRect.y0);
+ const float xStart = (float)sRect.x0 + 0.5f * w;
float y = (float)sRect.y0 + 0.5f * h;
for(int j = dRect.y0; j < dRect.y1; j++)
{
- float x = (float)sRect.x0 + 0.5f * w;
+ float x = xStart;
for(int i = dRect.x0; i < dRect.x1; i++)
{
@@ -115,8 +133,21 @@
return true;
}
- bool Blitter::blitReactor(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter)
+ bool Blitter::blitReactor(Surface *source, const SliceRect &sourceRect, Surface *dest, const SliceRect &destRect, bool filter)
{
+ Rect dRect = destRect;
+ Rect sRect = sourceRect;
+ if(destRect.x0 > destRect.x1)
+ {
+ swap(dRect.x0, dRect.x1);
+ swap(sRect.x0, sRect.x1);
+ }
+ if(destRect.y0 > destRect.y1)
+ {
+ swap(dRect.y0, dRect.y1);
+ swap(sRect.y0, sRect.y1);
+ }
+
BlitState state;
state.sourceFormat = source->getInternalFormat();
@@ -154,6 +185,7 @@
For(Int j = y0d, j < y1d, j++)
{
Float x = x0;
+ Pointer<Byte> destLine = dest + j * dPitchB;
For(Int i = x0d, i < x1d, i++)
{
@@ -262,7 +294,7 @@
Surface::isUnsignedComponent(state.destFormat, 3) ? 0.0f : -1.0f));
}
- Pointer<Byte> d = dest + j * dPitchB + i * Surface::bytes(state.destFormat);
+ Pointer<Byte> d = destLine + i * Surface::bytes(state.destFormat);
switch(state.destFormat)
{
@@ -321,8 +353,8 @@
BlitData data;
- data.source = source->lockInternal(0, 0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
- data.dest = dest->lockInternal(0, 0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
+ data.source = source->lockInternal(0, 0, sourceRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
+ data.dest = dest->lockInternal(0, 0, destRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
data.sPitchB = source->getInternalPitchB();
data.dPitchB = dest->getInternalPitchB();