Commit 4ffc8188 by Alexis Hetu Committed by Alexis Hétu

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/3004Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent b72f8ee8
...@@ -703,6 +703,14 @@ void Context::setColorMask(bool red, bool green, bool blue, bool alpha) ...@@ -703,6 +703,14 @@ void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
} }
} }
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) void Context::setDepthMask(bool mask)
{ {
if(mState.depthMask != mask) if(mState.depthMask != mask)
...@@ -2530,6 +2538,34 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu ...@@ -2530,6 +2538,34 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
return true; 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 // Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle
bool Context::applyRenderTarget() bool Context::applyRenderTarget()
{ {
...@@ -2562,18 +2598,7 @@ bool Context::applyRenderTarget() ...@@ -2562,18 +2598,7 @@ bool Context::applyRenderTarget()
device->setViewport(viewport); device->setViewport(viewport);
if(mState.scissorTest) applyScissor(width, height);
{
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);
}
Program *program = getCurrentProgram(); Program *program = getCurrentProgram();
...@@ -3368,22 +3393,16 @@ void Context::clear(GLbitfield mask) ...@@ -3368,22 +3393,16 @@ void Context::clear(GLbitfield mask)
return; 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) if(mask & GL_COLOR_BUFFER_BIT)
{ {
unsigned int rgbaMask = (mState.colorMaskRed ? 0x1 : 0) | unsigned int rgbaMask = getColorMask();
(mState.colorMaskGreen ? 0x2 : 0) |
(mState.colorMaskBlue ? 0x4 : 0) |
(mState.colorMaskAlpha ? 0x8 : 0);
if(rgbaMask != 0) 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(color, rgbaMask);
} }
} }
...@@ -3392,6 +3411,7 @@ void Context::clear(GLbitfield mask) ...@@ -3392,6 +3411,7 @@ void Context::clear(GLbitfield mask)
{ {
if(mState.depthMask != 0) if(mState.depthMask != 0)
{ {
float depth = clamp01(mState.depthClearValue);
device->clearDepth(depth); device->clearDepth(depth);
} }
} }
...@@ -3400,11 +3420,103 @@ void Context::clear(GLbitfield mask) ...@@ -3400,11 +3420,103 @@ void Context::clear(GLbitfield mask)
{ {
if(mState.stencilWritemask != 0) if(mState.stencilWritemask != 0)
{ {
int stencil = mState.stencilClearValue & 0x000000FF;
device->clearStencil(stencil, mState.stencilWritemask); 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) void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
{ {
if(!mState.currentProgram) if(!mState.currentProgram)
......
...@@ -425,6 +425,7 @@ public: ...@@ -425,6 +425,7 @@ public:
void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
void setColorMask(bool red, bool green, bool blue, bool alpha); void setColorMask(bool red, bool green, bool blue, bool alpha);
unsigned int getColorMask() const;
void setDepthMask(bool mask); void setDepthMask(bool mask);
void setActiveSampler(unsigned int active); void setActiveSampler(unsigned int active);
...@@ -579,6 +580,12 @@ public: ...@@ -579,6 +580,12 @@ public:
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
void clear(GLbitfield mask); 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 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 drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount = 1);
void finish(); void finish();
...@@ -609,6 +616,8 @@ public: ...@@ -609,6 +616,8 @@ public:
private: private:
virtual ~Context(); 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(); bool applyRenderTarget();
void applyState(GLenum drawMode); void applyState(GLenum drawMode);
GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count, GLsizei instanceId); GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count, GLsizei instanceId);
......
...@@ -157,17 +157,12 @@ namespace es2 ...@@ -157,17 +157,12 @@ namespace es2
delete context; 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) x0 = 0;
{ y0 = 0;
return; width = sourceSurface->getExternalWidth();
} height = sourceSurface->getExternalHeight();
int x0 = 0;
int y0 = 0;
int width = renderTarget->getExternalWidth();
int height = renderTarget->getExternalHeight();
if(scissorEnable) // Clamp against scissor rectangle if(scissorEnable) // Clamp against scissor rectangle
{ {
...@@ -176,6 +171,17 @@ namespace es2 ...@@ -176,6 +171,17 @@ namespace es2
if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0; if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0; 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); renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
} }
...@@ -190,18 +196,8 @@ namespace es2 ...@@ -190,18 +196,8 @@ namespace es2
if(z > 1) z = 1; if(z > 1) z = 1;
if(z < 0) z = 0; if(z < 0) z = 0;
int x0 = 0; int x0(0), y0(0), width(0), height(0);
int y0 = 0; getScissoredRegion(depthStencil, x0, y0, width, height);
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;
}
depthStencil->clearDepthBuffer(z, x0, y0, width, height); depthStencil->clearDepthBuffer(z, x0, y0, width, height);
} }
...@@ -213,18 +209,8 @@ namespace es2 ...@@ -213,18 +209,8 @@ namespace es2
return; return;
} }
int x0 = 0; int x0(0), y0(0), width(0), height(0);
int y0 = 0; getScissoredRegion(depthStencil, x0, y0, width, height);
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;
}
depthStencil->clearStencilBuffer(stencil, mask, x0, y0, width, height); depthStencil->clearStencilBuffer(stencil, mask, x0, y0, width, height);
} }
......
...@@ -72,6 +72,8 @@ namespace es2 ...@@ -72,6 +72,8 @@ namespace es2
virtual bool stretchCube(egl::Image *sourceSurface, egl::Image *destSurface); virtual bool stretchCube(egl::Image *sourceSurface, egl::Image *destSurface);
virtual void finish(); virtual void finish();
void getScissoredRegion(egl::Image *sourceSurface, int &x0, int &y0, int& width, int& height) const;
private: private:
sw::Context *const context; sw::Context *const context;
......
...@@ -2421,25 +2421,36 @@ GL_APICALL void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, con ...@@ -2421,25 +2421,36 @@ GL_APICALL void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, con
TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = %p)", TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = %p)",
buffer, drawbuffer, value); buffer, drawbuffer, value);
switch(buffer) es2::Context *context = es2::getContext();
if(context)
{ {
case GL_COLOR: switch(buffer)
if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
{
return error(GL_INVALID_VALUE);
}
break;
case GL_STENCIL:
if(drawbuffer != 0)
{ {
return error(GL_INVALID_VALUE); 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);
} }
break;
default:
return error(GL_INVALID_ENUM);
} }
UNIMPLEMENTED();
} }
GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
...@@ -2447,19 +2458,26 @@ GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, co ...@@ -2447,19 +2458,26 @@ GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, co
TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = %p)", TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = %p)",
buffer, drawbuffer, value); buffer, drawbuffer, value);
switch(buffer) es2::Context *context = es2::getContext();
if(context)
{ {
case GL_COLOR: switch(buffer)
if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
{ {
return error(GL_INVALID_VALUE); 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);
} }
break;
default:
return error(GL_INVALID_ENUM);
} }
UNIMPLEMENTED();
} }
GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
...@@ -2467,25 +2485,36 @@ GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, con ...@@ -2467,25 +2485,36 @@ GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, con
TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = %p)", TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = %p)",
buffer, drawbuffer, value); buffer, drawbuffer, value);
switch(buffer) es2::Context *context = es2::getContext();
if(context)
{ {
case GL_COLOR: switch(buffer)
if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)
{
return error(GL_INVALID_VALUE);
}
break;
case GL_DEPTH:
if(drawbuffer != 0)
{ {
return error(GL_INVALID_VALUE); 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);
} }
break;
default:
return error(GL_INVALID_ENUM);
} }
UNIMPLEMENTED();
} }
GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
...@@ -2493,19 +2522,26 @@ GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLf ...@@ -2493,19 +2522,26 @@ GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLf
TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)", TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)",
buffer, drawbuffer, depth, stencil); buffer, drawbuffer, depth, stencil);
switch(buffer) es2::Context *context = es2::getContext();
if(context)
{ {
case GL_DEPTH_STENCIL: switch(buffer)
if(drawbuffer != 0)
{ {
return error(GL_INVALID_VALUE); 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);
} }
break;
default:
return error(GL_INVALID_ENUM);
} }
UNIMPLEMENTED();
} }
GL_APICALL const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index) GL_APICALL const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)
......
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