Explorar o código

LibGPU+LibSoftGPU: Move size and pixel format information to GPU::Image

Size and format information are the same for every implementation and do
not need to be virtual. This removes the need to reimplement them for
each driver.
Stephan Unverwerth %!s(int64=2) %!d(string=hai) anos
pai
achega
3b2ded1d44

+ 1 - 0
Userland/Libraries/LibGPU/CMakeLists.txt

@@ -1,5 +1,6 @@
 set(SOURCES
     Driver.cpp
+    Image.cpp
 )
 
 serenity_lib(LibGPU gpu)

+ 32 - 0
Userland/Libraries/LibGPU/Image.cpp

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022, Stephan Unverwerth <s.unverwerth@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/Math.h>
+#include <LibGPU/Image.h>
+
+namespace GPU {
+
+Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format, u32 width, u32 height, u32 depth, u32 max_levels)
+    : m_ownership_token { ownership_token }
+    , m_pixel_format { pixel_format }
+{
+    VERIFY(width > 0);
+    VERIFY(height > 0);
+    VERIFY(depth > 0);
+    VERIFY(max_levels > 0);
+
+    u32 number_of_levels_in_full_chain = max(max(AK::log2(width), AK::log2(height)), AK::log2(depth)) + 1;
+    m_mipmap_sizes.resize(min(max_levels, number_of_levels_in_full_chain));
+
+    for (u32 level = 0; level < m_mipmap_sizes.size(); ++level) {
+        m_mipmap_sizes[level] = { width, height, depth };
+        width = max(width / 2, 1);
+        height = max(height / 2, 1);
+        depth = max(depth / 2, 1);
+    }
+}
+
+}

+ 11 - 9
Userland/Libraries/LibGPU/Image.h

@@ -8,24 +8,24 @@
 #pragma once
 
 #include <AK/RefCounted.h>
+#include <AK/Vector.h>
 #include <LibGPU/ImageDataLayout.h>
+#include <LibGPU/ImageFormat.h>
 #include <LibGfx/Vector3.h>
 
 namespace GPU {
 
 class Image : public RefCounted<Image> {
 public:
-    Image(void const* ownership_token)
-        : m_ownership_token { ownership_token }
-    {
-    }
-
+    Image(void const* ownership_token, PixelFormat const&, u32 width, u32 height, u32 depth, u32 max_levels);
     virtual ~Image() { }
 
-    virtual u32 width_at_level(u32 level) const = 0;
-    virtual u32 height_at_level(u32 level) const = 0;
-    virtual u32 depth_at_level(u32 level) const = 0;
-    virtual u32 number_of_levels() const = 0;
+    u32 width_at_level(u32 level) const { return m_mipmap_sizes[level].x(); }
+    u32 height_at_level(u32 level) const { return m_mipmap_sizes[level].y(); }
+    u32 depth_at_level(u32 level) const { return m_mipmap_sizes[level].z(); }
+    u32 number_of_levels() const { return m_mipmap_sizes.size(); }
+
+    PixelFormat pixel_format() const { return m_pixel_format; }
 
     virtual void regenerate_mipmaps() = 0;
 
@@ -38,6 +38,8 @@ public:
 
 private:
     void const* const m_ownership_token { nullptr };
+    Vector<Vector3<u32>> m_mipmap_sizes;
+    PixelFormat m_pixel_format;
 };
 
 }

+ 1 - 0
Userland/Libraries/LibSoftGPU/CMakeLists.txt

@@ -12,3 +12,4 @@ set(SOURCES
 add_compile_options(-Wno-psabi)
 serenity_lib(LibSoftGPU softgpu)
 target_link_libraries(LibSoftGPU PRIVATE LibCore LibGfx)
+target_sources(LibSoftGPU PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../LibGPU/Image.cpp")

+ 6 - 21
Userland/Libraries/LibSoftGPU/Image.cpp

@@ -14,9 +14,8 @@
 namespace SoftGPU {
 
 Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format, u32 width, u32 height, u32 depth, u32 max_levels)
-    : GPU::Image(ownership_token)
-    , m_pixel_format(pixel_format)
-    , m_mipmap_buffers(FixedArray<RefPtr<Typed3DBuffer<FloatVector4>>>::must_create_but_fixme_should_propagate_errors(max_levels))
+    : GPU::Image(ownership_token, pixel_format, width, height, depth, max_levels)
+    , m_mipmap_buffers(FixedArray<RefPtr<Typed3DBuffer<FloatVector4>>>::must_create_but_fixme_should_propagate_errors(number_of_levels()))
 {
     VERIFY(pixel_format == GPU::PixelFormat::Alpha
         || pixel_format == GPU::PixelFormat::Intensity
@@ -24,28 +23,14 @@ Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format,
         || pixel_format == GPU::PixelFormat::LuminanceAlpha
         || pixel_format == GPU::PixelFormat::RGB
         || pixel_format == GPU::PixelFormat::RGBA);
-    VERIFY(width > 0);
-    VERIFY(height > 0);
-    VERIFY(depth > 0);
-    VERIFY(max_levels > 0);
 
     m_width_is_power_of_two = is_power_of_two(width);
     m_height_is_power_of_two = is_power_of_two(height);
     m_depth_is_power_of_two = is_power_of_two(depth);
 
-    u32 level;
-    for (level = 0; level < max_levels; ++level) {
-        m_mipmap_buffers[level] = MUST(Typed3DBuffer<FloatVector4>::try_create(width, height, depth));
-
-        if (width <= 1 && height <= 1 && depth <= 1)
-            break;
-
-        width = max(width / 2, 1);
-        height = max(height / 2, 1);
-        depth = max(depth / 2, 1);
+    for (u32 level = 0; level < number_of_levels(); ++level) {
+        m_mipmap_buffers[level] = MUST(Typed3DBuffer<FloatVector4>::try_create(width_at_level(level), height_at_level(level), depth_at_level(level)));
     }
-
-    m_number_of_levels = level + 1;
 }
 
 GPU::ImageDataLayout Image::image_data_layout(u32 level, Vector3<i32> offset) const
@@ -86,7 +71,7 @@ void Image::write_texels(u32 level, Vector3<i32> const& output_offset, void cons
 
     PixelConverter converter { input_layout, output_layout };
     ErrorOr<void> conversion_result;
-    switch (m_pixel_format) {
+    switch (pixel_format()) {
     case GPU::PixelFormat::Luminance:
     case GPU::PixelFormat::RGB:
         // Both Luminance and RGB set the alpha to 1, regardless of the source texel
@@ -195,7 +180,7 @@ void Image::regenerate_mipmaps()
     };
 
     // For levels 1..number_of_levels-1, we generate downscaled versions of the level above
-    for (u32 level = 1; level < m_number_of_levels; ++level) {
+    for (u32 level = 1; level < number_of_levels(); ++level) {
         auto higher_level_bitmap = copy_image_into_bitmap(level - 1);
         auto current_level_bitmap = empty_bitmap_for_level(level);
 

+ 0 - 7
Userland/Libraries/LibSoftGPU/Image.h

@@ -22,10 +22,6 @@ class Image final : public GPU::Image {
 public:
     Image(void const* ownership_token, GPU::PixelFormat const&, u32 width, u32 height, u32 depth, u32 max_levels);
 
-    virtual u32 width_at_level(u32 level) const override { return m_mipmap_buffers[level]->width(); }
-    virtual u32 height_at_level(u32 level) const override { return m_mipmap_buffers[level]->height(); }
-    virtual u32 depth_at_level(u32 level) const override { return m_mipmap_buffers[level]->depth(); }
-    virtual u32 number_of_levels() const override { return m_number_of_levels; }
     bool width_is_power_of_two() const { return m_width_is_power_of_two; }
     bool height_is_power_of_two() const { return m_height_is_power_of_two; }
     bool depth_is_power_of_two() const { return m_depth_is_power_of_two; }
@@ -58,9 +54,6 @@ public:
     }
 
 private:
-    u32 m_number_of_levels { 0 };
-
-    GPU::PixelFormat m_pixel_format;
     FixedArray<RefPtr<Typed3DBuffer<FloatVector4>>> m_mipmap_buffers;
 
     bool m_width_is_power_of_two { false };