Improve color clear precision.
Change-Id: Ib9dadf3d8fee0f63deb10e6754856c0530c928ab
Reviewed-on: https://swiftshader-review.googlesource.com/3995
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/D3D9/Direct3DDevice9.cpp b/src/D3D9/Direct3DDevice9.cpp
index 30d8ea3..ffb7021 100644
--- a/src/D3D9/Direct3DDevice9.cpp
+++ b/src/D3D9/Direct3DDevice9.cpp
@@ -435,24 +435,19 @@
D3DSURFACE_DESC description;
renderTarget[index]->GetDesc(&description);
+ float r = (float)(color & 0x00FF0000) / 0x00FF0000;
+ float g = (float)(color & 0x0000FF00) / 0x0000FF00;
+ float b = (float)(color & 0x000000FF) / 0x000000FF;
+ float a = (float)(color & 0xFF000000) / 0xFF000000;
+
if(renderState[D3DRS_SRGBWRITEENABLE] != FALSE && index == 0 && Capabilities::isSRGBwritable(description.Format))
{
- float r = (float)(color & 0x00FF0000) / 0x00FF0000;
- float g = (float)(color & 0x0000FF00) / 0x0000FF00;
- float b = (float)(color & 0x000000FF) / 0x000000FF;
- float a = (float)(color & 0xFF000000) / 0xFF000000;
-
r = sw::linearToSRGB(r);
g = sw::linearToSRGB(g);
b = sw::linearToSRGB(b);
-
- color = ((int)(a * 255) << 24) |
- ((int)(r * 255) << 16) |
- ((int)(g * 255) << 8) |
- ((int)(b * 255) << 0);
}
- renderTarget[index]->clearColorBuffer(color, 0xF, rect.x1, rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1);
+ renderTarget[index]->clearColorBuffer(r, g, b, a, 0xF, rect.x1, rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1);
}
}
}
diff --git a/src/OpenGL/libGL/Context.cpp b/src/OpenGL/libGL/Context.cpp
index 5ca3b5e..0c718a4 100644
--- a/src/OpenGL/libGL/Context.cpp
+++ b/src/OpenGL/libGL/Context.cpp
@@ -2454,11 +2454,7 @@
{
return;
}
-
- unsigned int color = (unorm<8>(mState.colorClearValue.alpha) << 24) |
- (unorm<8>(mState.colorClearValue.red) << 16) |
- (unorm<8>(mState.colorClearValue.green) << 8) |
- (unorm<8>(mState.colorClearValue.blue) << 0);
+
float depth = clamp01(mState.depthClearValue);
int stencil = mState.stencilClearValue & 0x000000FF;
@@ -2471,7 +2467,7 @@
if(rgbaMask != 0)
{
- device->clearColor(color, rgbaMask);
+ device->clearColor(mState.colorClearValue.red, mState.colorClearValue.green, mState.colorClearValue.blue, mState.colorClearValue.alpha, rgbaMask);
}
}
diff --git a/src/OpenGL/libGL/Device.cpp b/src/OpenGL/libGL/Device.cpp
index f9250bd..c4b1318 100644
--- a/src/OpenGL/libGL/Device.cpp
+++ b/src/OpenGL/libGL/Device.cpp
@@ -178,7 +178,7 @@
delete context;
}
- void Device::clearColor(unsigned int color, unsigned int rgbaMask)
+ void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
{
if(!renderTarget)
{
@@ -198,7 +198,7 @@
if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
}
- renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
+ renderTarget->clearColorBuffer(red, green, blue, alpha, rgbaMask, x0, y0, width, height);
}
void Device::clearDepth(float z)
diff --git a/src/OpenGL/libGL/Device.hpp b/src/OpenGL/libGL/Device.hpp
index dec8dfb..a3e2274 100644
--- a/src/OpenGL/libGL/Device.hpp
+++ b/src/OpenGL/libGL/Device.hpp
@@ -48,7 +48,7 @@
virtual ~Device();
- virtual void clearColor(unsigned int color, unsigned int rgbaMask);
+ virtual void clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask);
virtual void clearDepth(float z);
virtual void clearStencil(unsigned int stencil, unsigned int mask);
virtual Image *createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard);
diff --git a/src/OpenGL/libGLES_CM/Context.cpp b/src/OpenGL/libGLES_CM/Context.cpp
index e54ee16..435b716 100644
--- a/src/OpenGL/libGLES_CM/Context.cpp
+++ b/src/OpenGL/libGLES_CM/Context.cpp
@@ -2659,10 +2659,6 @@
return;
}
- unsigned int color = (unorm<8>(mState.colorClearValue.alpha) << 24) |
- (unorm<8>(mState.colorClearValue.red) << 16) |
- (unorm<8>(mState.colorClearValue.green) << 8) |
- (unorm<8>(mState.colorClearValue.blue) << 0);
float depth = clamp01(mState.depthClearValue);
int stencil = mState.stencilClearValue & 0x000000FF;
@@ -2675,7 +2671,7 @@
if(rgbaMask != 0)
{
- device->clearColor(color, rgbaMask);
+ device->clearColor(mState.colorClearValue.red, mState.colorClearValue.green, mState.colorClearValue.blue, mState.colorClearValue.alpha, rgbaMask);
}
}
diff --git a/src/OpenGL/libGLES_CM/Device.cpp b/src/OpenGL/libGLES_CM/Device.cpp
index 043afdf..6b4fa9f 100644
--- a/src/OpenGL/libGLES_CM/Device.cpp
+++ b/src/OpenGL/libGLES_CM/Device.cpp
@@ -136,7 +136,7 @@
delete context;
}
- void Device::clearColor(unsigned int color, unsigned int rgbaMask)
+ void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
{
if(!renderTarget)
{
@@ -156,7 +156,7 @@
if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
}
- renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
+ renderTarget->clearColorBuffer(red, green, blue, alpha, rgbaMask, x0, y0, width, height);
}
void Device::clearDepth(float z)
diff --git a/src/OpenGL/libGLES_CM/Device.hpp b/src/OpenGL/libGLES_CM/Device.hpp
index 699cc51..abfbd13 100644
--- a/src/OpenGL/libGLES_CM/Device.hpp
+++ b/src/OpenGL/libGLES_CM/Device.hpp
@@ -51,7 +51,7 @@
virtual ~Device();
- virtual void clearColor(unsigned int color, unsigned int rgbaMask);
+ virtual void clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask);
virtual void clearDepth(float z);
virtual void clearStencil(unsigned int stencil, unsigned int mask);
virtual egl::Image *createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard);
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index e4f71f3..0411a68 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3538,11 +3538,7 @@
if(rgbaMask != 0)
{
- unsigned int color = (unorm<8>(mState.colorClearValue.alpha) << 24) |
- (unorm<8>(mState.colorClearValue.red) << 16) |
- (unorm<8>(mState.colorClearValue.green) << 8) |
- (unorm<8>(mState.colorClearValue.blue) << 0);
- device->clearColor(color, rgbaMask);
+ device->clearColor(mState.colorClearValue.red, mState.colorClearValue.green, mState.colorClearValue.blue, mState.colorClearValue.alpha, rgbaMask);
}
}
@@ -3573,11 +3569,12 @@
int x0(0), y0(0), width(0), height(0);
egl::Image* image = getScissoredImage(drawbuffer, x0, y0, width, height, false);
- unsigned int color = (value[0] < 0 ? 0 : (value[0] & 0x7F800000) << 1) |
- (value[1] < 0 ? 0 : (value[1] & 0x7F800000) >> 7) |
- (value[2] < 0 ? 0 : (value[2] & 0x7F800000) >> 15) |
- (value[3] < 0 ? 0 : (value[3] & 0x7F800000) >> 23);
- image->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
+ float red = clamp01((float)value[0] / 0x7FFFFFFF);
+ float green = clamp01((float)value[1] / 0x7FFFFFFF);
+ float blue = clamp01((float)value[2] / 0x7FFFFFFF);
+ float alpha = clamp01((float)value[3] / 0x7FFFFFFF);
+
+ image->clearColorBuffer(red, green, blue, alpha, rgbaMask, x0, y0, width, height);
}
}
@@ -3589,11 +3586,12 @@
int x0(0), y0(0), width(0), height(0);
egl::Image* image = getScissoredImage(drawbuffer, x0, y0, width, height, false);
- unsigned int color = (value[0] & 0xFF000000) >> 0 |
- (value[1] & 0xFF000000) >> 8 |
- (value[2] & 0xFF000000) >> 16 |
- (value[3] & 0xFF000000) >> 24;
- image->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
+ float red = (float)value[0] / 0xFFFFFFFF;
+ float green = (float)value[1] / 0xFFFFFFFF;
+ float blue = (float)value[2] / 0xFFFFFFFF;
+ float alpha = (float)value[3] / 0xFFFFFFFF;
+
+ image->clearColorBuffer(red, green, blue, alpha, rgbaMask, x0, y0, width, height);
}
}
@@ -3605,11 +3603,12 @@
int x0(0), y0(0), width(0), height(0);
egl::Image* image = getScissoredImage(drawbuffer, x0, y0, width, height, false);
- unsigned int color = (unorm<8>(value[0]) << 24) |
- (unorm<8>(value[1]) << 16) |
- (unorm<8>(value[2]) << 8) |
- (unorm<8>(value[3]) << 0);
- image->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
+ float red = clamp01(value[0]);
+ float green = clamp01(value[1]);
+ float blue = clamp01(value[2]);
+ float alpha = clamp01(value[3]);
+
+ image->clearColorBuffer(red, green, blue, alpha, rgbaMask, x0, y0, width, height);
}
}
diff --git a/src/OpenGL/libGLESv2/Device.cpp b/src/OpenGL/libGLESv2/Device.cpp
index f162dcd..5b77c27 100644
--- a/src/OpenGL/libGLESv2/Device.cpp
+++ b/src/OpenGL/libGLESv2/Device.cpp
@@ -175,7 +175,7 @@
}
}
- void Device::clearColor(unsigned int color, unsigned int rgbaMask)
+ void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
{
if(!renderTarget)
{
@@ -185,7 +185,7 @@
int x0(0), y0(0), width(0), height(0);
getScissoredRegion(renderTarget, x0, y0, width, height);
- renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
+ renderTarget->clearColorBuffer(red, green, blue, alpha, rgbaMask, x0, y0, width, height);
}
void Device::clearDepth(float z)
diff --git a/src/OpenGL/libGLESv2/Device.hpp b/src/OpenGL/libGLESv2/Device.hpp
index b6bb533..3d6f552c 100644
--- a/src/OpenGL/libGLESv2/Device.hpp
+++ b/src/OpenGL/libGLESv2/Device.hpp
@@ -51,7 +51,7 @@
virtual ~Device();
- virtual void clearColor(unsigned int color, unsigned int rgbaMask);
+ virtual void clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask);
virtual void clearDepth(float z);
virtual void clearStencil(unsigned int stencil, unsigned int mask);
virtual egl::Image *createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard);
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index 3a72601..0919066 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -2797,7 +2797,7 @@
}
}
- void Surface::clearColorBuffer(unsigned int colorARGB, unsigned int rgbaMask, int x0, int y0, int width, int height)
+ void Surface::clearColorBuffer(float red, float green, float blue, float alpha, unsigned int rgbaMask, int x0, int y0, int width, int height)
{
// FIXME: Also clear buffers in other formats?
@@ -2837,30 +2837,39 @@
case FORMAT_A8R8G8B8:
// case FORMAT_X8G8R8B8Q: // FIXME
// case FORMAT_A8G8R8B8Q: // FIXME
- if(rgbaMask == 0xF || (internal.format == FORMAT_X8R8G8B8 && rgbaMask == 0x7))
{
- memfill4(target, colorARGB, 4 * (x1 - x0));
- }
- else
- {
- unsigned int bgraMask = (rgbaMask & 0x1 ? 0x00FF0000 : 0) | (rgbaMask & 0x2 ? 0x0000FF00 : 0) | (rgbaMask & 0x4 ? 0x000000FF : 0) | (rgbaMask & 0x8 ? 0xFF000000 : 0);
- unsigned int invMask = ~bgraMask;
- unsigned int maskedColor = colorARGB & bgraMask;
- unsigned int *target32 = (unsigned int*)target;
+ unsigned char r8 = iround(red * 0xFF);
+ unsigned char g8 = iround(green * 0xFF);
+ unsigned char b8 = iround(blue * 0xFF);
+ unsigned char a8 = iround(alpha * 0xFF);
+ unsigned char a8r8g8b8[4] = {b8, g8, r8, a8};
+ unsigned int colorARGB = (unsigned int&)a8r8g8b8;
- for(int x = 0; x < width; x++)
+ if(rgbaMask == 0xF || (internal.format == FORMAT_X8R8G8B8 && rgbaMask == 0x7))
{
- target32[x] = maskedColor | (target32[x] & invMask);
+ memfill4(target, colorARGB, 4 * (x1 - x0));
+ }
+ else
+ {
+ unsigned int bgraMask = (rgbaMask & 0x1 ? 0x00FF0000 : 0) | (rgbaMask & 0x2 ? 0x0000FF00 : 0) | (rgbaMask & 0x4 ? 0x000000FF : 0) | (rgbaMask & 0x8 ? 0xFF000000 : 0);
+ unsigned int invMask = ~bgraMask;
+ unsigned int maskedColor = colorARGB & bgraMask;
+ unsigned int *target32 = (unsigned int*)target;
+
+ for(int x = 0; x < width; x++)
+ {
+ target32[x] = maskedColor | (target32[x] & invMask);
+ }
}
}
break;
case FORMAT_X8B8G8R8:
case FORMAT_A8B8G8R8:
{
- unsigned char r8 = (colorARGB & 0x00FF0000) >> 16;
- unsigned char g8 = (colorARGB & 0x0000FF00) >> 8;
- unsigned char b8 = (colorARGB & 0x000000FF) >> 0;
- unsigned char a8 = (colorARGB & 0xFF000000) >> 24;
+ unsigned char r8 = iround(red * 0xFF);
+ unsigned char g8 = iround(green * 0xFF);
+ unsigned char b8 = iround(blue * 0xFF);
+ unsigned char a8 = iround(alpha * 0xFF);
unsigned char a8b8g8r8[4] = {r8, g8, b8, a8};
unsigned int colorABGR = (unsigned int&)a8b8g8r8;
@@ -2884,8 +2893,8 @@
break;
case FORMAT_G8R8:
{
- unsigned char r8 = (colorARGB & 0x00FF0000) >> 16;
- unsigned char g8 = (colorARGB & 0x0000FF00) >> 8;
+ unsigned char r8 = iround(red * 0xFF);
+ unsigned char g8 = iround(green * 0xFF);
unsigned char g8r8[4] = {r8, g8, r8, g8};
if((rgbaMask & 0x3) == 0x3)
@@ -2908,10 +2917,8 @@
break;
case FORMAT_G16R16:
{
- unsigned char r8 = (colorARGB & 0x00FF0000) >> 16;
- unsigned char g8 = (colorARGB & 0x0000FF00) >> 8;
- unsigned short r16 = (r8 << 8) | r8;
- unsigned short g16 = (g8 << 8) | g8;
+ unsigned char r16 = iround(red * 0xFFFF);
+ unsigned char g16 = iround(green * 0xFFFF);
unsigned short g16r16[2] = {r16, g16};
if((rgbaMask & 0x3) == 0x3)
@@ -2934,14 +2941,10 @@
break;
case FORMAT_A16B16G16R16:
{
- unsigned char r8 = (colorARGB & 0x00FF0000) >> 16;
- unsigned char g8 = (colorARGB & 0x0000FF00) >> 8;
- unsigned char b8 = (colorARGB & 0x000000FF) >> 0;
- unsigned char a8 = (colorARGB & 0xFF000000) >> 24;
- unsigned short r16 = (r8 << 8) | r8;
- unsigned short g16 = (g8 << 8) | g8;
- unsigned short b16 = (b8 << 8) | b8;
- unsigned short a16 = (a8 << 8) | a8;
+ unsigned char r16 = iround(red * 0xFFFF);
+ unsigned char g16 = iround(green * 0xFFFF);
+ unsigned char b16 = iround(blue * 0xFFFF);
+ unsigned char a16 = iround(alpha * 0xFFFF);
if(rgbaMask == 0xF)
{
@@ -2965,63 +2968,52 @@
case FORMAT_R32F:
if(rgbaMask & 0x1)
{
- float r32f = (float)(colorARGB & 0x00FF0000) / 0x00FF0000;
-
for(int x = 0; x < width; x++)
{
- ((float*)target)[x] = r32f;
+ ((float*)target)[x] = red;
}
}
break;
case FORMAT_G32R32F:
+ if((rgbaMask & 0x3) == 0x3)
{
- float r32f = (float)(colorARGB & 0x00FF0000) / 0x00FF0000;
- float g32f = (float)(colorARGB & 0x0000FF00) / 0x0000FF00;
-
- if((rgbaMask & 0x3) == 0x3)
+ for(int x = 0; x < width; x++)
{
- for(int x = 0; x < width; x++)
- {
- ((float*)target)[2 * x + 0] = r32f;
- ((float*)target)[2 * x + 1] = g32f;
- }
+ ((float*)target)[2 * x + 0] = red;
+ ((float*)target)[2 * x + 1] = green;
}
- else
- {
- if(rgbaMask & 0x1) for(int x = 0; x < width; x++) ((float*)target)[2 * x + 0] = r32f;
- if(rgbaMask & 0x2) for(int x = 0; x < width; x++) ((float*)target)[2 * x + 1] = g32f;
- }
+ }
+ else
+ {
+ if(rgbaMask & 0x1) for(int x = 0; x < width; x++) ((float*)target)[2 * x + 0] = red;
+ if(rgbaMask & 0x2) for(int x = 0; x < width; x++) ((float*)target)[2 * x + 1] = green;
}
break;
case FORMAT_A32B32G32R32F:
+ if(rgbaMask == 0xF)
{
- float r32f = (float)(colorARGB & 0x00FF0000) / 0x00FF0000;
- float g32f = (float)(colorARGB & 0x0000FF00) / 0x0000FF00;
- float b32f = (float)(colorARGB & 0x000000FF) / 0x000000FF;
- float a32f = (float)(colorARGB & 0xFF000000) / 0xFF000000;
-
- if(rgbaMask == 0xF)
+ for(int x = 0; x < width; x++)
{
- for(int x = 0; x < width; x++)
- {
- ((float*)target)[4 * x + 0] = r32f;
- ((float*)target)[4 * x + 1] = g32f;
- ((float*)target)[4 * x + 2] = b32f;
- ((float*)target)[4 * x + 3] = a32f;
- }
+ ((float*)target)[4 * x + 0] = red;
+ ((float*)target)[4 * x + 1] = green;
+ ((float*)target)[4 * x + 2] = blue;
+ ((float*)target)[4 * x + 3] = alpha;
}
- else
- {
- if(rgbaMask & 0x1) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 0] = r32f;
- if(rgbaMask & 0x2) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 1] = g32f;
- if(rgbaMask & 0x4) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 2] = b32f;
- if(rgbaMask & 0x8) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 3] = a32f;
- }
+ }
+ else
+ {
+ if(rgbaMask & 0x1) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 0] = red;
+ if(rgbaMask & 0x2) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 1] = green;
+ if(rgbaMask & 0x4) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 2] = blue;
+ if(rgbaMask & 0x8) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 3] = alpha;
}
break;
case FORMAT_R5G6B5:
{
- unsigned int r5g6b5 = ((colorARGB >> 8) & 0xF800) | ((colorARGB >> 5) & 0x07E0) | ((colorARGB >> 3) & 0x001F);
+ unsigned int r5 = iround(red * 0x1F);
+ unsigned int g6 = iround(green * 0x3F);
+ unsigned int b5 = iround(blue * 0x1F);
+ unsigned int r5g6b5 = (r5 << 11) | (g6 << 5) | b5;
if((rgbaMask & 0x7) == 0x7)
{
diff --git a/src/Renderer/Surface.hpp b/src/Renderer/Surface.hpp
index 48502c4..9860b6d 100644
--- a/src/Renderer/Surface.hpp
+++ b/src/Renderer/Surface.hpp
@@ -254,7 +254,7 @@
inline int getMultiSampleCount() const;
inline int getSuperSampleCount() const;
- void clearColorBuffer(unsigned int colorARGB, unsigned int rgbaMask, int x0, int y0, int width, int height);
+ void clearColorBuffer(float red, float green, float blue, float alpha, unsigned int rgbaMask, int x0, int y0, int width, int height);
void clearDepthBuffer(float depth, int x0, int y0, int width, int height);
void clearStencilBuffer(unsigned char stencil, unsigned char mask, int x0, int y0, int width, int height);
void fill(const Color<float> &color, int x0, int y0, int width, int height);