@@ -5389,6 +5389,11 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
53895389 int xEnd = (int )end -> position [0 ];
53905390 if (xStart == xEnd ) return ;
53915391
5392+ // Get the current row and skip if outside the framebuffer.
5393+ // Maybe this check is better suited elsewhere?
5394+ int y = (int )start -> position [1 ];
5395+ if (y < 0 || y >= RLSW .colorBuffer -> height ) return ;
5396+
53925397 // Compute the inverse horizontal distance along the X axis
53935398 float dxRcp = sw_rcp (end -> position [0 ] - start -> position [0 ]);
53945399
@@ -5411,38 +5416,45 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
54115416 // Compute the subpixel distance to traverse before the first pixel
54125417 float xSubstep = 1.0f - sw_fract (start -> position [0 ]);
54135418
5414- // Initializing the interpolation starting values
5415- float w = start -> position [3 ] + dWdx * xSubstep ;
5419+ // Intercept the span bounds to ensure we don't write before the framebuffer.
5420+ int xLoopStart = sw_clamp_int (xStart , 0 , RLSW .colorBuffer -> width - 1 );
5421+ int dxStart = xLoopStart - xStart ;
5422+
5423+ // Initializing the interpolation starting values.
5424+ // Also step further into them to move away from the colorbuffer edge.
5425+ float w = start -> position [3 ] + dWdx * xSubstep + dWdx * dxStart ;
54165426 float color [4 ] = {
5417- start -> color [0 ] + dCdx [0 ]* xSubstep ,
5418- start -> color [1 ] + dCdx [1 ]* xSubstep ,
5419- start -> color [2 ] + dCdx [2 ]* xSubstep ,
5420- start -> color [3 ] + dCdx [3 ]* xSubstep
5427+ start -> color [0 ] + dCdx [0 ]* xSubstep + dCdx [ 0 ] * dxStart ,
5428+ start -> color [1 ] + dCdx [1 ]* xSubstep + dCdx [ 1 ] * dxStart ,
5429+ start -> color [2 ] + dCdx [2 ]* xSubstep + dCdx [ 2 ] * dxStart ,
5430+ start -> color [3 ] + dCdx [3 ]* xSubstep + dCdx [ 3 ] * dxStart
54215431 };
54225432#ifdef SW_ENABLE_DEPTH_TEST
5423- float z = start -> position [2 ] + dZdx * xSubstep ;
5433+ float z = start -> position [2 ] + dZdx * xSubstep + dZdx * dxStart ;
54245434#endif
54255435#ifdef SW_ENABLE_TEXTURE
5426- float u = start -> texcoord [0 ] + dUdx * xSubstep ;
5427- float v = start -> texcoord [1 ] + dVdx * xSubstep ;
5436+ float u = start -> texcoord [0 ] + dUdx * xSubstep + dUdx * dxStart ;
5437+ float v = start -> texcoord [1 ] + dVdx * xSubstep + dVdx * dxStart ;
54285438#endif
54295439
54305440 // Pre-calculate the starting pointers for the framebuffer row
5431- int y = ( int ) start -> position [ 1 ];
5432- int baseOffset = y * RLSW .colorBuffer -> width + xStart ;
5441+ // Don't allow a y value outside the buffer.
5442+ int baseOffset = y * RLSW .colorBuffer -> width + xLoopStart ;
54335443 uint8_t * cPtr = (uint8_t * )(RLSW .colorBuffer -> pixels ) + baseOffset * SW_FRAMEBUFFER_COLOR_SIZE ;
54345444#ifdef SW_ENABLE_DEPTH_TEST
54355445 uint8_t * dPtr = (uint8_t * )(RLSW .depthBuffer -> pixels ) + baseOffset * SW_FRAMEBUFFER_DEPTH_SIZE ;
54365446#endif
54375447
54385448#define SW_AFFINE_BLOCK 16
54395449
5440- int x = xStart ;
5441- while (x < xEnd )
5450+ int x = xLoopStart ;
5451+ // Prevent pixels from beyond the buffer from processing.
5452+ int xLoopEnd = sw_clamp_int (xEnd , 0 , RLSW .colorBuffer -> width - 1 );
5453+ while (x < xLoopEnd )
54425454 {
54435455 // Clamp last block to remaining pixels
54445456 int blockEnd = x + SW_AFFINE_BLOCK ;
5445- if (blockEnd > xEnd ) blockEnd = xEnd ;
5457+ if (blockEnd > xLoopEnd ) blockEnd = xLoopEnd ;
54465458 float blockLenF = (float )(blockEnd - x );
54475459 float blockLenRcp = sw_rcp (blockLenF );
54485460
@@ -5730,21 +5742,38 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
57305742 uint8_t * dPixels = RLSW .depthBuffer -> pixels ;
57315743#endif
57325744
5733- for (int y = yMin ; y < yMax ; y ++ )
5745+ // Intercept the boundaries to stay within the framebuffer.
5746+ int yLoopMin = sw_clamp_int (yMin , 0 , RLSW .colorBuffer -> height - 1 );
5747+ int yLoopMax = sw_clamp_int (yMax , 0 , RLSW .colorBuffer -> height - 1 );
5748+ int xLoopMin = sw_clamp_int (xMin , 0 , RLSW .colorBuffer -> width - 1 );
5749+ int xLoopMax = sw_clamp_int (xMax , 0 , RLSW .colorBuffer -> width - 1 );
5750+ int dxMin = xLoopMin - xMin ;
5751+ #if defined(SW_ENABLE_DEPTH_TEST ) || defined(SW_ENABLE_TEXTURE )
5752+ int dyMin = yLoopMin - yMin ;
5753+ #endif
5754+
5755+ for (int y = yLoopMin ; y < yLoopMax ; y ++ )
57345756 {
5735- int baseOffset = y * stride + xMin ;
5757+ int baseOffset = y * stride + xLoopMin ;
57365758 uint8_t * cPtr = cPixels + baseOffset * SW_FRAMEBUFFER_COLOR_SIZE ;
57375759 #ifdef SW_ENABLE_DEPTH_TEST
57385760 uint8_t * dPtr = dPixels + baseOffset * SW_FRAMEBUFFER_DEPTH_SIZE ;
5739- float z = zRow ;
5761+ // Correct our start by how far we clipped outside the framebuffer.
5762+ float z = zRow + dZdy * dyMin ;
57405763 #endif
57415764 #ifdef SW_ENABLE_TEXTURE
5742- float u = uRow ;
5743- float v = vRow ;
5765+ // Correct our start by how far we clipped outside the framebuffer.
5766+ float u = uRow + dUdy * dyMin ;
5767+ float v = vRow + dVdy * dyMin ;
57445768 #endif
5745- float color [4 ] = { cRow [0 ], cRow [1 ], cRow [2 ], cRow [3 ] };
5769+ float color [4 ] = {
5770+ cRow [0 ] + dCdx [0 ]* dxMin ,
5771+ cRow [1 ] + dCdx [1 ]* dxMin ,
5772+ cRow [2 ] + dCdx [2 ]* dxMin ,
5773+ cRow [3 ] + dCdx [3 ]* dxMin
5774+ };
57465775
5747- for (int x = xMin ; x < xMax ; x ++ )
5776+ for (int x = xLoopMin ; x < xLoopMax ; x ++ )
57485777 {
57495778 float srcColor [4 ] = { color [0 ], color [1 ], color [2 ], color [3 ] };
57505779
0 commit comments