Image.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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 <LibSoftGPU/Image.h>
  8. #include <LibSoftGPU/PixelConverter.h>
  9. namespace SoftGPU {
  10. Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format, u32 width, u32 height, u32 depth, u32 max_levels)
  11. : GPU::Image(ownership_token)
  12. , m_pixel_format(pixel_format)
  13. , m_mipmap_buffers(FixedArray<RefPtr<Typed3DBuffer<FloatVector4>>>::must_create_but_fixme_should_propagate_errors(max_levels))
  14. {
  15. VERIFY(pixel_format == GPU::PixelFormat::Alpha
  16. || pixel_format == GPU::PixelFormat::Intensity
  17. || pixel_format == GPU::PixelFormat::Luminance
  18. || pixel_format == GPU::PixelFormat::LuminanceAlpha
  19. || pixel_format == GPU::PixelFormat::RGB
  20. || pixel_format == GPU::PixelFormat::RGBA);
  21. VERIFY(width > 0);
  22. VERIFY(height > 0);
  23. VERIFY(depth > 0);
  24. VERIFY(max_levels > 0);
  25. m_width_is_power_of_two = is_power_of_two(width);
  26. m_height_is_power_of_two = is_power_of_two(height);
  27. m_depth_is_power_of_two = is_power_of_two(depth);
  28. u32 level;
  29. for (level = 0; level < max_levels; ++level) {
  30. m_mipmap_buffers[level] = MUST(Typed3DBuffer<FloatVector4>::try_create(width, height, depth));
  31. if (width <= 1 && height <= 1 && depth <= 1)
  32. break;
  33. width = max(width / 2, 1);
  34. height = max(height / 2, 1);
  35. depth = max(depth / 2, 1);
  36. }
  37. m_num_levels = level + 1;
  38. }
  39. GPU::ImageDataLayout Image::image_data_layout(u32 level, Vector3<i32> offset) const
  40. {
  41. auto const width = level_width(level);
  42. auto const height = level_height(level);
  43. auto const depth = level_depth(level);
  44. // FIXME: we are directly writing to FloatVector4s. We should probably find a better way to do this
  45. return {
  46. .pixel_type = {
  47. .format = GPU::PixelFormat::RGBA,
  48. .bits = GPU::PixelComponentBits::AllBits,
  49. .data_type = GPU::PixelDataType::Float,
  50. },
  51. .dimensions = {
  52. .width = width,
  53. .height = height,
  54. .depth = depth,
  55. },
  56. .selection = {
  57. .offset_x = offset.x(),
  58. .offset_y = offset.y(),
  59. .offset_z = offset.z(),
  60. .width = width - offset.x(),
  61. .height = height - offset.y(),
  62. .depth = depth - offset.z(),
  63. },
  64. };
  65. }
  66. void Image::write_texels(u32 level, Vector3<i32> const& output_offset, void const* input_data, GPU::ImageDataLayout const& input_layout)
  67. {
  68. VERIFY(level < num_levels());
  69. auto output_layout = image_data_layout(level, output_offset);
  70. auto texel_data = texel_pointer(level, 0, 0, 0);
  71. PixelConverter converter { input_layout, output_layout };
  72. ErrorOr<void> conversion_result;
  73. switch (m_pixel_format) {
  74. case GPU::PixelFormat::Luminance:
  75. case GPU::PixelFormat::RGB:
  76. // Both Luminance and RGB set the alpha to 1, regardless of the source texel
  77. conversion_result = converter.convert(input_data, texel_data, [](auto& components) { components[3] = 1.f; });
  78. break;
  79. default:
  80. conversion_result = converter.convert(input_data, texel_data, {});
  81. }
  82. if (conversion_result.is_error())
  83. dbgln("Pixel conversion failed: {}", conversion_result.error().string_literal());
  84. }
  85. void Image::read_texels(u32 level, Vector3<i32> const& input_offset, void* output_data, GPU::ImageDataLayout const& output_layout) const
  86. {
  87. VERIFY(level < num_levels());
  88. auto input_layout = image_data_layout(level, input_offset);
  89. PixelConverter converter { input_layout, output_layout };
  90. auto conversion_result = converter.convert(texel_pointer(level, 0, 0, 0), output_data, {});
  91. if (conversion_result.is_error())
  92. dbgln("Pixel conversion failed: {}", conversion_result.error().string_literal());
  93. }
  94. 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)
  95. {
  96. VERIFY(source.has_same_ownership_token(*this));
  97. auto const& src_image = static_cast<Image const&>(source);
  98. VERIFY(source_level < src_image.num_levels());
  99. VERIFY(source_offset.x() + size.x() <= src_image.level_width(source_level));
  100. VERIFY(source_offset.y() + size.y() <= src_image.level_height(source_level));
  101. VERIFY(source_offset.z() + size.z() <= src_image.level_depth(source_level));
  102. VERIFY(destination_level < num_levels());
  103. VERIFY(destination_offset.x() + size.x() <= level_width(destination_level));
  104. VERIFY(destination_offset.y() + size.y() <= level_height(destination_level));
  105. VERIFY(destination_offset.z() + size.z() <= level_depth(destination_level));
  106. for (u32 z = 0; z < size.z(); ++z) {
  107. for (u32 y = 0; y < size.y(); ++y) {
  108. for (u32 x = 0; x < size.x(); ++x) {
  109. auto color = src_image.texel(source_level, source_offset.x() + x, source_offset.y() + y, source_offset.z() + z);
  110. set_texel(destination_level, destination_offset.x() + x, destination_offset.y() + y, destination_offset.z() + z, color);
  111. }
  112. }
  113. }
  114. }
  115. }