[Scummvm-git-logs] scummvm master -> 6a591146c8fc5605423f00f1db573f06245b8c8b
aquadran
noreply at scummvm.org
Thu Dec 9 20:11:00 UTC 2021
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
6a591146c8 TINYGL: Added stencil buffer implementation
Commit: 6a591146c8fc5605423f00f1db573f06245b8c8b
https://github.com/scummvm/scummvm/commit/6a591146c8fc5605423f00f1db573f06245b8c8b
Author: PaweÅ KoÅodziejski (aquadran at gmail.com)
Date: 2021-12-09T21:10:53+01:00
Commit Message:
TINYGL: Added stencil buffer implementation
Changed paths:
engines/grim/gfx_tinygl.cpp
engines/myst3/gfx_tinygl.cpp
engines/playground3d/gfx_tinygl.cpp
engines/stark/gfx/tinygl.cpp
engines/stark/gfx/tinyglactor.cpp
graphics/tinygl/Changelog
graphics/tinygl/api.cpp
graphics/tinygl/clear.cpp
graphics/tinygl/clip.cpp
graphics/tinygl/get.cpp
graphics/tinygl/gl.h
graphics/tinygl/init.cpp
graphics/tinygl/misc.cpp
graphics/tinygl/opinfo.h
graphics/tinygl/tinygl.h
graphics/tinygl/zblit.cpp
graphics/tinygl/zbuffer.cpp
graphics/tinygl/zbuffer.h
graphics/tinygl/zdirtyrect.cpp
graphics/tinygl/zdirtyrect.h
graphics/tinygl/zgl.h
graphics/tinygl/ztriangle.cpp
diff --git a/engines/grim/gfx_tinygl.cpp b/engines/grim/gfx_tinygl.cpp
index 8ddea296ca..61a5c758f3 100644
--- a/engines/grim/gfx_tinygl.cpp
+++ b/engines/grim/gfx_tinygl.cpp
@@ -85,7 +85,7 @@ void GfxTinyGL::setupScreen(int screenW, int screenH) {
_pixelFormat = g_system->getScreenFormat();
debug("INFO: TinyGL front buffer pixel format: %s", _pixelFormat.toString().c_str());
- TinyGL::createContext(screenW, screenH, _pixelFormat, 256, ConfMan.getBool("dirtyrects"));
+ TinyGL::createContext(screenW, screenH, _pixelFormat, 256, g_grim->getGameType() == GType_GRIM, ConfMan.getBool("dirtyrects"));
_storedDisplay = new Graphics::Surface;
_storedDisplay->create(_gameWidth, _gameHeight, _pixelFormat);
diff --git a/engines/myst3/gfx_tinygl.cpp b/engines/myst3/gfx_tinygl.cpp
index dfa6e51d6a..0cba042349 100644
--- a/engines/myst3/gfx_tinygl.cpp
+++ b/engines/myst3/gfx_tinygl.cpp
@@ -62,7 +62,7 @@ void TinyGLRenderer::init() {
computeScreenViewport();
- TinyGL::createContext(kOriginalWidth, kOriginalHeight, g_system->getScreenFormat(), 512, ConfMan.getBool("dirtyrects"));
+ TinyGL::createContext(kOriginalWidth, kOriginalHeight, g_system->getScreenFormat(), 512, false, ConfMan.getBool("dirtyrects"));
tglMatrixMode(TGL_PROJECTION);
tglLoadIdentity();
diff --git a/engines/playground3d/gfx_tinygl.cpp b/engines/playground3d/gfx_tinygl.cpp
index 002231dd17..42ae820f64 100644
--- a/engines/playground3d/gfx_tinygl.cpp
+++ b/engines/playground3d/gfx_tinygl.cpp
@@ -88,7 +88,7 @@ void TinyGLRenderer::init() {
computeScreenViewport();
- TinyGL::createContext(kOriginalWidth, kOriginalHeight, g_system->getScreenFormat(), 512, ConfMan.getBool("dirtyrects"));
+ TinyGL::createContext(kOriginalWidth, kOriginalHeight, g_system->getScreenFormat(), 512, true, ConfMan.getBool("dirtyrects"));
tglMatrixMode(TGL_PROJECTION);
tglLoadIdentity();
diff --git a/engines/stark/gfx/tinygl.cpp b/engines/stark/gfx/tinygl.cpp
index 242ed794e4..d854a5d3dd 100644
--- a/engines/stark/gfx/tinygl.cpp
+++ b/engines/stark/gfx/tinygl.cpp
@@ -51,7 +51,7 @@ TinyGLDriver::~TinyGLDriver() {
void TinyGLDriver::init() {
computeScreenViewport();
- TinyGL::createContext(kOriginalWidth, kOriginalHeight, g_system->getScreenFormat(), 512, ConfMan.getBool("dirtyrects"));
+ TinyGL::createContext(kOriginalWidth, kOriginalHeight, g_system->getScreenFormat(), 512, true, ConfMan.getBool("dirtyrects"));
tglMatrixMode(TGL_PROJECTION);
tglLoadIdentity();
@@ -89,7 +89,7 @@ void TinyGLDriver::setViewport(const Common::Rect &rect) {
}
void TinyGLDriver::clearScreen() {
- tglClear(TGL_COLOR_BUFFER_BIT | TGL_DEPTH_BUFFER_BIT);
+ tglClear(TGL_COLOR_BUFFER_BIT | TGL_DEPTH_BUFFER_BIT | TGL_STENCIL_BUFFER_BIT);
}
void TinyGLDriver::flipBuffer() {
@@ -159,8 +159,8 @@ void TinyGLDriver::set3DMode() {
// Stencil test are only used in rendering shadows
// They are manually enabled and disabled there
- //tglStencilFunc(TGL_EQUAL, 0, 0xFF);
- //tglStencilOp(TGL_KEEP, TGL_KEEP, TGL_INCR);
+ tglStencilFunc(TGL_EQUAL, 0, 0xFF);
+ tglStencilOp(TGL_KEEP, TGL_KEEP, TGL_INCR);
}
bool TinyGLDriver::computeLightsEnabled() {
diff --git a/engines/stark/gfx/tinyglactor.cpp b/engines/stark/gfx/tinyglactor.cpp
index 994c31d1e8..82763035b2 100644
--- a/engines/stark/gfx/tinyglactor.cpp
+++ b/engines/stark/gfx/tinyglactor.cpp
@@ -256,7 +256,7 @@ void TinyGLActorRenderer::render(const Math::Vector3d &position, float direction
if (drawShadow) {
tglEnable(TGL_BLEND);
- //tglEnable(TGL_STENCIL_TEST);
+ tglEnable(TGL_STENCIL_TEST);
tglDisable(TGL_TEXTURE_2D);
tglColor4f(0.0f, 0.0f, 0.0f, 0.5f);
@@ -273,7 +273,7 @@ void TinyGLActorRenderer::render(const Math::Vector3d &position, float direction
tglEnable(TGL_TEXTURE_2D);
tglDisable(TGL_BLEND);
- //tglDisable(TGL_STENCIL_TEST);
+ tglDisable(TGL_STENCIL_TEST);
}
}
diff --git a/graphics/tinygl/Changelog b/graphics/tinygl/Changelog
index c39c8fe895..42d87ebf81 100644
--- a/graphics/tinygl/Changelog
+++ b/graphics/tinygl/Changelog
@@ -16,11 +16,11 @@ The changes made from the original version of TinyGL 0.4 are:
* Added additional functions missing, like glColor4ub. (To make the code similar with the GL-code we use)
* Added simplistic glColorMask implementation, on/off.
* Applied some C++-isms:
- * "for(int i = 0;" instead of "int i; for (i = 0;",
- * struct structName instead of typedef struct {} structName;
- * pass-by-const-reference instead of by-value when possible
+ - "for(int i = 0;" instead of "int i; for (i = 0;",
+ - struct structName instead of typedef struct {} structName;
+ - pass-by-const-reference instead of by-value when possible
* Changed the math-functions to use const-pointers if possible.
-* Reformatted the source to use the same code-formatting conventions as the rest of ResidualVM
+* Reformatted the source to use the same code-formatting conventions as the rest of ScummVM
(indentation-wise, not variable-naming wise)
* Refactored all the maths code in a C++ fashion, removed some unused functions.
* Heavily refactored the triangle and line drawing routines
@@ -31,6 +31,7 @@ The changes made from the original version of TinyGL 0.4 are:
* Added an API that enables the user to perform color and z buffer blitting.
* Implemented a system that enables to defer draw calls.
* Implemented dirty rectangle system that prevents redrawing of unchanged region of the screen.
-* Added implementation of tglDrawElements
+* Added implementation of tglDrawElements.
+* Added stencil buffer implementation.
For more information refer to log changes in github: https://github.com/scummvm/scummvm
diff --git a/graphics/tinygl/api.cpp b/graphics/tinygl/api.cpp
index 019adf5981..fcda2d32a1 100644
--- a/graphics/tinygl/api.cpp
+++ b/graphics/tinygl/api.cpp
@@ -199,6 +199,15 @@ void tglDepthMask(int enableWrite) {
c->gl_add_op(p);
}
+void tglStencilMask(TGLuint mask) {
+ TinyGL::GLContext *c = TinyGL::gl_get_context();
+ TinyGL::GLParam p[2];
+ p[0].op = TinyGL::OP_StencilMask;
+ p[1].i = mask;
+
+ c->gl_add_op(p);
+}
+
void tglBlendFunc(TGLenum sfactor, TGLenum dfactor) {
TinyGL::GLContext *c = TinyGL::gl_get_context();
TinyGL::GLParam p[3];
@@ -230,6 +239,28 @@ void tglDepthFunc(TGLenum func) {
c->gl_add_op(p);
}
+void tglStencilFunc(TGLenum func, TGLint ref, TGLuint mask) {
+ TinyGL::GLContext *c = TinyGL::gl_get_context();
+ TinyGL::GLParam p[4];
+ p[0].op = TinyGL::OP_StencilFunc;
+ p[1].i = func;
+ p[2].i = ref;
+ p[3].i = mask;
+
+ c->gl_add_op(p);
+}
+
+void tglStencilOp(TGLenum sfail, TGLenum dpfail, TGLenum dppass) {
+ TinyGL::GLContext *c = TinyGL::gl_get_context();
+ TinyGL::GLParam p[4];
+ p[0].op = TinyGL::OP_StencilOp;
+ p[1].i = sfail;
+ p[2].i = dpfail;
+ p[3].i = dppass;
+
+ c->gl_add_op(p);
+}
+
void tglPolygonMode(int face, int mode) {
TinyGL::GLContext *c = TinyGL::gl_get_context();
TinyGL::GLParam p[3];
@@ -569,6 +600,16 @@ void tglClearDepth(double depth) {
c->gl_add_op(p);
}
+void tglClearStencil(TGLint s) {
+ TinyGL::GLContext *c = TinyGL::gl_get_context();
+ TinyGL::GLParam p[2];
+
+ p[0].op = TinyGL::OP_ClearStencil;
+ p[1].i = s;
+
+ c->gl_add_op(p);
+}
+
// textures
void tglTexImage2D(int target, int level, int components, int width, int height, int border, int format, int type, void *pixels) {
diff --git a/graphics/tinygl/clear.cpp b/graphics/tinygl/clear.cpp
index 3b91852ed9..7751d8992a 100644
--- a/graphics/tinygl/clear.cpp
+++ b/graphics/tinygl/clear.cpp
@@ -39,14 +39,21 @@ void GLContext::glopClearDepth(GLParam *p) {
clear_depth = p[1].f;
}
+void GLContext::glopClearStencil(GLParam *p) {
+ clear_stencil = p[1].i & 0xFF;
+}
+
void GLContext::glopClear(GLParam *p) {
int mask = p[1].i;
int z = (int)(clear_depth * ((1 << ZB_Z_BITS) - 1));
int r = (int)(clear_color.X * 255);
int g = (int)(clear_color.Y * 255);
int b = (int)(clear_color.Z * 255);
+ int s = (int)(clear_stencil);
- issueDrawCall(new ClearBufferDrawCall(mask & TGL_DEPTH_BUFFER_BIT, z, mask & TGL_COLOR_BUFFER_BIT, r, g, b));
+ issueDrawCall(new ClearBufferDrawCall(mask & TGL_DEPTH_BUFFER_BIT, z,
+ mask & TGL_COLOR_BUFFER_BIT, r, g, b,
+ mask & TGL_STENCIL_BUFFER_BIT, s));
}
} // end of namespace TinyGL
diff --git a/graphics/tinygl/clip.cpp b/graphics/tinygl/clip.cpp
index 1db02fc7cf..e3e7dd9ba6 100644
--- a/graphics/tinygl/clip.cpp
+++ b/graphics/tinygl/clip.cpp
@@ -141,7 +141,7 @@ void GLContext::gl_draw_line(GLVertex *p1, GLVertex *p2) {
if (render_mode == TGL_SELECT) {
gl_add_select1(p1->zp.z, p2->zp.z, p2->zp.z);
} else {
- if (depth_test)
+ if (depth_test_enabled)
fb->fillLineZ(&p1->zp, &p2->zp);
else
fb->fillLine(&p1->zp, &p2->zp);
@@ -171,7 +171,7 @@ void GLContext::gl_draw_line(GLVertex *p1, GLVertex *p2) {
gl_transform_to_viewport(&q1);
gl_transform_to_viewport(&q2);
- if (depth_test)
+ if (depth_test_enabled)
fb->fillLineZ(&q1.zp, &q2.zp);
else
fb->fillLine(&q1.zp, &q2.zp);
@@ -425,7 +425,7 @@ void GLContext::gl_draw_triangle_fill(GLContext *c, GLVertex *p0, GLVertex *p1,
// Render a clipped triangle in line mode
void GLContext::gl_draw_triangle_line(GLContext *c, GLVertex *p0, GLVertex *p1, GLVertex *p2) {
- if (c->depth_test) {
+ if (c->depth_test_enabled) {
if (p0->edge_flag)
c->fb->fillLineZ(&p0->zp, &p1->zp);
if (p1->edge_flag)
diff --git a/graphics/tinygl/get.cpp b/graphics/tinygl/get.cpp
index 6fd3c24c07..38222fd3c5 100644
--- a/graphics/tinygl/get.cpp
+++ b/graphics/tinygl/get.cpp
@@ -62,6 +62,12 @@ void tglGetIntegerv(int pname, int *params) {
case TGL_ALPHA_TEST:
*params = c->alpha_test_enabled;
break;
+ case TGL_DEPTH_TEST:
+ *params = c->depth_test_enabled;
+ break;
+ case TGL_STENCIL_TEST:
+ *params = c->stencil_test_enabled;
+ break;
default:
error("tglGet: option not implemented");
break;
diff --git a/graphics/tinygl/gl.h b/graphics/tinygl/gl.h
index 0c6214fc8f..f1db34b9cd 100644
--- a/graphics/tinygl/gl.h
+++ b/graphics/tinygl/gl.h
@@ -328,6 +328,8 @@ enum {
TGL_REPLACE = 0x1E01,
TGL_INCR = 0x1E02,
TGL_DECR = 0x1E03,
+ TGL_INCR_WRAP = 0x8507,
+ TGL_DECR_WRAP = 0x8508,
// Buffers, Pixel Drawing/Reading
TGL_NONE = 0,
@@ -790,6 +792,12 @@ void tglCallList(unsigned int list);
void tglClear(int mask);
void tglClearColor(float r, float g, float b, float a);
void tglClearDepth(double depth);
+void tglClearStencil(TGLint s);
+
+// stencil buffer
+void tglStencilFunc(TGLenum func, TGLint ref, TGLuint mask);
+void tglStencilOp(TGLenum sfail, TGLenum dpfail, TGLenum dppass);
+void tglStencilMask(TGLuint mask);
// selection
int tglRenderMode(int mode);
diff --git a/graphics/tinygl/init.cpp b/graphics/tinygl/init.cpp
index 5a92844634..573b7f7900 100644
--- a/graphics/tinygl/init.cpp
+++ b/graphics/tinygl/init.cpp
@@ -55,19 +55,18 @@ void GLContext::endSharedState() {
gl_free(s->texture_hash_table);
}
-void createContext(int screenW, int screenH, Graphics::PixelFormat pixelFormat, int textureSize, bool dirtyRectsEnable) {
+void createContext(int screenW, int screenH, Graphics::PixelFormat pixelFormat, int textureSize, bool enableStencilBuffer, bool dirtyRectsEnable) {
assert(gl_ctx == nullptr);
- GLContext *c = new GLContext();
- gl_ctx = c;
- c->init(screenW, screenH, pixelFormat, textureSize, dirtyRectsEnable);
+ gl_ctx = new GLContext();
+ gl_ctx->init(screenW, screenH, pixelFormat, textureSize, enableStencilBuffer, dirtyRectsEnable);
}
-void GLContext::init(int screenW, int screenH, Graphics::PixelFormat pixelFormat, int textureSize, bool dirtyRectsEnable) {
+void GLContext::init(int screenW, int screenH, Graphics::PixelFormat pixelFormat, int textureSize, bool enableStencilBuffer, bool dirtyRectsEnable) {
GLViewport *v;
_enableDirtyRectangles = dirtyRectsEnable;
- fb = new TinyGL::FrameBuffer(screenW, screenH, pixelFormat);
+ fb = new TinyGL::FrameBuffer(screenW, screenH, pixelFormat, enableStencilBuffer);
renderRect = Common::Rect(0, 0, screenW, screenH);
if ((textureSize & (textureSize - 1)))
@@ -169,20 +168,37 @@ void GLContext::init(int screenW, int screenH, Graphics::PixelFormat pixelFormat
// clear
clear_color = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
clear_depth = 1.0f;
+ clear_stencil = 0;
// selection
render_mode = TGL_RENDER;
- select_buffer = NULL;
+ select_buffer = nullptr;
name_stack_size = 0;
// blending
blending_enabled = false;
+ source_blending_factor = TGL_ONE;
+ destination_blending_factor = TGL_ZERO;
// alpha test
alpha_test_enabled = false;
+ alpha_test_func = TGL_ALWAYS;
+ alpha_test_ref_val = 0;
// depth test
- depth_test = false;
+ depth_test_enabled = false;
+ depth_func = TGL_LESS;
+ depth_write_mask = true;
+
+ // stencil
+ stencil_test_enabled = false;
+ stencil_test_func = TGL_ALWAYS;
+ stencil_ref_val = 0;
+ stencil_mask = 0xff;
+ stencil_write_mask = 0xff;
+ stencil_sfail = TGL_KEEP;
+ stencil_dpfail = TGL_KEEP;
+ stencil_dppass = TGL_KEEP;
// matrix
matrix_mode = 0;
@@ -203,12 +219,6 @@ void GLContext::init(int screenW, int screenH, Graphics::PixelFormat pixelFormat
tglMatrixMode(TGL_MODELVIEW);
tglLoadIdentity();
- tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
-
- tglAlphaFunc(TGL_ALWAYS, 0.f);
-
- tglDepthFunc(TGL_LESS);
-
matrix_model_projection_updated = 1;
// opengl 1.1 arrays
@@ -223,10 +233,10 @@ void GLContext::init(int screenW, int screenH, Graphics::PixelFormat pixelFormat
shadow_mode = 0;
// clear the resize callback function pointer
- gl_resize_viewport = NULL;
+ gl_resize_viewport = nullptr;
// specular buffer
- specbuf_first = NULL;
+ specbuf_first = nullptr;
specbuf_used_counter = 0;
specbuf_num_buffers = 0;
@@ -237,7 +247,6 @@ void GLContext::init(int screenW, int screenH, Graphics::PixelFormat pixelFormat
_currentAllocatorIndex = 0;
_drawCallAllocator[0].initialize(kDrawCallMemory);
_drawCallAllocator[1].initialize(kDrawCallMemory);
- _enableDirtyRectangles = true;
_debugRectsEnabled = false;
TinyGL::Internal::tglBlitResetScissorRect();
diff --git a/graphics/tinygl/misc.cpp b/graphics/tinygl/misc.cpp
index fca6758b55..fa27aa5007 100644
--- a/graphics/tinygl/misc.cpp
+++ b/graphics/tinygl/misc.cpp
@@ -86,11 +86,14 @@ void GLContext::glopEnableDisable(GLParam *p) {
normalize_enabled = v;
break;
case TGL_DEPTH_TEST:
- depth_test = v;
+ depth_test_enabled = v;
break;
case TGL_ALPHA_TEST:
alpha_test_enabled = v;
break;
+ case TGL_STENCIL_TEST:
+ stencil_test_enabled = v;
+ break;
case TGL_BLEND:
blending_enabled = v;
break;
@@ -148,6 +151,27 @@ void GLContext::glopDepthFunc(GLParam *p) {
depth_func = p[1].i;
}
+void GLContext::glopStencilFunc(GLParam *p) {
+ TGLenum func = p[1].i;
+ TGLint ref = p[2].i;
+ TGLuint mask = p[3].i;
+ if (func < TGL_NEVER || func > TGL_ALWAYS)
+ return;
+ if (ref < 0)
+ ref = 0;
+ else if (ref > 255)
+ ref = 255;
+ stencil_test_func = func;
+ stencil_ref_val = ref;
+ stencil_mask = mask;
+}
+
+void GLContext::glopStencilOp(GLParam *p) {
+ stencil_sfail = p[1].i;
+ stencil_dpfail = p[2].i;
+ stencil_dppass = p[3].i;
+}
+
void GLContext::glopShadeModel(GLParam *p) {
int code = p[1].i;
current_shade_model = code;
@@ -197,7 +221,11 @@ void GLContext::glopColorMask(GLParam *p) {
}
void GLContext::glopDepthMask(GLParam *p) {
- depth_write = p[1].i;
+ depth_write_mask = p[1].i;
+}
+
+void GLContext::glopStencilMask(TinyGL::GLParam *p) {
+ stencil_write_mask = p[1].i;
}
} // end of namespace TinyGL
diff --git a/graphics/tinygl/opinfo.h b/graphics/tinygl/opinfo.h
index 137b5e6732..424f44a981 100644
--- a/graphics/tinygl/opinfo.h
+++ b/graphics/tinygl/opinfo.h
@@ -60,6 +60,7 @@ ADD_OP(LightModel, 5, "%C %f %f %f %f")
ADD_OP(Clear, 1, "%d")
ADD_OP(ClearColor, 4, "%f %f %f %f")
ADD_OP(ClearDepth, 1, "%f")
+ADD_OP(ClearStencil, 1, "%d")
ADD_OP(InitNames, 0, "")
ADD_OP(PushName, 1, "%d")
@@ -78,9 +79,12 @@ ADD_OP(FrontFace, 1, "%C")
ADD_OP(PolygonMode, 2, "%C %C")
ADD_OP(ColorMask, 1, "%08x")
ADD_OP(DepthMask, 1, "%d")
+ADD_OP(StencilMask, 1, "%d")
ADD_OP(BlendFunc, 2, "%d %d")
ADD_OP(AlphaFunc, 2, "%d %f")
ADD_OP(DepthFunc, 1, "%d")
+ADD_OP(StencilFunc, 3, "%C %d %d")
+ADD_OP(StencilOp, 3, "%C %C %C")
ADD_OP(CallList, 1, "%d")
ADD_OP(Hint, 2, "%C %C")
diff --git a/graphics/tinygl/tinygl.h b/graphics/tinygl/tinygl.h
index b4103c883f..c22010fd7a 100644
--- a/graphics/tinygl/tinygl.h
+++ b/graphics/tinygl/tinygl.h
@@ -30,7 +30,7 @@
namespace TinyGL {
-void createContext(int screenW, int screenH, Graphics::PixelFormat pixelFormat, int textureSize, bool dirtyRectsEnable = true);
+void createContext(int screenW, int screenH, Graphics::PixelFormat pixelFormat, int textureSize, bool enableStencilBuffer, bool dirtyRectsEnable = true);
void destroyContext();
void presentBuffer();
void getSurfaceRef(Graphics::Surface &surface);
diff --git a/graphics/tinygl/zblit.cpp b/graphics/tinygl/zblit.cpp
index d29646679a..30d6fe99a7 100644
--- a/graphics/tinygl/zblit.cpp
+++ b/graphics/tinygl/zblit.cpp
@@ -200,7 +200,7 @@ public:
int fbWidth = c->fb->getPixelBufferWidth();
Graphics::PixelBuffer srcBuf(_surface.format, (byte *)const_cast<void *>(_surface.getPixels())); // Blit image buffer
- Graphics::PixelBuffer dstBuf(_surface.format, (byte *)c->fb->getZBuffer()); // TinyGL z buffer
+ Graphics::PixelBuffer dstBuf(_surface.format, (byte *)const_cast<uint *>(c->fb->getZBuffer())); // TinyGL z buffer
srcBuf.shiftBy(srcY * _surface.w);
diff --git a/graphics/tinygl/zbuffer.cpp b/graphics/tinygl/zbuffer.cpp
index 55fca6688a..83ad77037b 100644
--- a/graphics/tinygl/zbuffer.cpp
+++ b/graphics/tinygl/zbuffer.cpp
@@ -80,17 +80,20 @@ static void memset_l(void *adr, int val, int count) {
*p++ = val;
}
-FrameBuffer::FrameBuffer(int width, int height, const Graphics::PixelFormat &format) {
+FrameBuffer::FrameBuffer(int width, int height, const Graphics::PixelFormat &format, bool enableStencilBuffer) {
_pbufWidth = width;
_pbufHeight = height;
_pbufFormat = format;
_pbufBpp = _pbufFormat.bytesPerPixel;
_pbufPitch = (_pbufWidth * _pbufBpp + 3) & ~3;
- _offscreenBuffer.zbuf = _zbuf = (uint *)gl_zalloc(_pbufWidth * _pbufHeight * sizeof(uint));
-
_pbuf.set(_pbufFormat, new byte[_pbufHeight * _pbufPitch]);
+ _zbuf = (uint *)gl_zalloc(_pbufWidth * _pbufHeight * sizeof(uint));
+ if (enableStencilBuffer)
+ _sbuf = (byte *)gl_zalloc(_pbufWidth * _pbufHeight * sizeof(byte));
+
_offscreenBuffer.pbuf = _pbuf.getRawBuffer();
+ _offscreenBuffer.zbuf = _zbuf;
_currentTexture = nullptr;
}
@@ -98,12 +101,14 @@ FrameBuffer::FrameBuffer(int width, int height, const Graphics::PixelFormat &for
FrameBuffer::~FrameBuffer() {
_pbuf.free();
gl_free(_zbuf);
+ if (_sbuf)
+ gl_free(_sbuf);
}
Buffer *FrameBuffer::genOffscreenBuffer() {
Buffer *buf = (Buffer *)gl_malloc(sizeof(Buffer));
- buf->pbuf = (byte *)gl_malloc(_pbufHeight * _pbufPitch);
- buf->zbuf = (unsigned int *)gl_malloc(_pbufWidth * _pbufHeight * sizeof(uint));
+ buf->pbuf = (byte *)gl_zalloc(_pbufHeight * _pbufPitch);
+ buf->zbuf = (uint *)gl_zalloc(_pbufWidth * _pbufHeight * sizeof(uint));
return buf;
}
@@ -113,7 +118,8 @@ void FrameBuffer::delOffscreenBuffer(Buffer *buf) {
gl_free(buf);
}
-void FrameBuffer::clear(int clearZ, int z, int clearColor, int r, int g, int b) {
+void FrameBuffer::clear(int clearZ, int z, int clearColor, int r, int g, int b,
+ bool clearStencil, int stencilValue) {
if (clearZ) {
const uint8 *zc = (const uint8 *)&z;
unsigned int i;
@@ -149,9 +155,13 @@ void FrameBuffer::clear(int clearZ, int z, int clearColor, int r, int g, int b)
}
}
}
+ if (_sbuf && clearStencil) {
+ memset(_sbuf, stencilValue, _pbufWidth * _pbufHeight);
+ }
}
-void FrameBuffer::clearRegion(int x, int y, int w, int h, int clearZ, int z, int clearColor, int r, int g, int b) {
+void FrameBuffer::clearRegion(int x, int y, int w, int h, bool clearZ, int z,
+ bool clearColor, int r, int g, int b, bool clearStencil, int stencilValue) {
if (clearZ) {
int height = h;
unsigned int *zbuf = _zbuf + (y * _pbufWidth);
@@ -202,6 +212,13 @@ void FrameBuffer::clearRegion(int x, int y, int w, int h, int clearZ, int z, int
}
}
}
+ if (_sbuf && clearStencil) {
+ byte *pp = _sbuf + y * _pbufWidth + x;
+ for (int i = y; i < y + h; i++) {
+ memset(pp, stencilValue, w);
+ pp += _pbufWidth;
+ }
+ }
}
inline static void blitPixel(uint8 offset, unsigned int *from_z, unsigned int *to_z, unsigned int z_length, byte *from_color, byte *to_color, unsigned int color_length) {
diff --git a/graphics/tinygl/zbuffer.h b/graphics/tinygl/zbuffer.h
index c2dd9cc63c..370d05947a 100644
--- a/graphics/tinygl/zbuffer.h
+++ b/graphics/tinygl/zbuffer.h
@@ -78,7 +78,7 @@ static const int DRAW_SHADOW = 4;
struct Buffer {
byte *pbuf;
- unsigned int *zbuf;
+ uint *zbuf;
bool used;
};
@@ -103,7 +103,7 @@ struct ZBufferPoint {
};
struct FrameBuffer {
- FrameBuffer(int xsize, int ysize, const Graphics::PixelFormat &format);
+ FrameBuffer(int width, int height, const Graphics::PixelFormat &format, bool enableStencilBuffer);
~FrameBuffer();
Graphics::PixelFormat getPixelFormat() {
@@ -212,6 +212,72 @@ private:
return false;
}
+ FORCEINLINE bool stencilTest(byte sSrc) {
+ switch (_stencilTestFunc) {
+ case TGL_NEVER:
+ break;
+ case TGL_LESS:
+ if ((_stencilRefVal & _stencilMask) < (sSrc & _stencilMask))
+ return true;
+ break;
+ case TGL_LEQUAL:
+ if ((_stencilRefVal & _stencilMask) <= (sSrc & _stencilMask))
+ return true;
+ break;
+ case TGL_GREATER:
+ if ((_stencilRefVal & _stencilMask) > (sSrc & _stencilMask))
+ return true;
+ break;
+ case TGL_GEQUAL:
+ if ((_stencilRefVal & _stencilMask) >= (sSrc & _stencilMask))
+ return true;
+ break;
+ case TGL_EQUAL:
+ if ((_stencilRefVal & _stencilMask) == (sSrc & _stencilMask))
+ return true;
+ break;
+ case TGL_NOTEQUAL:
+ if ((_stencilRefVal & _stencilMask) != (sSrc & _stencilMask))
+ return true;
+ break;
+ case TGL_ALWAYS:
+ return true;
+ }
+ return false;
+ }
+
+ FORCEINLINE void stencilOp(bool stencilTestResult, bool depthTestResult, byte *sDst) {
+ int op = !stencilTestResult ? _stencilSfail : !depthTestResult ? _stencilDpfail : _stencilDppass;
+ byte value = *sDst;
+ switch (op) {
+ case TGL_KEEP:
+ return;
+ case TGL_ZERO:
+ value = 0;
+ break;
+ case TGL_REPLACE:
+ value = _stencilRefVal;
+ break;
+ case TGL_INCR:
+ if (value < 255)
+ value++;
+ break;
+ case TGL_INCR_WRAP:
+ value++;
+ break;
+ case TGL_DECR:
+ if (value > 0)
+ value--;
+ break;
+ case TGL_DECR_WRAP:
+ value--;
+ break;
+ case TGL_INVERT:
+ value = ~value;
+ }
+ *sDst = value & _stencilWriteMask;
+ }
+
template <bool kEnableAlphaTest, bool kBlendingEnabled>
FORCEINLINE void writePixel(int pixel, int value) {
writePixel<kEnableAlphaTest, kBlendingEnabled, false>(pixel, value, 0);
@@ -240,25 +306,25 @@ private:
}
}
- template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
- FORCEINLINE void putPixelFlat(FrameBuffer *buffer, int buf, unsigned int *pz, int _a,
+ template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending, bool kStencilEnabled>
+ FORCEINLINE void putPixelFlat(FrameBuffer *buffer, int buf, unsigned int *pz, byte *ps, int _a,
int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a, int &dzdx);
- template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
- FORCEINLINE void putPixelSmooth(FrameBuffer *buffer, int buf, unsigned int *pz, int _a,
+ template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending, bool kStencilEnabled>
+ FORCEINLINE void putPixelSmooth(FrameBuffer *buffer, int buf, unsigned int *pz, byte *ps, int _a,
int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
int &dzdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx);
- template <bool kDepthWrite, bool kEnableScissor>
- FORCEINLINE void putPixelDepth(FrameBuffer *buffer, int buf, unsigned int *pz, int _a, int x, int y, unsigned int &z, int &dzdx);
+ template <bool kDepthWrite, bool kEnableScissor, bool kStencilEnabled>
+ FORCEINLINE void putPixelDepth(FrameBuffer *buffer, int buf, unsigned int *pz, byte *ps, int _a, int x, int y, unsigned int &z, int &dzdx);
template <bool kDepthWrite, bool kAlphaTestEnabled, bool kEnableScissor, bool kBlendingEnabled>
FORCEINLINE void putPixelShadow(FrameBuffer *buffer, int buf, unsigned int *pz, int _a, int x, int y, unsigned int &z,
unsigned int &r, unsigned int &g, unsigned int &b, int &dzdx, unsigned char *pm);
- template <bool kDepthWrite, bool kLightsMode, bool kSmoothMode, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
+ template <bool kDepthWrite, bool kLightsMode, bool kSmoothMode, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending, bool kStencilEnabled>
FORCEINLINE void putPixelTextureMappingPerspective(FrameBuffer *buffer, int buf, const Graphics::TexelBuffer *texture,
- unsigned int wrap_s, unsigned int wrap_t, unsigned int *pz, int _a,
+ unsigned int wrap_s, unsigned int wrap_t, unsigned int *pz, byte *ps, int _a,
int x, int y, unsigned int &z, int &t, int &s,
unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
int &dzdx, int &dsdx, int &dtdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx);
@@ -420,8 +486,10 @@ private:
public:
- void clear(int clear_z, int z, int clear_color, int r, int g, int b);
- void clearRegion(int x, int y, int w, int h,int clear_z, int z, int clear_color, int r, int g, int b);
+ void clear(int clear_z, int z, int clear_color, int r, int g, int b,
+ bool clearStencil, int stencilValue);
+ void clearRegion(int x, int y, int w, int h, bool clearZ, int z,
+ bool clearColor, int r, int g, int b, bool clearStencil, int stencilValue);
FORCEINLINE void setScissorRectangle(const Common::Rect &rect) {
_clipRectangle = rect;
@@ -472,6 +540,26 @@ public:
_depthWrite = enable;
}
+ FORCEINLINE void enableStencilTest(bool enable) {
+ _stencilTestEnabled = enable;
+ }
+
+ FORCEINLINE void setStencilWriteMask(uint stencilWriteMask) {
+ _stencilWriteMask = stencilWriteMask;
+ }
+
+ FORCEINLINE void setStencilTestFunc(int stencilFunc, int stencilValue, uint stencilMask) {
+ _stencilTestFunc = stencilFunc;
+ _stencilRefVal = stencilValue;
+ _stencilMask = stencilMask;
+ }
+
+ FORCEINLINE void setStencilOp(int stencilSfail, int stencilDpfail, int stencilDppass) {
+ _stencilSfail = stencilSfail;
+ _stencilDpfail = stencilDpfail;
+ _stencilDppass = stencilDppass;
+ }
+
FORCEINLINE void setOffsetStates(int offsetStates) {
_offsetStates = offsetStates;
}
@@ -508,7 +596,10 @@ private:
void selectOffscreenBuffer(Buffer *buffer);
void clearOffscreenBuffer(Buffer *buffer);
- template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool enableAlphaTest, bool kEnableScissor, bool enableBlending>
+ template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool enableAlphaTest, bool kEnableScissor, bool kBlendingEnabled, bool kStencilEnabled>
+ void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
+
+ template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool enableAlphaTest, bool kEnableScissor, bool kBlendingEnabled>
void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite, bool enableAlphaTest, bool kEnableScissor>
@@ -560,9 +651,6 @@ private:
FORCEINLINE void drawLine(const ZBufferPoint *p1, const ZBufferPoint *p2);
Buffer _offscreenBuffer;
-
- unsigned int *_zbuf;
-
Graphics::PixelBuffer _pbuf;
int _pbufWidth;
int _pbufHeight;
@@ -570,6 +658,10 @@ private:
Graphics::PixelFormat _pbufFormat;
int _pbufBpp;
+ uint *_zbuf;
+ byte *_sbuf;
+
+ bool _enableStencil;
int _textureSize;
int _textureSizeMask;
@@ -590,6 +682,14 @@ private:
int _alphaTestRefVal;
bool _depthTestEnabled;
bool _depthWrite;
+ bool _stencilTestEnabled;
+ int _stencilTestFunc;
+ int _stencilRefVal;
+ uint _stencilMask;
+ uint _stencilWriteMask;
+ int _stencilSfail;
+ int _stencilDpfail;
+ int _stencilDppass;
int _depthFunc;
int _offsetStates;
float _offsetFactor;
diff --git a/graphics/tinygl/zdirtyrect.cpp b/graphics/tinygl/zdirtyrect.cpp
index b22f7814ca..7bf80e9d2c 100644
--- a/graphics/tinygl/zdirtyrect.cpp
+++ b/graphics/tinygl/zdirtyrect.cpp
@@ -423,21 +423,36 @@ void RasterizationDrawCall::execute(bool restoreState) const {
RasterizationDrawCall::RasterizationState RasterizationDrawCall::captureState() const {
RasterizationState state;
GLContext *c = gl_get_context();
- state.alphaTest = c->alpha_test_enabled;
+ state.enableBlending = c->blending_enabled;
state.sfactor = c->source_blending_factor;
state.dfactor = c->destination_blending_factor;
- state.enableBlending = c->blending_enabled;
+ state.alphaTestEnabled = c->alpha_test_enabled;
state.alphaFunc = c->alpha_test_func;
state.alphaRefValue = c->alpha_test_ref_val;
+ state.depthTestEnabled = c->depth_test_enabled;
+ state.depthFunction = c->depth_func;
+ state.depthWriteMask = c->depth_write_mask;
+ state.stencilTestEnabled = c->stencil_test_enabled;
+ state.stencilTestFunc = c->stencil_test_func;
+ state.stencilValue = c->stencil_ref_val;
+ state.stencilMask = c->stencil_mask;
+ state.stencilWriteMask = c->stencil_write_mask;
+ state.stencilSfail = c->stencil_sfail;
+ state.stencilDpfail = c->stencil_dpfail;
+ state.stencilDppass = c->stencil_dppass;
+ state.offsetStates = c->offset_states;
+ state.offsetFactor = c->offset_factor;
+ state.offsetUnits = c->offset_units;
+ state.shadowMaskBuf = c->shadow_mask_buf;
+ state.shadowColorR = c->shadow_color_r;
+ state.shadowColorG = c->shadow_color_g;
+ state.shadowColorB = c->shadow_color_b;
+
state.cullFaceEnabled = c->cull_face_enabled;
state.beginType = c->begin_type;
state.colorMask = c->color_mask;
state.currentFrontFace = c->current_front_face;
state.currentShadeModel = c->current_shade_model;
- state.depthTest = c->depth_test;
- state.offsetStates = c->offset_states;
- state.offsetFactor = c->offset_factor;
- state.offsetUnits = c->offset_units;
state.polygonModeBack = c->polygon_mode_back;
state.polygonModeFront = c->polygon_mode_front;
state.shadowMode = c->shadow_mode;
@@ -445,14 +460,7 @@ RasterizationDrawCall::RasterizationState RasterizationDrawCall::captureState()
state.texture = c->current_texture;
state.wrapS = c->texture_wrap_s;
state.wrapT = c->texture_wrap_t;
- state.shadowMaskBuf = c->shadow_mask_buf;
- state.shadowColorR = c->shadow_color_r;
- state.shadowColorG = c->shadow_color_g;
- state.shadowColorB = c->shadow_color_b;
- state.depthFunction = c->depth_func;
- state.depthWrite = c->depth_write;
state.lightingEnabled = c->lighting_enabled;
- state.depthTestEnabled = c->depth_test;
if (c->current_texture != nullptr)
state.textureVersion = c->current_texture->versionNumber;
@@ -466,11 +474,15 @@ void RasterizationDrawCall::applyState(const RasterizationDrawCall::Rasterizatio
GLContext *c = gl_get_context();
c->fb->enableBlending(state.enableBlending);
c->fb->setBlendingFactors(state.sfactor, state.dfactor);
- c->fb->enableAlphaTest(state.alphaTest);
+ c->fb->enableAlphaTest(state.alphaTestEnabled);
c->fb->setAlphaTestFunc(state.alphaFunc, state.alphaRefValue);
c->fb->setDepthFunc(state.depthFunction);
- c->fb->enableDepthWrite(state.depthWrite);
+ c->fb->enableDepthWrite(state.depthWriteMask);
c->fb->enableDepthTest(state.depthTestEnabled);
+ c->fb->enableStencilTest(state.stencilTestEnabled);
+ c->fb->setStencilWriteMask(state.stencilWriteMask);
+ c->fb->setStencilTestFunc(state.stencilTestFunc, state.stencilValue, state.stencilMask);
+ c->fb->setStencilOp(state.stencilSfail, state.stencilDpfail, state.stencilDppass);
c->fb->setOffsetStates(state.offsetStates);
c->fb->setOffsetFactor(state.offsetFactor);
c->fb->setOffsetUnits(state.offsetUnits);
@@ -480,12 +492,20 @@ void RasterizationDrawCall::applyState(const RasterizationDrawCall::Rasterizatio
c->blending_enabled = state.enableBlending;
c->source_blending_factor = state.sfactor;
c->destination_blending_factor = state.dfactor;
- c->alpha_test_enabled = state.alphaTest;
+ c->alpha_test_enabled = state.alphaTestEnabled;
c->alpha_test_func = state.alphaFunc;
c->alpha_test_ref_val = state.alphaRefValue;
- c->depth_test = state.depthTest;
+ c->depth_test_enabled = state.depthTestEnabled;
c->depth_func = state.depthFunction;
- c->depth_write = state.depthWrite;
+ c->depth_write_mask = state.depthWriteMask;
+ c->stencil_test_enabled = state.stencilTestEnabled;
+ c->stencil_test_func = state.stencilTestFunc;
+ c->stencil_ref_val = state.stencilValue;
+ c->stencil_mask = state.stencilMask;
+ c->stencil_write_mask = state.stencilWriteMask;
+ c->stencil_sfail = state.stencilSfail;
+ c->stencil_dpfail = state.stencilDpfail;
+ c->stencil_dppass = state.stencilDppass;
c->offset_states = state.offsetStates;
c->offset_factor = state.offsetFactor;
c->offset_units = state.offsetUnits;
@@ -591,7 +611,7 @@ BlittingDrawCall::BlittingState BlittingDrawCall::captureState() const {
state.alphaTest = c->alpha_test_enabled;
state.alphaFunc = c->alpha_test_func;
state.alphaRefValue = c->alpha_test_ref_val;
- state.depthTestEnabled = c->depth_test;
+ state.depthTestEnabled = c->depth_test_enabled;
return state;
}
@@ -609,7 +629,7 @@ void BlittingDrawCall::applyState(const BlittingState &state) const {
c->alpha_test_enabled = state.alphaTest;
c->alpha_test_func = state.alphaFunc;
c->alpha_test_ref_val = state.alphaRefValue;
- c->depth_test = state.depthTestEnabled;
+ c->depth_test_enabled = state.depthTestEnabled;
}
void BlittingDrawCall::computeDirtyRegion() {
@@ -643,16 +663,21 @@ void BlittingDrawCall::computeDirtyRegion() {
}
bool BlittingDrawCall::operator==(const BlittingDrawCall &other) const {
- return _mode == other._mode &&
- _image == other._image &&
- _transform == other._transform &&
- _blitState == other._blitState &&
- _imageVersion == tglGetBlitImageVersion(other._image);
+ return
+ _mode == other._mode &&
+ _image == other._image &&
+ _transform == other._transform &&
+ _blitState == other._blitState &&
+ _imageVersion == tglGetBlitImageVersion(other._image);
}
-ClearBufferDrawCall::ClearBufferDrawCall(bool clearZBuffer, int zValue, bool clearColorBuffer, int rValue, int gValue, int bValue)
- : _clearZBuffer(clearZBuffer), _clearColorBuffer(clearColorBuffer), _zValue(zValue), _rValue(rValue), _gValue(gValue), _bValue(bValue), DrawCall(DrawCall_Clear) {
+ClearBufferDrawCall::ClearBufferDrawCall(bool clearZBuffer, int zValue,
+ bool clearColorBuffer, int rValue, int gValue, int bValue,
+ bool clearStencilBuffer, int stencilValue)
+ : _clearZBuffer(clearZBuffer), _clearColorBuffer(clearColorBuffer), _zValue(zValue),
+ _rValue(rValue), _gValue(gValue), _bValue(bValue), _clearStencilBuffer(clearStencilBuffer),
+ _stencilValue(stencilValue), DrawCall(DrawCall_Clear) {
TinyGL::GLContext *c = gl_get_context();
if (c->_enableDirtyRectangles) {
_dirtyRegion = c->renderRect;
@@ -661,58 +686,71 @@ ClearBufferDrawCall::ClearBufferDrawCall(bool clearZBuffer, int zValue, bool cle
void ClearBufferDrawCall::execute(bool restoreState) const {
TinyGL::GLContext *c = gl_get_context();
- c->fb->clear(_clearZBuffer, _zValue, _clearColorBuffer, _rValue, _gValue, _bValue);
+ c->fb->clear(_clearZBuffer, _zValue, _clearColorBuffer, _rValue, _gValue, _bValue, _clearStencilBuffer, _stencilValue);
}
void ClearBufferDrawCall::execute(const Common::Rect &clippingRectangle, bool restoreState) const {
TinyGL::GLContext *c = gl_get_context();
Common::Rect clearRect = clippingRectangle.findIntersectingRect(getDirtyRegion());
- c->fb->clearRegion(clearRect.left, clearRect.top, clearRect.width(), clearRect.height(), _clearZBuffer, _zValue, _clearColorBuffer, _rValue, _gValue, _bValue);
+ c->fb->clearRegion(clearRect.left, clearRect.top, clearRect.width(), clearRect.height(),
+ _clearZBuffer, _zValue, _clearColorBuffer, _rValue, _gValue, _bValue,
+ _clearStencilBuffer, _stencilValue);
}
bool ClearBufferDrawCall::operator==(const ClearBufferDrawCall &other) const {
- return _clearZBuffer == other._clearZBuffer &&
- _clearColorBuffer == other._clearColorBuffer &&
- _rValue == other._rValue &&
- _gValue == other._gValue &&
- _bValue == other._bValue &&
- _zValue == other._zValue;
+ return
+ _clearZBuffer == other._clearZBuffer &&
+ _clearColorBuffer == other._clearColorBuffer &&
+ _clearStencilBuffer == other._clearStencilBuffer &&
+ _rValue == other._rValue &&
+ _gValue == other._gValue &&
+ _bValue == other._bValue &&
+ _zValue == other._zValue &&
+ _stencilValue == other._stencilValue;
}
bool RasterizationDrawCall::RasterizationState::operator==(const RasterizationState &other) const {
- return beginType == other.beginType &&
- currentFrontFace == other.currentFrontFace &&
- cullFaceEnabled == other.cullFaceEnabled &&
- colorMask == other.colorMask &&
- depthTest == other.depthTest &&
- offsetStates == other.offsetStates &&
- offsetFactor == other.offsetFactor &&
- offsetUnits == other.offsetUnits &&
- depthFunction == other.depthFunction &&
- depthWrite == other.depthWrite &&
- shadowMode == other.shadowMode &&
- texture2DEnabled == other.texture2DEnabled &&
- currentShadeModel == other.currentShadeModel &&
- polygonModeBack == other.polygonModeBack &&
- polygonModeFront == other.polygonModeFront &&
- lightingEnabled == other.lightingEnabled &&
- enableBlending == other.enableBlending &&
- sfactor == other.sfactor &&
- dfactor == other.dfactor &&
- alphaTest == other.alphaTest &&
- alphaFunc == other.alphaFunc &&
- alphaRefValue == other.alphaRefValue &&
- depthTestEnabled == other.depthTestEnabled &&
- texture == other.texture &&
- textureVersion == texture->versionNumber &&
- shadowMaskBuf == other.shadowMaskBuf &&
- viewportTranslation[0] == other.viewportTranslation[0] &&
- viewportTranslation[1] == other.viewportTranslation[1] &&
- viewportTranslation[2] == other.viewportTranslation[2] &&
- viewportScaling[0] == other.viewportScaling[0] &&
- viewportScaling[1] == other.viewportScaling[1] &&
- viewportScaling[2] == other.viewportScaling[2];
+ return
+ enableBlending == other.enableBlending &&
+ sfactor == other.sfactor &&
+ dfactor == other.dfactor &&
+ alphaTestEnabled == other.alphaTestEnabled &&
+ alphaFunc == other.alphaFunc &&
+ alphaRefValue == other.alphaRefValue &&
+ depthTestEnabled == other.depthTestEnabled &&
+ depthFunction == other.depthFunction &&
+ depthWriteMask == other.depthWriteMask &&
+ stencilTestEnabled == other.stencilTestEnabled &&
+ stencilTestFunc == other.stencilTestFunc &&
+ stencilValue == other.stencilValue &&
+ stencilMask == other.stencilMask &&
+ stencilWriteMask == other.stencilWriteMask &&
+ stencilSfail == other.stencilSfail &&
+ stencilDpfail == other.stencilDpfail &&
+ stencilDppass == other.stencilDppass &&
+ offsetStates == other.offsetStates &&
+ offsetFactor == other.offsetFactor &&
+ offsetUnits == other.offsetUnits &&
+ shadowMaskBuf == other.shadowMaskBuf &&
+ lightingEnabled == other.lightingEnabled &&
+ cullFaceEnabled == other.cullFaceEnabled &&
+ beginType == other.beginType &&
+ colorMask == other.colorMask &&
+ currentFrontFace == other.currentFrontFace &&
+ currentShadeModel == other.currentShadeModel &&
+ polygonModeBack == other.polygonModeBack &&
+ polygonModeFront == other.polygonModeFront &&
+ shadowMode == other.shadowMode &&
+ texture2DEnabled == other.texture2DEnabled &&
+ texture == other.texture &&
+ textureVersion == texture->versionNumber &&
+ viewportTranslation[0] == other.viewportTranslation[0] &&
+ viewportTranslation[1] == other.viewportTranslation[1] &&
+ viewportTranslation[2] == other.viewportTranslation[2] &&
+ viewportScaling[0] == other.viewportScaling[0] &&
+ viewportScaling[1] == other.viewportScaling[1] &&
+ viewportScaling[2] == other.viewportScaling[2];
}
void *Internal::allocateFrame(int size) {
diff --git a/graphics/tinygl/zdirtyrect.h b/graphics/tinygl/zdirtyrect.h
index 92fd8b189d..68c9d50c68 100644
--- a/graphics/tinygl/zdirtyrect.h
+++ b/graphics/tinygl/zdirtyrect.h
@@ -23,6 +23,7 @@
#ifndef GRAPHICS_TINYGL_ZRECT_H
#define GRAPHICS_TINYGL_ZRECT_H
+#include "common/types.h"
#include "common/rect.h"
#include "common/array.h"
@@ -65,7 +66,7 @@ private:
class ClearBufferDrawCall : public DrawCall {
public:
- ClearBufferDrawCall(bool clearZBuffer, int zValue, bool clearColorBuffer, int rValue, int gValue, int bValue);
+ ClearBufferDrawCall(bool clearZBuffer, int zValue, bool clearColorBuffer, int rValue, int gValue, int bValue, bool clearStencilBuffer, int stencilValue);
virtual ~ClearBufferDrawCall() { }
bool operator==(const ClearBufferDrawCall &other) const;
virtual void execute(bool restoreState) const;
@@ -77,8 +78,8 @@ public:
void operator delete(void *p) { }
private:
- bool _clearZBuffer, _clearColorBuffer;
- int _rValue, _gValue, _bValue, _zValue;
+ bool _clearZBuffer, _clearColorBuffer, _clearStencilBuffer;
+ int _rValue, _gValue, _bValue, _zValue, _stencilValue;
};
// Encapsulate a rasterization call: it might execute either a triangle or line rasterization.
@@ -107,32 +108,41 @@ private:
int currentFrontFace;
int cullFaceEnabled;
int colorMask;
- int depthTest;
+ bool depthTestEnabled;
int depthFunction;
- int depthWrite;
+ int depthWriteMask;
int shadowMode;
int shadowColorR;
int shadowColorG;
int shadowColorB;
- int texture2DEnabled;
+ bool texture2DEnabled;
int currentShadeModel;
int polygonModeBack;
int polygonModeFront;
int lightingEnabled;
bool enableBlending;
- int sfactor, dfactor;
+ int sfactor;
+ int dfactor;
int textureVersion;
- int depthTestEnabled;
int offsetStates;
float offsetFactor;
float offsetUnits;
float viewportTranslation[3];
float viewportScaling[3];
- bool alphaTest;
- int alphaFunc, alphaRefValue;
+ bool alphaTestEnabled;
+ int alphaFunc;
+ int alphaRefValue;
+ bool stencilTestEnabled;
+ int stencilTestFunc;
+ int stencilValue;
+ uint stencilMask;
+ uint stencilWriteMask;
+ int stencilSfail;
+ int stencilDpfail;
+ int stencilDppass;
TinyGL::GLTexture *texture;
- unsigned int wrapS, wrapT;
- unsigned char *shadowMaskBuf;
+ uint wrapS, wrapT;
+ byte *shadowMaskBuf;
bool operator==(const RasterizationState &other) const;
};
@@ -181,13 +191,14 @@ private:
int depthTestEnabled;
bool operator==(const BlittingState &other) const {
- return enableBlending == other.enableBlending &&
- sfactor == other.sfactor &&
- dfactor == other.dfactor &&
- alphaTest == other.alphaTest &&
- alphaFunc == other.alphaFunc &&
- alphaRefValue == other.alphaRefValue &&
- depthTestEnabled == other.depthTestEnabled;
+ return
+ enableBlending == other.enableBlending &&
+ sfactor == other.sfactor &&
+ dfactor == other.dfactor &&
+ alphaTest == other.alphaTest &&
+ alphaFunc == other.alphaFunc &&
+ alphaRefValue == other.alphaRefValue &&
+ depthTestEnabled == other.depthTestEnabled;
}
};
diff --git a/graphics/tinygl/zgl.h b/graphics/tinygl/zgl.h
index 78cd9aa8f6..d1f6295d9f 100644
--- a/graphics/tinygl/zgl.h
+++ b/graphics/tinygl/zgl.h
@@ -359,6 +359,7 @@ struct GLContext {
// clear
float clear_depth;
Vector4 clear_color;
+ int clear_stencil;
// current vertex state
Vector4 current_color;
@@ -410,9 +411,19 @@ struct GLContext {
int (*gl_resize_viewport)(int *xsize, int *ysize);
// depth test
- bool depth_test;
+ bool depth_test_enabled;
int depth_func;
- bool depth_write;
+ bool depth_write_mask;
+
+ // stencil
+ bool stencil_test_enabled;
+ int stencil_test_func;
+ int stencil_ref_val;
+ uint stencil_mask;
+ uint stencil_write_mask;
+ int stencil_sfail;
+ int stencil_dpfail;
+ int stencil_dppass;
int color_mask;
@@ -479,7 +490,7 @@ public:
void initSharedState();
void endSharedState();
- void init(int screenW, int screenH, Graphics::PixelFormat pixelFormat, int textureSize, bool dirtyRectsEnable = true);
+ void init(int screenW, int screenH, Graphics::PixelFormat pixelFormat, int textureSize, bool enableStencilBuffer, bool dirtyRectsEnable = true);
void deinit();
};
diff --git a/graphics/tinygl/ztriangle.cpp b/graphics/tinygl/ztriangle.cpp
index d96634dda0..7c986878b7 100644
--- a/graphics/tinygl/ztriangle.cpp
+++ b/graphics/tinygl/ztriangle.cpp
@@ -35,20 +35,48 @@ namespace TinyGL {
static const int NB_INTERP = 8;
-template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
-FORCEINLINE void FrameBuffer::putPixelFlat(FrameBuffer *buffer, int buf, unsigned int *pz, int _a,
- int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a, int &dzdx) {
- if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
+template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending, bool kStencilEnabled>
+FORCEINLINE void FrameBuffer::putPixelFlat(FrameBuffer *buffer, int buf, unsigned int *pz, byte *ps, int _a,
+ int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a, int &dzdx) {
+ if (kEnableScissor && buffer->scissorPixel(x + _a, y)) {
+ return;
+ }
+ if (kStencilEnabled) {
+ bool stencilResult = stencilTest(ps[_a]);
+ if (!stencilResult) {
+ stencilOp(false, true, ps + _a);
+ return;
+ }
+ }
+ bool depthTestResult = buffer->compareDepth(z, pz[_a]);
+ if (kStencilEnabled) {
+ stencilOp(true, depthTestResult, ps + _a);
+ }
+ if (depthTestResult) {
buffer->writePixel<kEnableAlphaTest, kEnableBlending, kDepthWrite>(buf + _a, a >> (ZB_POINT_ALPHA_BITS - 8), r >> (ZB_POINT_RED_BITS - 8), g >> (ZB_POINT_GREEN_BITS - 8), b >> (ZB_POINT_BLUE_BITS - 8), z);
}
z += dzdx;
}
-template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
-FORCEINLINE void FrameBuffer::putPixelSmooth(FrameBuffer *buffer, int buf, unsigned int *pz, int _a,
- int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
- int &dzdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx) {
- if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
+template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending, bool kStencilEnabled>
+FORCEINLINE void FrameBuffer::putPixelSmooth(FrameBuffer *buffer, int buf, unsigned int *pz, byte *ps, int _a,
+ int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
+ int &dzdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx) {
+ if (kEnableScissor && buffer->scissorPixel(x + _a, y)) {
+ return;
+ }
+ if (kStencilEnabled) {
+ bool stencilResult = stencilTest(ps[_a]);
+ if (!stencilResult) {
+ stencilOp(false, true, ps + _a);
+ return;
+ }
+ }
+ bool depthTestResult = buffer->compareDepth(z, pz[_a]);
+ if (kStencilEnabled) {
+ stencilOp(true, depthTestResult, ps + _a);
+ }
+ if (depthTestResult) {
buffer->writePixel<kEnableAlphaTest, kEnableBlending, kDepthWrite>(buf + _a, a >> (ZB_POINT_ALPHA_BITS - 8), r >> (ZB_POINT_RED_BITS - 8), g >> (ZB_POINT_GREEN_BITS - 8), b >> (ZB_POINT_BLUE_BITS - 8), z);
}
z += dzdx;
@@ -58,32 +86,54 @@ FORCEINLINE void FrameBuffer::putPixelSmooth(FrameBuffer *buffer, int buf, unsig
b += dbdx;
}
-template <bool kDepthWrite, bool kEnableScissor>
-FORCEINLINE void FrameBuffer::putPixelDepth(FrameBuffer *buffer, int buf, unsigned int *pz, int _a, int x, int y, unsigned int &z, int &dzdx) {
- if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
- if (kDepthWrite) {
- pz[_a] = z;
+template <bool kDepthWrite, bool kEnableScissor, bool kStencilEnabled>
+FORCEINLINE void FrameBuffer::putPixelDepth(FrameBuffer *buffer, int buf, unsigned int *pz, byte *ps, int _a, int x, int y, unsigned int &z, int &dzdx) {
+ if (kEnableScissor && buffer->scissorPixel(x + _a, y)) {
+ return;
+ }
+ if (kStencilEnabled) {
+ bool stencilResult = stencilTest(ps[_a]);
+ if (!stencilResult) {
+ stencilOp(false, true, ps + _a);
+ return;
}
}
+ if (kDepthWrite && buffer->compareDepth(z, pz[_a])) {
+ pz[_a] = z;
+ }
z += dzdx;
}
template <bool kDepthWrite, bool kAlphaTestEnabled, bool kEnableScissor, bool kBlendingEnabled>
FORCEINLINE void FrameBuffer::putPixelShadow(FrameBuffer *buffer, int buf, unsigned int *pz, int _a, int x, int y, unsigned int &z,
- unsigned int &r, unsigned int &g, unsigned int &b, int &dzdx, unsigned char *pm) {
+ unsigned int &r, unsigned int &g, unsigned int &b, int &dzdx, unsigned char *pm) {
if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a]) && pm[_a]) {
buffer->writePixel<kAlphaTestEnabled, kBlendingEnabled, kDepthWrite>(buf + _a, 255, r >> (ZB_POINT_RED_BITS - 8), g >> (ZB_POINT_GREEN_BITS - 8), b >> (ZB_POINT_BLUE_BITS - 8), z);
}
z += dzdx;
}
-template <bool kDepthWrite, bool kLightsMode, bool kSmoothMode, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
+template <bool kDepthWrite, bool kLightsMode, bool kSmoothMode, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending, bool kStencilEnabled>
FORCEINLINE void FrameBuffer::putPixelTextureMappingPerspective(FrameBuffer *buffer, int buf, const Graphics::TexelBuffer *texture,
- unsigned int wrap_s, unsigned int wrap_t, unsigned int *pz, int _a,
- int x, int y, unsigned int &z, int &t, int &s,
- unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
- int &dzdx, int &dsdx, int &dtdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx) {
- if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
+ unsigned int wrap_s, unsigned int wrap_t, unsigned int *pz, byte *ps, int _a,
+ int x, int y, unsigned int &z, int &t, int &s,
+ unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
+ int &dzdx, int &dsdx, int &dtdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx) {
+ if (kEnableScissor && buffer->scissorPixel(x + _a, y)) {
+ return;
+ }
+ if (kStencilEnabled) {
+ bool stencilResult = stencilTest(ps[_a]);
+ if (!stencilResult) {
+ stencilOp(false, true, ps + _a);
+ return;
+ }
+ }
+ bool depthTestResult = buffer->compareDepth(z, pz[_a]);
+ if (kStencilEnabled) {
+ stencilOp(true, depthTestResult, ps + _a);
+ }
+ if (depthTestResult) {
uint8 c_a, c_r, c_g, c_b;
texture->getARGBAt(wrap_s, wrap_t, s, t, c_a, c_r, c_g, c_b);
if (kLightsMode) {
@@ -109,15 +159,16 @@ FORCEINLINE void FrameBuffer::putPixelTextureMappingPerspective(FrameBuffer *buf
}
}
-template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool kAlphaTestEnabled, bool kEnableScissor, bool kBlendingEnabled>
+template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool kAlphaTestEnabled, bool kEnableScissor, bool kBlendingEnabled, bool kStencilEnabled>
void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
const Graphics::TexelBuffer *texture;
float fdzdx = 0, fndzdx = 0, ndszdx = 0, ndtzdx = 0;
ZBufferPoint *tp, *pr1 = 0, *pr2 = 0, *l1 = 0, *l2 = 0;
float fdx1, fdx2, fdy1, fdy2, fz0, d1, d2;
- unsigned int *pz1 = NULL;
- unsigned char *pm1 = NULL;
+ uint *pz1 = nullptr;
+ byte *pm1 = nullptr;
+ byte *ps1 = nullptr;
int part, update_left = 1, update_right = 1;
int nb_lines, dx1, dy1, tmp, dx2, dy2, y;
@@ -243,6 +294,9 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
int pp1 = _pbufWidth * p0->y;
pz1 = _zbuf + p0->y * _pbufWidth;
+ if (kStencilEnabled) {
+ ps1 = _sbuf + p0->y * _pbufWidth;
+ }
switch (kDrawLogic) {
case DRAW_SHADOW_MASK:
@@ -375,6 +429,7 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
int pp;
int n;
unsigned int *pz;
+ byte *ps = nullptr;
unsigned int z, a;
int buf = pp1 + x1;
unsigned int r = r1;
@@ -386,41 +441,50 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
pz = pz1 + x1;
z = z1;
}
+ if (kStencilEnabled) {
+ ps = ps1 + x1;
+ }
if (kDrawLogic == DRAW_FLAT) {
a = a1;
}
while (n >= 3) {
if (kDrawLogic == DRAW_DEPTH_ONLY) {
- putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 0, x, y, z, dzdx);
- putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 1, x, y, z, dzdx);
- putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 2, x, y, z, dzdx);
- putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 3, x, y, z, dzdx);
+ putPixelDepth<kDepthWrite, kEnableScissor, kStencilEnabled>(this, buf, pz, ps, 0, x, y, z, dzdx);
+ putPixelDepth<kDepthWrite, kEnableScissor, kStencilEnabled>(this, buf, pz, ps, 1, x, y, z, dzdx);
+ putPixelDepth<kDepthWrite, kEnableScissor, kStencilEnabled>(this, buf, pz, ps, 2, x, y, z, dzdx);
+ putPixelDepth<kDepthWrite, kEnableScissor, kStencilEnabled>(this, buf, pz, ps, 3, x, y, z, dzdx);
buf += 4;
}
if (kDrawLogic == DRAW_FLAT) {
- putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 0, x, y, z, r, g, b, a, dzdx);
- putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 1, x, y, z, r, g, b, a, dzdx);
- putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 2, x, y, z, r, g, g, a, dzdx);
- putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 3, x, y, z, r, g, b, a, dzdx);
+ putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, pp, pz, ps, 0, x, y, z, r, g, b, a, dzdx);
+ putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, pp, pz, ps, 1, x, y, z, r, g, b, a, dzdx);
+ putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, pp, pz, ps, 2, x, y, z, r, g, g, a, dzdx);
+ putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, pp, pz, ps, 3, x, y, z, r, g, b, a, dzdx);
}
if (kInterpZ) {
pz += 4;
}
+ if (kStencilEnabled) {
+ ps += 4;
+ }
pp += 4;
n -= 4;
x += 4;
}
while (n >= 0) {
if (kDrawLogic == DRAW_DEPTH_ONLY) {
- putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 0, x, y, z, dzdx);
+ putPixelDepth<kDepthWrite, kEnableScissor, kStencilEnabled>(this, buf, pz, ps, 0, x, y, z, dzdx);
buf ++;
}
if (kDrawLogic == DRAW_FLAT) {
- putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 0, x, y, z, r, g, b, a, dzdx);
+ putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, pp, pz, ps, 0, x, y, z, r, g, b, a, dzdx);
}
if (kInterpZ) {
pz += 1;
}
+ if (kStencilEnabled) {
+ ps += 1;
+ }
pp += 1;
n -= 1;
x += 1;
@@ -483,35 +547,46 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
}
} else if (kDrawLogic == DRAW_SMOOTH && !(kInterpST || kInterpSTZ)) {
unsigned int *pz;
+ byte *ps = nullptr;
int buf = pp1 + x1;
unsigned int z, r, g, b, a;
int n;
n = (x2 >> 16) - x1;
pz = pz1 + x1;
+ if (kStencilEnabled) {
+ ps = ps1 + x1;
+ }
z = z1;
r = r1;
g = g1;
b = b1;
a = a1;
while (n >= 3) {
- putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 0, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
- putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 1, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
- putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 2, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
- putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 3, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
+ putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, buf, pz, ps, 0, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
+ putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, buf, pz, ps, 1, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
+ putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, buf, pz, ps, 2, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
+ putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, buf, pz, ps, 3, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
pz += 4;
+ if (kStencilEnabled) {
+ ps += 4;
+ }
buf += 4;
n -= 4;
x += 4;
}
while (n >= 0) {
- putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 0, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
+ putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>(this, buf, pz, ps, 0, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
buf += 1;
pz += 1;
+ if (kStencilEnabled) {
+ ps += 1;
+ }
n -= 1;
x += 1;
}
} else if (kInterpST || kInterpSTZ) {
unsigned int *pz;
+ byte *ps = nullptr;
int s, t;
unsigned int z, r, g, b, a;
int n;
@@ -525,6 +600,9 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
int buf = pp1 + x1;
pz = pz1 + x1;
+ if (kStencilEnabled) {
+ ps = ps1 + x1;
+ }
z = z1;
sz = sz1;
tz = tz1;
@@ -545,10 +623,13 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
zinv = (float)(1.0 / fz);
}
for (int _a = 0; _a < NB_INTERP; _a++) {
- putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, texture, _wrapS, _wrapT,
- pz, _a, x, y, z, t, s, r, g, b, a, dzdx, dsdx, dtdx, drdx, dgdx, dbdx, dadx);
+ putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>
+ (this, buf, texture, _wrapS, _wrapT, pz, ps, _a, x, y, z, t, s, r, g, b, a, dzdx, dsdx, dtdx, drdx, dgdx, dbdx, dadx);
}
pz += NB_INTERP;
+ if (kStencilEnabled) {
+ ps += NB_INTERP;
+ }
buf += NB_INTERP;
n -= NB_INTERP;
x += NB_INTERP;
@@ -567,9 +648,12 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
}
while (n >= 0) {
- putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, texture, _wrapS, _wrapT,
- pz, 0, x, y, z, t, s, r, g, b, a, dzdx, dsdx, dtdx, drdx, dgdx, dbdx, dadx);
+ putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled, kStencilEnabled>
+ (this, buf, texture, _wrapS, _wrapT, pz, ps, 0, x, y, z, t, s, r, g, b, a, dzdx, dsdx, dtdx, drdx, dgdx, dbdx, dadx);
pz += 1;
+ if (kStencilEnabled) {
+ ps += 1;
+ }
buf += 1;
n -= 1;
x += 1;
@@ -620,15 +704,27 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
// screen coordinates
pp1 += _pbufWidth;
pz1 += _pbufWidth;
+ if (kStencilEnabled) {
+ ps1 += _pbufWidth;
+ }
if (kDrawLogic == DRAW_SHADOW || kDrawLogic == DRAW_SHADOW_MASK)
- pm1 = pm1 + _pbufWidth;
+ pm1 += _pbufWidth;
nb_lines--;
y++;
}
}
}
+template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
+void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
+ if (_sbuf && _stencilTestEnabled) {
+ fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, kDepthWrite, kEnableAlphaTest, kEnableScissor, kEnableBlending, true>(p0, p1, p2);
+ } else {
+ fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, kDepthWrite, kEnableAlphaTest, kEnableScissor, kEnableBlending, false>(p0, p1, p2);
+ }
+}
+
template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor>
void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
if (_blendingEnabled) {
More information about the Scummvm-git-logs
mailing list