Image.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
  3. * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibGfx/Bitmap.h>
  8. #include <LibGfx/Painter.h>
  9. #include <LibGfx/Size.h>
  10. #include <LibSoftGPU/Image.h>
  11. #include <LibSoftGPU/PixelConverter.h>
  12. namespace SoftGPU {
  13. Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format, u32 width, u32 height, u32 depth, u32 max_levels)
  14. : GPU::Image(ownership_token, pixel_format, width, height, depth, max_levels)
  15. , m_mipmap_buffers(FixedArray<RefPtr<Typed3DBuffer<FloatVector4>>>::must_create_but_fixme_should_propagate_errors(number_of_levels()))
  16. {
  17. VERIFY(pixel_format == GPU::PixelFormat::Alpha
  18. || pixel_format == GPU::PixelFormat::Intensity
  19. || pixel_format == GPU::PixelFormat::Luminance
  20. || pixel_format == GPU::PixelFormat::LuminanceAlpha
  21. || pixel_format == GPU::PixelFormat::RGB
  22. || pixel_format == GPU::PixelFormat::RGBA);
  23. m_width_is_power_of_two = is_power_of_two(width);
  24. m_height_is_power_of_two = is_power_of_two(height);
  25. m_depth_is_power_of_two = is_power_of_two(depth);
  26. for (u32 level = 0; level < number_of_levels(); ++level) {
  27. m_mipmap_buffers[level] = MUST(Typed3DBuffer<FloatVector4>::try_create(width_at_level(level), height_at_level(level), depth_at_level(level)));
  28. }
  29. }
  30. GPU::ImageDataLayout Image::image_data_layout(u32 level, Vector3<i32> offset) const
  31. {
  32. auto const width = width_at_level(level);
  33. auto const height = height_at_level(level);
  34. auto const depth = depth_at_level(level);
  35. // FIXME: we are directly writing to FloatVector4s. We should probably find a better way to do this
  36. return {
  37. .pixel_type = {
  38. .format = GPU::PixelFormat::RGBA,
  39. .bits = GPU::PixelComponentBits::AllBits,
  40. .data_type = GPU::PixelDataType::Float,
  41. },
  42. .dimensions = {
  43. .width = width,
  44. .height = height,
  45. .depth = depth,
  46. },
  47. .selection = {
  48. .offset_x = offset.x(),
  49. .offset_y = offset.y(),
  50. .offset_z = offset.z(),
  51. .width = width - offset.x(),
  52. .height = height - offset.y(),
  53. .depth = depth - offset.z(),
  54. },
  55. };
  56. }
  57. void Image::write_texels(u32 level, Vector3<i32> const& output_offset, void const* input_data, GPU::ImageDataLayout const& input_layout)
  58. {
  59. VERIFY(level < number_of_levels());
  60. auto output_layout = image_data_layout(level, output_offset);
  61. auto texel_data = texel_pointer(level, 0, 0, 0);
  62. PixelConverter converter { input_layout, output_layout };
  63. ErrorOr<void> conversion_result;
  64. switch (pixel_format()) {
  65. case GPU::PixelFormat::Luminance:
  66. case GPU::PixelFormat::RGB:
  67. // Both Luminance and RGB set the alpha to 1, regardless of the source texel
  68. conversion_result = converter.convert(input_data, texel_data, [](auto& components) { components[3] = 1.f; });
  69. break;
  70. default:
  71. conversion_result = converter.convert(input_data, texel_data, {});
  72. }
  73. if (conversion_result.is_error())
  74. dbgln("Pixel conversion failed: {}", conversion_result.error().string_literal());
  75. }
  76. void Image::read_texels(u32 level, Vector3<i32> const& input_offset, void* output_data, GPU::ImageDataLayout const& output_layout) const
  77. {
  78. VERIFY(level < number_of_levels());
  79. auto input_layout = image_data_layout(level, input_offset);
  80. PixelConverter converter { input_layout, output_layout };
  81. auto conversion_result = converter.convert(texel_pointer(level, 0, 0, 0), output_data, {});
  82. if (conversion_result.is_error())
  83. dbgln("Pixel conversion failed: {}", conversion_result.error().string_literal());
  84. }
  85. void Image::copy_texels(GPU::Image const& source, u32 source_level, Vector3<u32> const& source_offset, Vector3<u32> const& size, u32 destination_level, Vector3<u32> const& destination_offset)
  86. {
  87. VERIFY(source.has_same_ownership_token(*this));
  88. auto const& src_image = static_cast<Image const&>(source);
  89. VERIFY(source_level < src_image.number_of_levels());
  90. VERIFY(source_offset.x() + size.x() <= src_image.width_at_level(source_level));
  91. VERIFY(source_offset.y() + size.y() <= src_image.height_at_level(source_level));
  92. VERIFY(source_offset.z() + size.z() <= src_image.depth_at_level(source_level));
  93. VERIFY(destination_level < number_of_levels());
  94. VERIFY(destination_offset.x() + size.x() <= width_at_level(destination_level));
  95. VERIFY(destination_offset.y() + size.y() <= height_at_level(destination_level));
  96. VERIFY(destination_offset.z() + size.z() <= depth_at_level(destination_level));
  97. for (u32 z = 0; z < size.z(); ++z) {
  98. for (u32 y = 0; y < size.y(); ++y) {
  99. for (u32 x = 0; x < size.x(); ++x) {
  100. auto const& color = src_image.texel(source_level, source_offset.x() + x, source_offset.y() + y, source_offset.z() + z);
  101. set_texel(destination_level, destination_offset.x() + x, destination_offset.y() + y, destination_offset.z() + z, color);
  102. }
  103. }
  104. }
  105. }
  106. static GPU::ImageDataLayout image_data_layout_for_bitmap(Gfx::Bitmap& bitmap)
  107. {
  108. VERIFY(bitmap.format() == Gfx::BitmapFormat::BGRA8888);
  109. return GPU::ImageDataLayout {
  110. .pixel_type = {
  111. .format = GPU::PixelFormat::BGRA,
  112. .bits = GPU::PixelComponentBits::B8_8_8_8,
  113. .data_type = GPU::PixelDataType::UnsignedInt,
  114. .components_order = GPU::ComponentsOrder::Reversed,
  115. },
  116. .dimensions = {
  117. .width = static_cast<u32>(bitmap.width()),
  118. .height = static_cast<u32>(bitmap.height()),
  119. .depth = 1,
  120. },
  121. .selection = {
  122. .width = static_cast<u32>(bitmap.width()),
  123. .height = static_cast<u32>(bitmap.height()),
  124. .depth = 1,
  125. },
  126. };
  127. }
  128. void Image::regenerate_mipmaps()
  129. {
  130. // FIXME: currently this only works for 2D Images
  131. VERIFY(depth_at_level(0) == 1);
  132. auto empty_bitmap_for_level = [&](u32 level) -> NonnullRefPtr<Gfx::Bitmap> {
  133. Gfx::IntSize size = { width_at_level(level), height_at_level(level) };
  134. return MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, size));
  135. };
  136. auto copy_image_into_bitmap = [&](u32 level) -> NonnullRefPtr<Gfx::Bitmap> {
  137. auto bitmap = empty_bitmap_for_level(level);
  138. auto input_layout = image_data_layout(level, { 0, 0, 0 });
  139. auto const* input_data = texel_pointer(level, 0, 0, 0);
  140. auto output_layout = image_data_layout_for_bitmap(bitmap);
  141. auto* output_data = bitmap->scanline(0);
  142. PixelConverter converter { input_layout, output_layout };
  143. MUST(converter.convert(input_data, output_data, {}));
  144. return bitmap;
  145. };
  146. auto copy_bitmap_into_level = [&](NonnullRefPtr<Gfx::Bitmap> bitmap, u32 level) {
  147. VERIFY(level >= 1);
  148. auto input_layout = image_data_layout_for_bitmap(bitmap);
  149. auto const* input_data = bitmap->scanline(0);
  150. auto output_layout = image_data_layout(level, { 0, 0, 0 });
  151. auto* output_data = texel_pointer(level, 0, 0, 0);
  152. PixelConverter converter { input_layout, output_layout };
  153. MUST(converter.convert(input_data, output_data, {}));
  154. };
  155. // For levels 1..number_of_levels-1, we generate downscaled versions of the level above
  156. for (u32 level = 1; level < number_of_levels(); ++level) {
  157. auto higher_level_bitmap = copy_image_into_bitmap(level - 1);
  158. auto current_level_bitmap = empty_bitmap_for_level(level);
  159. Gfx::Painter current_level_painter { current_level_bitmap };
  160. current_level_painter.draw_scaled_bitmap(
  161. current_level_bitmap->rect(),
  162. higher_level_bitmap,
  163. higher_level_bitmap->rect(),
  164. 1.f,
  165. Gfx::Painter::ScalingMode::BilinearBlend);
  166. copy_bitmap_into_level(current_level_bitmap, level);
  167. }
  168. }
  169. }