glClearBuffer implementation
Implemented glClearBuffer* functions.
Right now, all colors are represented
as floats internally, but should that
change, and integer types be supported,
we'd be able to remove the casts to
float here.
Change-Id: Ie785858d77ce7ac03b78fca9e43ac922c15e76e0
Reviewed-on: https://swiftshader-review.googlesource.com/3004
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 a66da83..3c0aaea 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -703,6 +703,14 @@
}
}
+unsigned int Context::getColorMask() const
+{
+ return (mState.colorMaskRed ? 0x1 : 0) |
+ (mState.colorMaskGreen ? 0x2 : 0) |
+ (mState.colorMaskBlue ? 0x4 : 0) |
+ (mState.colorMaskAlpha ? 0x8 : 0);
+}
+
void Context::setDepthMask(bool mask)
{
if(mState.depthMask != mask)
@@ -2530,6 +2538,34 @@
return true;
}
+void Context::applyScissor(int width, int height)
+{
+ if(mState.scissorTest)
+ {
+ sw::Rect scissor = { mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight };
+ scissor.clip(0, 0, width, height);
+
+ device->setScissorRect(scissor);
+ device->setScissorEnable(true);
+ }
+ else
+ {
+ device->setScissorEnable(false);
+ }
+}
+
+egl::Image *Context::getScissoredImage(GLint drawbuffer, int &x0, int &y0, int &width, int &height, bool depthStencil)
+{
+ Framebuffer* framebuffer = getFramebuffer(drawbuffer);
+ egl::Image* image = depthStencil ? framebuffer->getDepthStencil() : framebuffer->getRenderTarget(0);
+
+ applyScissor(image->getWidth(), image->getHeight());
+
+ device->getScissoredRegion(image, x0, y0, width, height);
+
+ return image;
+}
+
// Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle
bool Context::applyRenderTarget()
{
@@ -2562,18 +2598,7 @@
device->setViewport(viewport);
- if(mState.scissorTest)
- {
- sw::Rect scissor = {mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight};
- scissor.clip(0, 0, width, height);
-
- device->setScissorRect(scissor);
- device->setScissorEnable(true);
- }
- else
- {
- device->setScissorEnable(false);
- }
+ applyScissor(width, height);
Program *program = getCurrentProgram();
@@ -3368,22 +3393,16 @@
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;
-
if(mask & GL_COLOR_BUFFER_BIT)
{
- unsigned int rgbaMask = (mState.colorMaskRed ? 0x1 : 0) |
- (mState.colorMaskGreen ? 0x2 : 0) |
- (mState.colorMaskBlue ? 0x4 : 0) |
- (mState.colorMaskAlpha ? 0x8 : 0);
+ unsigned int rgbaMask = getColorMask();
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);
}
}
@@ -3392,6 +3411,7 @@
{
if(mState.depthMask != 0)
{
+ float depth = clamp01(mState.depthClearValue);
device->clearDepth(depth);
}
}
@@ -3400,11 +3420,103 @@
{
if(mState.stencilWritemask != 0)
{
+ int stencil = mState.stencilClearValue & 0x000000FF;
device->clearStencil(stencil, mState.stencilWritemask);
}
}
}
+void Context::clearColorBuffer(GLint drawbuffer, const GLint *value)
+{
+ unsigned int rgbaMask = getColorMask();
+ if(device && rgbaMask)
+ {
+ 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);
+ }
+}
+
+void Context::clearColorBuffer(GLint drawbuffer, const GLuint *value)
+{
+ unsigned int rgbaMask = getColorMask();
+ if(device && rgbaMask)
+ {
+ 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);
+ }
+}
+
+void Context::clearColorBuffer(GLint drawbuffer, const GLfloat *value)
+{
+ unsigned int rgbaMask = getColorMask();
+ if(device && rgbaMask)
+ {
+ 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);
+ }
+}
+
+void Context::clearDepthBuffer(GLint drawbuffer, const GLfloat *value)
+{
+ if(device && mState.depthMask)
+ {
+ int x0(0), y0(0), width(0), height(0);
+ egl::Image* image = getScissoredImage(drawbuffer, x0, y0, width, height, true);
+
+ float depth = clamp01(value[0]);
+ image->clearDepthBuffer(depth, x0, y0, width, height);
+ }
+}
+
+void Context::clearStencilBuffer(GLint drawbuffer, const GLint *value)
+{
+ if(device && mState.stencilWritemask)
+ {
+ int x0(0), y0(0), width(0), height(0);
+ egl::Image* image = getScissoredImage(drawbuffer, x0, y0, width, height, true);
+
+ unsigned char stencil = value[0] < 0 ? 0 : static_cast<unsigned char>(value[0] & 0x000000FF);
+ image->clearStencilBuffer(stencil, static_cast<unsigned char>(mState.stencilWritemask), x0, y0, width, height);
+ }
+}
+
+void Context::clearDepthStencilBuffer(GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ if(device && (mState.depthMask || mState.stencilWritemask))
+ {
+ int x0(0), y0(0), width(0), height(0);
+ egl::Image* image = getScissoredImage(drawbuffer, x0, y0, width, height, true);
+
+ if(mState.stencilWritemask)
+ {
+ image->clearStencilBuffer(static_cast<unsigned char>(stencil & 0x000000FF), static_cast<unsigned char>(mState.stencilWritemask), x0, y0, width, height);
+ }
+
+ if(mState.depthMask)
+ {
+ image->clearDepthBuffer(clamp01(depth), x0, y0, width, height);
+ }
+ }
+}
+
void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
{
if(!mState.currentProgram)
diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index f7795e3..fe881c1 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -425,6 +425,7 @@
void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
void setColorMask(bool red, bool green, bool blue, bool alpha);
+ unsigned int getColorMask() const;
void setDepthMask(bool mask);
void setActiveSampler(unsigned int active);
@@ -579,6 +580,12 @@
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
void clear(GLbitfield mask);
+ void clearColorBuffer(GLint drawbuffer, const GLint *value);
+ void clearColorBuffer(GLint drawbuffer, const GLuint *value);
+ void clearColorBuffer(GLint drawbuffer, const GLfloat *value);
+ void clearDepthBuffer(GLint drawbuffer, const GLfloat *value);
+ void clearStencilBuffer(GLint drawbuffer, const GLint *value);
+ void clearDepthStencilBuffer(GLint drawbuffer, GLfloat depth, GLint stencil);
void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount = 1);
void drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount = 1);
void finish();
@@ -609,6 +616,8 @@
private:
virtual ~Context();
+ egl::Image *getScissoredImage(GLint drawbuffer, int &x0, int &y0, int &width, int &height, bool depthStencil);
+ void applyScissor(int width, int height);
bool applyRenderTarget();
void applyState(GLenum drawMode);
GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count, GLsizei instanceId);
diff --git a/src/OpenGL/libGLESv2/Device.cpp b/src/OpenGL/libGLESv2/Device.cpp
index 5eabab1..cb7ef48 100644
--- a/src/OpenGL/libGLESv2/Device.cpp
+++ b/src/OpenGL/libGLESv2/Device.cpp
@@ -157,17 +157,12 @@
delete context;
}
- void Device::clearColor(unsigned int color, unsigned int rgbaMask)
+ void Device::getScissoredRegion(egl::Image *sourceSurface, int &x0, int &y0, int& width, int& height) const
{
- if(!renderTarget)
- {
- return;
- }
-
- int x0 = 0;
- int y0 = 0;
- int width = renderTarget->getExternalWidth();
- int height = renderTarget->getExternalHeight();
+ x0 = 0;
+ y0 = 0;
+ width = sourceSurface->getExternalWidth();
+ height = sourceSurface->getExternalHeight();
if(scissorEnable) // Clamp against scissor rectangle
{
@@ -176,6 +171,17 @@
if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
}
+ }
+
+ void Device::clearColor(unsigned int color, unsigned int rgbaMask)
+ {
+ if(!renderTarget)
+ {
+ return;
+ }
+
+ int x0(0), y0(0), width(0), height(0);
+ getScissoredRegion(renderTarget, x0, y0, width, height);
renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
}
@@ -190,18 +196,8 @@
if(z > 1) z = 1;
if(z < 0) z = 0;
- int x0 = 0;
- int y0 = 0;
- int width = depthStencil->getExternalWidth();
- int height = depthStencil->getExternalHeight();
-
- if(scissorEnable) // Clamp against scissor rectangle
- {
- if(x0 < scissorRect.x0) x0 = scissorRect.x0;
- if(y0 < scissorRect.y0) y0 = scissorRect.y0;
- if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
- if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
- }
+ int x0(0), y0(0), width(0), height(0);
+ getScissoredRegion(depthStencil, x0, y0, width, height);
depthStencil->clearDepthBuffer(z, x0, y0, width, height);
}
@@ -213,18 +209,8 @@
return;
}
- int x0 = 0;
- int y0 = 0;
- int width = depthStencil->getExternalWidth();
- int height = depthStencil->getExternalHeight();
-
- if(scissorEnable) // Clamp against scissor rectangle
- {
- if(x0 < scissorRect.x0) x0 = scissorRect.x0;
- if(y0 < scissorRect.y0) y0 = scissorRect.y0;
- if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
- if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
- }
+ int x0(0), y0(0), width(0), height(0);
+ getScissoredRegion(depthStencil, x0, y0, width, height);
depthStencil->clearStencilBuffer(stencil, mask, x0, y0, width, height);
}
diff --git a/src/OpenGL/libGLESv2/Device.hpp b/src/OpenGL/libGLESv2/Device.hpp
index 26bc248..4cf1860 100644
--- a/src/OpenGL/libGLESv2/Device.hpp
+++ b/src/OpenGL/libGLESv2/Device.hpp
@@ -72,6 +72,8 @@
virtual bool stretchCube(egl::Image *sourceSurface, egl::Image *destSurface);
virtual void finish();
+ void getScissoredRegion(egl::Image *sourceSurface, int &x0, int &y0, int& width, int& height) const;
+
private:
sw::Context *const context;
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 56d825a..3d59a1d 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -2421,25 +2421,36 @@
TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = %p)",
buffer, drawbuffer, value);
- switch(buffer)
- {
- case GL_COLOR:
- if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
- {
- return error(GL_INVALID_VALUE);
- }
- break;
- case GL_STENCIL:
- if(drawbuffer != 0)
- {
- return error(GL_INVALID_VALUE);
- }
- break;
- default:
- return error(GL_INVALID_ENUM);
- }
+ es2::Context *context = es2::getContext();
- UNIMPLEMENTED();
+ if(context)
+ {
+ switch(buffer)
+ {
+ case GL_COLOR:
+ if(drawbuffer < 0 || drawbuffer >= es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ else
+ {
+ context->clearColorBuffer(drawbuffer, value);
+ }
+ break;
+ case GL_STENCIL:
+ if(drawbuffer != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ else
+ {
+ context->clearStencilBuffer(drawbuffer, value);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
@@ -2447,19 +2458,26 @@
TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = %p)",
buffer, drawbuffer, value);
- switch(buffer)
- {
- case GL_COLOR:
- if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
- {
- return error(GL_INVALID_VALUE);
- }
- break;
- default:
- return error(GL_INVALID_ENUM);
- }
+ es2::Context *context = es2::getContext();
- UNIMPLEMENTED();
+ if(context)
+ {
+ switch(buffer)
+ {
+ case GL_COLOR:
+ if(drawbuffer < 0 || drawbuffer >= es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ else
+ {
+ context->clearColorBuffer(drawbuffer, value);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
@@ -2467,25 +2485,36 @@
TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = %p)",
buffer, drawbuffer, value);
- switch(buffer)
- {
- case GL_COLOR:
- if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
- {
- return error(GL_INVALID_VALUE);
- }
- break;
- case GL_DEPTH:
- if(drawbuffer != 0)
- {
- return error(GL_INVALID_VALUE);
- }
- break;
- default:
- return error(GL_INVALID_ENUM);
- }
+ es2::Context *context = es2::getContext();
- UNIMPLEMENTED();
+ if(context)
+ {
+ switch(buffer)
+ {
+ case GL_COLOR:
+ if(drawbuffer < 0 || drawbuffer >= es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ else
+ {
+ context->clearColorBuffer(drawbuffer, value);
+ }
+ break;
+ case GL_DEPTH:
+ if(drawbuffer != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ else
+ {
+ context->clearDepthBuffer(drawbuffer, value);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
@@ -2493,19 +2522,26 @@
TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)",
buffer, drawbuffer, depth, stencil);
- switch(buffer)
- {
- case GL_DEPTH_STENCIL:
- if(drawbuffer != 0)
- {
- return error(GL_INVALID_VALUE);
- }
- break;
- default:
- return error(GL_INVALID_ENUM);
- }
+ es2::Context *context = es2::getContext();
- UNIMPLEMENTED();
+ if(context)
+ {
+ switch(buffer)
+ {
+ case GL_DEPTH_STENCIL:
+ if(drawbuffer != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ else
+ {
+ context->clearDepthStencilBuffer(drawbuffer, depth, stencil);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
GL_APICALL const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)