mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 04:38:30 +09:00
[Fix, Test] (RenderState, DirectGLES, MG_IntegrationTest): tell a deliberately empty scissor box apart from one that was never written
This commit is contained in:
@@ -2134,19 +2134,31 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
if (tailSpanDirty) { // Scissor box. Resolved and shadowed like the viewport above, and
|
||||
// for the same reason: what has to reach the driver is NOT simply the parameter
|
||||
// field. (0,0,0,0) is where RenderStateParameters::ScissorBox starts and the only
|
||||
// thing that ever writes it is glScissor, so that value means "the application has
|
||||
// never called glScissor" - it is not a GL scissor box. GL's initial box is the
|
||||
// whole window, which the frontend has no way to spell before a surface exists.
|
||||
// The pre-resync code got away with pushing the field verbatim only by accident:
|
||||
// the shadow held the same default, the field never compared unequal, and the ES
|
||||
// context kept its own correct default. Under the forced full push that accident
|
||||
// is gone, glScissor(0,0,0,0) shrinks the scissor to an EMPTY rectangle, and
|
||||
// everything drawn with GL_SCISSOR_TEST enabled before the app's first glScissor
|
||||
// is clipped away - Minecraft 26.2 keeps only its unscissored sky and hand and
|
||||
// loses the terrain and the whole GUI.
|
||||
// field. RenderStateParameters::ScissorBoxes starts all-zero, which means "the
|
||||
// application has never called glScissor" - it is not a GL scissor box. GL's
|
||||
// initial box is the whole window, which the frontend has no way to spell before a
|
||||
// surface exists. The pre-resync code got away with pushing the field verbatim only
|
||||
// by accident: the shadow held the same default, the field never compared unequal,
|
||||
// and the ES context kept its own correct default. Under the forced full push that
|
||||
// accident is gone, glScissor(0,0,0,0) shrinks the scissor to an EMPTY rectangle,
|
||||
// and everything drawn with GL_SCISSOR_TEST enabled before the app's first
|
||||
// glScissor is clipped away - Minecraft 26.2 keeps only its unscissored sky and
|
||||
// hand and loses the terrain and the whole GUI.
|
||||
//
|
||||
// The condition is the WRITTEN FLAG, not the extent. An empty rectangle is a
|
||||
// perfectly legal thing to ask for - glScissor(0,0,0,0) means "the scissor test
|
||||
// rejects every fragment" - so testing `width <= 0 || height <= 0` substituted the
|
||||
// whole surface for a deliberately empty box and inverted the request into "accept
|
||||
// every fragment", no matter how many times the application had already called
|
||||
// glScissor. KHR-GL43.viewport_array.scissor_zero_dimension is exactly that: all 16
|
||||
// boxes zero-sized with the test enabled, requiring the draw to be clipped away
|
||||
// entirely. Reading the flag preserves the Minecraft protection bit-for-bit - before
|
||||
// the first glScissor the bit is clear and the surface size is still substituted -
|
||||
// while an explicit empty box now reaches the driver verbatim. Negative extents
|
||||
// cannot arrive here at all: all three entry points reject them with
|
||||
// GL_INVALID_VALUE before storing (GL_RenderState.cpp's ValidateNonNegativeExtent).
|
||||
IntVec4 backendScissorBox = parameters.ScissorBoxes[0];
|
||||
if (backendScissorBox.z() <= 0 || backendScissorBox.w() <= 0) {
|
||||
if ((parameters.ScissorBoxWrittenMask & 1u) == 0) {
|
||||
Int surfaceWidth = 0;
|
||||
Int surfaceHeight = 0;
|
||||
if (QueryCurrentSurfaceSize(surfaceWidth, surfaceHeight)) {
|
||||
|
||||
Reference in New Issue
Block a user