summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibSoftGPU/Device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibSoftGPU/Device.cpp')
-rw-r--r--Userland/Libraries/LibSoftGPU/Device.cpp63
1 files changed, 27 insertions, 36 deletions
diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp
index c5f601b1df..28f4ae4a38 100644
--- a/Userland/Libraries/LibSoftGPU/Device.cpp
+++ b/Userland/Libraries/LibSoftGPU/Device.cpp
@@ -183,11 +183,6 @@ void Device::rasterize_triangle(const Triangle& triangle)
{
INCREASE_STATISTICS_COUNTER(g_num_rasterized_triangles, 1);
- // Since the algorithm is based on blocks of uniform size, we need
- // to ensure that our m_render_target size is actually a multiple of the block size
- VERIFY((m_render_target->width() % 2) == 0);
- VERIFY((m_render_target->height() % 2) == 0);
-
// Return if alpha testing is a no-op
if (m_options.enable_alpha_test && m_options.alpha_test_func == AlphaTestFunction::Never)
return;
@@ -244,13 +239,6 @@ void Device::rasterize_triangle(const Triangle& triangle)
&& edges.z() >= zero.z();
};
- auto test_scissor4 = [window_scissor_rect](const Vector2<i32x4>& screen_coordinates) -> i32x4 {
- return screen_coordinates.x() >= window_scissor_rect.x()
- && screen_coordinates.x() < window_scissor_rect.x() + window_scissor_rect.width()
- && screen_coordinates.y() >= window_scissor_rect.y()
- && screen_coordinates.y() < window_scissor_rect.y() + window_scissor_rect.height();
- };
-
// Calculate block-based bounds
// clang-format off
int const bx0 = max(render_bounds.left(), min(min(v0.x(), v1.x()), v2.x()) / subpixel_factor) & ~1;
@@ -266,6 +254,11 @@ void Device::rasterize_triangle(const Triangle& triangle)
// FIXME: implement stencil testing
+ int const render_bounds_left = render_bounds.x();
+ int const render_bounds_right = render_bounds.x() + render_bounds.width();
+ int const render_bounds_top = render_bounds.y();
+ int const render_bounds_bottom = render_bounds.y() + render_bounds.height();
+
// Iterate over all blocks within the bounds of the triangle
for (int by = by0; by < by1; by += 2) {
for (int bx = bx0; bx < bx1; bx += 2) {
@@ -281,9 +274,12 @@ void Device::rasterize_triangle(const Triangle& triangle)
// Generate triangle coverage mask
quad.mask = test_point4(edge_values);
- if (m_options.scissor_enabled) {
- quad.mask &= test_scissor4(quad.screen_coordinates);
- }
+
+ // Test quad against intersection of render target size and scissor rect
+ quad.mask &= quad.screen_coordinates.x() >= render_bounds_left
+ && quad.screen_coordinates.x() < render_bounds_right
+ && quad.screen_coordinates.y() >= render_bounds_top
+ && quad.screen_coordinates.y() < render_bounds_bottom;
if (none(quad.mask))
continue;
@@ -298,11 +294,13 @@ void Device::rasterize_triangle(const Triangle& triangle)
to_f32x4(edge_values.z()),
} * one_over_area;
+ int coverage_bits = maskbits(quad.mask);
+
float* depth_ptrs[4] = {
- &m_depth_buffer->scanline(by)[bx],
- &m_depth_buffer->scanline(by)[bx + 1],
- &m_depth_buffer->scanline(by + 1)[bx],
- &m_depth_buffer->scanline(by + 1)[bx + 1],
+ coverage_bits & 1 ? &m_depth_buffer->scanline(by)[bx] : nullptr,
+ coverage_bits & 2 ? &m_depth_buffer->scanline(by)[bx + 1] : nullptr,
+ coverage_bits & 4 ? &m_depth_buffer->scanline(by + 1)[bx] : nullptr,
+ coverage_bits & 8 ? &m_depth_buffer->scanline(by + 1)[bx + 1] : nullptr,
};
// AND the depth mask onto the coverage mask
@@ -416,10 +414,10 @@ void Device::rasterize_triangle(const Triangle& triangle)
continue;
Gfx::RGBA32* color_ptrs[4] = {
- &m_render_target->scanline(by)[bx],
- &m_render_target->scanline(by)[bx + 1],
- &m_render_target->scanline(by + 1)[bx],
- &m_render_target->scanline(by + 1)[bx + 1],
+ coverage_bits & 1 ? &m_render_target->scanline(by)[bx] : nullptr,
+ coverage_bits & 2 ? &m_render_target->scanline(by)[bx + 1] : nullptr,
+ coverage_bits & 4 ? &m_render_target->scanline(by + 1)[bx] : nullptr,
+ coverage_bits & 8 ? &m_render_target->scanline(by + 1)[bx + 1] : nullptr,
};
u32x4 dst_u32;
@@ -456,16 +454,9 @@ void Device::rasterize_triangle(const Triangle& triangle)
}
}
-static Gfx::IntSize closest_multiple(const Gfx::IntSize& min_size, size_t step)
-{
- int width = ((min_size.width() + step - 1) / step) * step;
- int height = ((min_size.height() + step - 1) / step) * step;
- return { width, height };
-}
-
-Device::Device(const Gfx::IntSize& min_size)
- : m_render_target { Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, closest_multiple(min_size, 2)).release_value_but_fixme_should_propagate_errors() }
- , m_depth_buffer { adopt_own(*new DepthBuffer(closest_multiple(min_size, 2))) }
+Device::Device(const Gfx::IntSize& size)
+ : m_render_target { Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, size).release_value_but_fixme_should_propagate_errors() }
+ , m_depth_buffer { adopt_own(*new DepthBuffer(size)) }
{
m_options.scissor_box = m_render_target->rect();
}
@@ -829,12 +820,12 @@ ALWAYS_INLINE bool Device::test_alpha(PixelQuad& quad)
return any(quad.mask);
}
-void Device::resize(const Gfx::IntSize& min_size)
+void Device::resize(const Gfx::IntSize& size)
{
wait_for_all_threads();
- m_render_target = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, closest_multiple(min_size, 2)).release_value_but_fixme_should_propagate_errors();
- m_depth_buffer = adopt_own(*new DepthBuffer(m_render_target->size()));
+ m_render_target = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, size).release_value_but_fixme_should_propagate_errors();
+ m_depth_buffer = adopt_own(*new DepthBuffer(size));
}
void Device::clear_color(const FloatVector4& color)