From 3b2ded1d4405fc51acb8bbbd24e06cf00198dac8 Mon Sep 17 00:00:00 2001 From: Stephan Unverwerth Date: Mon, 19 Dec 2022 14:25:17 +0100 Subject: [PATCH] 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. --- Userland/Libraries/LibGPU/CMakeLists.txt | 1 + Userland/Libraries/LibGPU/Image.cpp | 32 ++++++++++++++++++++ Userland/Libraries/LibGPU/Image.h | 20 ++++++------ Userland/Libraries/LibSoftGPU/CMakeLists.txt | 1 + Userland/Libraries/LibSoftGPU/Image.cpp | 27 ++++------------- Userland/Libraries/LibSoftGPU/Image.h | 7 ----- 6 files changed, 51 insertions(+), 37 deletions(-) create mode 100644 Userland/Libraries/LibGPU/Image.cpp diff --git a/Userland/Libraries/LibGPU/CMakeLists.txt b/Userland/Libraries/LibGPU/CMakeLists.txt index 030c5b2f861..cf4fdbd1f1f 100644 --- a/Userland/Libraries/LibGPU/CMakeLists.txt +++ b/Userland/Libraries/LibGPU/CMakeLists.txt @@ -1,5 +1,6 @@ set(SOURCES Driver.cpp + Image.cpp ) serenity_lib(LibGPU gpu) diff --git a/Userland/Libraries/LibGPU/Image.cpp b/Userland/Libraries/LibGPU/Image.cpp new file mode 100644 index 00000000000..62106ccbdfc --- /dev/null +++ b/Userland/Libraries/LibGPU/Image.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022, Stephan Unverwerth + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +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); + } +} + +} diff --git a/Userland/Libraries/LibGPU/Image.h b/Userland/Libraries/LibGPU/Image.h index aed3f581c46..25096990d3b 100644 --- a/Userland/Libraries/LibGPU/Image.h +++ b/Userland/Libraries/LibGPU/Image.h @@ -8,24 +8,24 @@ #pragma once #include +#include #include +#include #include namespace GPU { class Image : public RefCounted { 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> m_mipmap_sizes; + PixelFormat m_pixel_format; }; } diff --git a/Userland/Libraries/LibSoftGPU/CMakeLists.txt b/Userland/Libraries/LibSoftGPU/CMakeLists.txt index e434a1bcf12..e02993798cc 100644 --- a/Userland/Libraries/LibSoftGPU/CMakeLists.txt +++ b/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") diff --git a/Userland/Libraries/LibSoftGPU/Image.cpp b/Userland/Libraries/LibSoftGPU/Image.cpp index 5bf44794ce0..b96fc9b363d 100644 --- a/Userland/Libraries/LibSoftGPU/Image.cpp +++ b/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>>::must_create_but_fixme_should_propagate_errors(max_levels)) + : GPU::Image(ownership_token, pixel_format, width, height, depth, max_levels) + , m_mipmap_buffers(FixedArray>>::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::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::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 offset) const @@ -86,7 +71,7 @@ void Image::write_texels(u32 level, Vector3 const& output_offset, void cons PixelConverter converter { input_layout, output_layout }; ErrorOr 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); diff --git a/Userland/Libraries/LibSoftGPU/Image.h b/Userland/Libraries/LibSoftGPU/Image.h index 85fc2adacac..7bd807de3e4 100644 --- a/Userland/Libraries/LibSoftGPU/Image.h +++ b/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>> m_mipmap_buffers; bool m_width_is_power_of_two { false };