Browse Source

LibGL+LibSoftGPU: Implement rasterization position

Implements support for `glRasterPos` and updating the raster position's
window coordinates through `glBitmap`. The input for `glRasterPos` is
an object position that needs to go through the same vertex
transformations as our regular triangles.
Jelle Raaijmakers 3 năm trước cách đây
mục cha
commit
ca78327a96

+ 10 - 8
Userland/Libraries/LibGL/SoftwareGLContext.cpp

@@ -2262,10 +2262,7 @@ void SoftwareGLContext::gl_draw_pixels(GLsizei width, GLsizei height, GLenum for
         for (int x = 0; x < width; ++x)
             bitmap->set_pixel(x, y, Color::from_rgba(*(pixel_data++)));
 
-    m_rasterizer.blit(
-        bitmap,
-        static_cast<int>(m_current_raster_position.window_coordinates.x()),
-        static_cast<int>(m_current_raster_position.window_coordinates.y()));
+    m_rasterizer.blit_to_color_buffer_at_raster_position(bitmap);
 }
 
 void SoftwareGLContext::gl_depth_range(GLdouble min, GLdouble max)
@@ -2686,8 +2683,7 @@ void SoftwareGLContext::gl_raster_pos(GLfloat x, GLfloat y, GLfloat z, GLfloat w
     APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_raster_pos, x, y, z, w);
     RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
 
-    m_current_raster_position.window_coordinates = { x, y, z };
-    m_current_raster_position.clip_coordinate_value = w;
+    m_rasterizer.set_raster_position({ x, y, z, w }, m_model_view_matrix, m_projection_matrix);
 }
 
 void SoftwareGLContext::gl_line_width(GLfloat width)
@@ -2751,8 +2747,14 @@ void SoftwareGLContext::gl_bitmap(GLsizei width, GLsizei height, GLfloat xorig,
     APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_bitmap, width, height, xorig, yorig, xmove, ymove, bitmap);
     RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
 
-    // FIXME: implement
-    dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_bitmap({}, {}, {}, {}, {}, {}, {})", width, height, xorig, yorig, xmove, ymove, bitmap);
+    if (bitmap != nullptr) {
+        // FIXME: implement
+        dbgln_if(GL_DEBUG, "gl_bitmap({}, {}, {}, {}, {}, {}, {}): unimplemented", width, height, xorig, yorig, xmove, ymove, bitmap);
+    }
+
+    auto raster_position = m_rasterizer.raster_position();
+    raster_position.window_coordinates += { xmove, ymove, 0.f, 0.f };
+    m_rasterizer.set_raster_position(raster_position);
 }
 
 void SoftwareGLContext::gl_copy_tex_image_2d(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)

+ 0 - 11
Userland/Libraries/LibGL/SoftwareGLContext.h

@@ -418,17 +418,6 @@ private:
     GLsizei m_unpack_row_length { 0 };
     u8 m_unpack_alignment { 4 };
 
-    struct RasterPosition {
-        FloatVector3 window_coordinates { 0.0f, 0.0f, 0.0f };
-        float clip_coordinate_value { 1.0f };
-        float eye_coordinate_distance { 0.0f };
-        bool valid { true };
-        FloatVector4 color_rgba { 1.0f, 1.0f, 1.0f, 1.0f };
-        float color_index { 1.0f };
-        FloatVector4 texture_coordinates { 0.0f, 0.0f, 0.0f, 1.0f };
-    };
-    RasterPosition m_current_raster_position;
-
     float m_line_width { 1.0f };
 
     // Lighting configuration

+ 54 - 3
Userland/Libraries/LibSoftGPU/Device.cpp

@@ -82,7 +82,7 @@ static Vector4<f32x4> to_vec4(u32x4 rgba)
     };
 }
 
-static Gfx::IntRect window_coordinates_to_target_coordinates(Gfx::IntRect const& window_rect, Gfx::IntRect const& target_rect)
+static Gfx::IntRect window_coordinates_to_target_coordinates(Gfx::IntRect const window_rect, Gfx::IntRect const target_rect)
 {
     return {
         window_rect.x(),
@@ -977,15 +977,19 @@ void Device::clear_depth(float depth)
     m_depth_buffer->clear(depth);
 }
 
-void Device::blit(Gfx::Bitmap const& source, int x, int y)
+void Device::blit_to_color_buffer_at_raster_position(Gfx::Bitmap const& source)
 {
+    if (!m_raster_position.valid)
+        return;
+
     wait_for_all_threads();
 
     INCREASE_STATISTICS_COUNTER(g_num_pixels, source.width() * source.height());
     INCREASE_STATISTICS_COUNTER(g_num_pixels_shaded, source.width() * source.height());
 
     Gfx::Painter painter { *m_render_target };
-    painter.blit({ x, y }, source, source.rect(), 1.0f, true);
+    auto const blit_rect = raster_rect_in_target_coordinates(source.size());
+    painter.blit({ blit_rect.x(), blit_rect.y() }, source, source.rect(), 1.0f, true);
 }
 
 void Device::blit_to(Gfx::Bitmap& target)
@@ -1124,4 +1128,51 @@ void Device::set_material_state(unsigned int material_id, Material const& materi
     m_materials.at(material_id) = material;
 }
 
+void Device::set_raster_position(RasterPosition const& raster_position)
+{
+    m_raster_position = raster_position;
+}
+
+void Device::set_raster_position(FloatVector4 const& position, FloatMatrix4x4 const& model_view_transform, FloatMatrix4x4 const& projection_transform)
+{
+    auto const eye_coordinates = model_view_transform * position;
+    auto const clip_coordinates = projection_transform * eye_coordinates;
+
+    // FIXME: implement clipping
+    m_raster_position.valid = true;
+
+    auto ndc_coordinates = clip_coordinates / clip_coordinates.w();
+    ndc_coordinates.set_w(clip_coordinates.w());
+
+    auto const viewport = m_options.viewport;
+    auto const viewport_half_width = viewport.width() / 2.0f;
+    auto const viewport_half_height = viewport.height() / 2.0f;
+    auto const viewport_center_x = viewport.x() + viewport_half_width;
+    auto const viewport_center_y = viewport.y() + viewport_half_height;
+    auto const depth_half_range = (m_options.depth_max - m_options.depth_min) / 2;
+    auto const depth_halfway = (m_options.depth_min + m_options.depth_max) / 2;
+
+    // FIXME: implement other raster position properties such as color and texcoords
+
+    m_raster_position.window_coordinates = {
+        viewport_center_x + ndc_coordinates.x() * viewport_half_width,
+        viewport_center_y + ndc_coordinates.y() * viewport_half_height,
+        depth_halfway + ndc_coordinates.z() * depth_half_range,
+        ndc_coordinates.w(),
+    };
+
+    m_raster_position.eye_coordinate_distance = eye_coordinates.length();
+}
+
+Gfx::IntRect Device::raster_rect_in_target_coordinates(Gfx::IntSize size)
+{
+    auto const raster_rect = Gfx::IntRect {
+        static_cast<int>(m_raster_position.window_coordinates.x()),
+        static_cast<int>(m_raster_position.window_coordinates.y()),
+        size.width(),
+        size.height(),
+    };
+    return window_coordinates_to_target_coordinates(raster_rect, m_render_target->rect());
+}
+
 }

+ 16 - 1
Userland/Libraries/LibSoftGPU/Device.h

@@ -84,6 +84,15 @@ struct LightModelParameters {
 
 struct PixelQuad;
 
+struct RasterPosition {
+    FloatVector4 window_coordinates { 0.0f, 0.0f, 0.0f, 1.0f };
+    float eye_coordinate_distance { 0.0f };
+    bool valid { true };
+    FloatVector4 color_rgba { 1.0f, 1.0f, 1.0f, 1.0f };
+    float color_index { 1.0f };
+    FloatVector4 texture_coordinates { 0.0f, 0.0f, 0.0f, 1.0f };
+};
+
 class Device final {
 public:
     Device(const Gfx::IntSize& min_size);
@@ -94,8 +103,8 @@ public:
     void resize(const Gfx::IntSize& min_size);
     void clear_color(const FloatVector4&);
     void clear_depth(float);
-    void blit(Gfx::Bitmap const&, int x, int y);
     void blit_to(Gfx::Bitmap&);
+    void blit_to_color_buffer_at_raster_position(Gfx::Bitmap const&);
     void wait_for_all_threads() const;
     void set_options(const RasterizerOptions&);
     void set_light_model_params(const LightModelParameters&);
@@ -110,8 +119,13 @@ public:
     void set_light_state(unsigned, Light const&);
     void set_material_state(unsigned, Material const&);
 
+    RasterPosition raster_position() const { return m_raster_position; }
+    void set_raster_position(RasterPosition const& raster_position);
+    void set_raster_position(FloatVector4 const& position, FloatMatrix4x4 const& model_view_transform, FloatMatrix4x4 const& projection_transform);
+
 private:
     void draw_statistics_overlay(Gfx::Bitmap&);
+    Gfx::IntRect raster_rect_in_target_coordinates(Gfx::IntSize size);
 
     void rasterize_triangle(const Triangle& triangle);
     void setup_blend_factors();
@@ -132,6 +146,7 @@ private:
     AlphaBlendFactors m_alpha_blend_factors;
     Array<Light, NUM_LIGHTS> m_lights;
     Array<Material, 2u> m_materials;
+    RasterPosition m_raster_position;
 };
 
 }