PixelConverter.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Array.h>
  7. #include <AK/Error.h>
  8. #include <AK/FloatingPoint.h>
  9. #include <LibSoftGPU/PixelConverter.h>
  10. namespace SoftGPU {
  11. template<typename T>
  12. static constexpr T reverse_component_bytes_if_needed(T value, GPU::ImageDataLayout const& image_data_layout)
  13. requires(sizeof(T) == 2 || sizeof(T) == 4)
  14. {
  15. if (image_data_layout.packing.component_bytes_order == GPU::ComponentBytesOrder::Normal)
  16. return value;
  17. VERIFY(image_data_layout.pixel_type.bits == GPU::PixelComponentBits::AllBits);
  18. auto* u8_ptr = reinterpret_cast<u8*>(&value);
  19. if constexpr (sizeof(T) == 2) {
  20. swap(u8_ptr[0], u8_ptr[1]);
  21. } else if constexpr (sizeof(T) == 4) {
  22. swap(u8_ptr[0], u8_ptr[3]);
  23. swap(u8_ptr[1], u8_ptr[2]);
  24. }
  25. return value;
  26. }
  27. static constexpr FloatVector4 decode_component_order_for_format(FloatVector4 const& components, GPU::PixelFormat format)
  28. {
  29. switch (format) {
  30. case GPU::PixelFormat::Alpha:
  31. return { 0.f, 0.f, 0.f, components[0] };
  32. case GPU::PixelFormat::BGR:
  33. return { components[2], components[1], components[0], 1.f };
  34. case GPU::PixelFormat::BGRA:
  35. return { components[2], components[1], components[0], components[3] };
  36. case GPU::PixelFormat::Blue:
  37. return { 0.f, 0.f, components[0], 1.f };
  38. case GPU::PixelFormat::ColorIndex:
  39. case GPU::PixelFormat::DepthComponent:
  40. case GPU::PixelFormat::StencilIndex:
  41. return { components[0], 0.f, 0.f, 0.f };
  42. case GPU::PixelFormat::Green:
  43. return { 0.f, components[0], 0.f, 1.f };
  44. case GPU::PixelFormat::Intensity:
  45. return { components[0], components[0], components[0], components[0] };
  46. case GPU::PixelFormat::Luminance:
  47. return { components[0], components[0], components[0], 1.f };
  48. case GPU::PixelFormat::LuminanceAlpha:
  49. return { components[0], components[0], components[0], components[1] };
  50. case GPU::PixelFormat::Red:
  51. return { components[0], 0.f, 0.f, 1.f };
  52. case GPU::PixelFormat::RGB:
  53. return { components[0], components[1], components[2], 1.f };
  54. case GPU::PixelFormat::RGBA:
  55. return components;
  56. }
  57. VERIFY_NOT_REACHED();
  58. }
  59. static constexpr FloatVector4 encode_component_order_for_format(FloatVector4 const& components, GPU::PixelFormat format)
  60. {
  61. switch (format) {
  62. case GPU::PixelFormat::Alpha:
  63. return { components[3], 0.f, 0.f, 0.f };
  64. case GPU::PixelFormat::BGR:
  65. return { components[2], components[1], components[0], 0.f };
  66. case GPU::PixelFormat::BGRA:
  67. return { components[2], components[1], components[0], components[3] };
  68. case GPU::PixelFormat::Blue:
  69. return { components[2], 0.f, 0.f, 0.f };
  70. case GPU::PixelFormat::ColorIndex:
  71. case GPU::PixelFormat::DepthComponent:
  72. case GPU::PixelFormat::Intensity:
  73. case GPU::PixelFormat::Luminance:
  74. case GPU::PixelFormat::Red:
  75. case GPU::PixelFormat::RGB:
  76. case GPU::PixelFormat::RGBA:
  77. case GPU::PixelFormat::StencilIndex:
  78. return components;
  79. case GPU::PixelFormat::Green:
  80. return { components[1], 0.f, 0.f, 0.f };
  81. case GPU::PixelFormat::LuminanceAlpha:
  82. return { components[0], components[3], 0.f, 0.f };
  83. }
  84. VERIFY_NOT_REACHED();
  85. }
  86. template<typename S, typename O>
  87. static int read_pixel_values(u8 const* input_data, Array<O, 4>& output_values, GPU::ImageDataLayout const& layout)
  88. {
  89. auto const& pixel_type = layout.pixel_type;
  90. auto const number_of_data_reads = GPU::number_of_components(pixel_type.format) / GPU::number_of_components(pixel_type.bits);
  91. for (int i = 0; i < number_of_data_reads; ++i) {
  92. auto storage_value = reinterpret_cast<S const*>(input_data)[i];
  93. if (layout.pixel_type.bits == GPU::PixelComponentBits::AllBits) {
  94. if constexpr (sizeof(S) == 2 || sizeof(S) == 4)
  95. storage_value = reverse_component_bytes_if_needed(storage_value, layout);
  96. }
  97. O value = storage_value;
  98. // Special case: convert HalfFloat to regular float
  99. if constexpr (IsSame<O, float>) {
  100. if (pixel_type.data_type == GPU::PixelDataType::HalfFloat)
  101. value = convert_to_native_float(FloatingPointBits<1, 5, 10>(storage_value));
  102. }
  103. output_values[i] = value;
  104. }
  105. return number_of_data_reads;
  106. }
  107. template<typename T>
  108. constexpr FloatVector4 extract_component_values(Span<T> data_values, GPU::PixelType const& pixel_type)
  109. {
  110. // FIXME: implement fixed point conversion for ::StencilIndex
  111. // FIXME: stencil components should account for GL_MAP_STENCIL
  112. // FIXME: stencil components should get GL_INDEX_SHIFT and GL_INDEX_OFFSET applied
  113. // FIXME: depth components should get GL_DEPTH_SCALE and GL_DEPTH_BIAS applied
  114. // FIXME: color components should get GL_C_SCALE and GL_C_BIAS applied
  115. auto const number_of_values = data_values.size();
  116. auto const bits_number_of_components = number_of_components(pixel_type.bits);
  117. VERIFY(bits_number_of_components == 1 || bits_number_of_components == number_of_components(pixel_type.format));
  118. // Maps a signed value to -1.0f..1.0f
  119. auto signed_to_float = [](T value) -> float {
  120. auto constexpr number_of_bits = sizeof(T) * 8 - 1;
  121. return max(static_cast<float>(value / static_cast<float>(1 << number_of_bits)), -1.f);
  122. };
  123. // Maps an unsigned value to 0.0f..1.0f
  124. auto unsigned_to_float = [](T value, u8 const number_of_bits) -> float {
  125. return static_cast<float>(value / static_cast<double>((1ull << number_of_bits) - 1));
  126. };
  127. // Handle full data values (1 or more)
  128. if (pixel_type.bits == GPU::PixelComponentBits::AllBits) {
  129. FloatVector4 components;
  130. for (size_t i = 0; i < number_of_values; ++i) {
  131. if constexpr (IsSigned<T>)
  132. components[i] = signed_to_float(data_values[i]);
  133. else
  134. components[i] = unsigned_to_float(data_values[i], sizeof(T) * 8);
  135. }
  136. return components;
  137. }
  138. VERIFY(number_of_values == 1);
  139. T const value = data_values[0];
  140. auto bitfields = pixel_component_bitfield_lengths(pixel_type.bits);
  141. // Map arbitrary bitfields to floats
  142. u8 remaining_width = 0;
  143. for (auto bitwidth : bitfields)
  144. remaining_width += bitwidth;
  145. // "By default the components are laid out from msb (most-significant bit) to lsb (least-significant bit)"
  146. FloatVector4 components;
  147. for (auto i = 0; i < 4; ++i) {
  148. auto bitwidth = bitfields[i];
  149. if (bitwidth == 0)
  150. break;
  151. remaining_width -= bitwidth;
  152. components[i] = unsigned_to_float((value >> remaining_width) & ((1 << bitwidth) - 1), bitwidth);
  153. }
  154. return components;
  155. }
  156. template<>
  157. constexpr FloatVector4 extract_component_values(Span<float> data_values, GPU::PixelType const&)
  158. {
  159. FloatVector4 components;
  160. for (size_t i = 0; i < data_values.size(); ++i)
  161. components[i] = data_values[i];
  162. return components;
  163. }
  164. template<typename T>
  165. static FloatVector4 pixel_values_to_components(Span<T> values, GPU::PixelType const& pixel_type)
  166. {
  167. // Deconstruct read value(s) into separate components
  168. auto components = extract_component_values(values, pixel_type);
  169. if (pixel_type.components_order == GPU::ComponentsOrder::Reversed)
  170. components = { components[3], components[2], components[1], components[0] };
  171. // Reconstruct component values in order
  172. auto component_values = decode_component_order_for_format(components, pixel_type.format);
  173. component_values.clamp(0.f, 1.f);
  174. return component_values;
  175. }
  176. FloatVector4 PixelConverter::read_pixel(u8 const** input_data)
  177. {
  178. auto read_components = [&]<typename S, typename O>() {
  179. Array<O, 4> values;
  180. auto number_of_values = read_pixel_values<S, O>(*input_data, values, m_input_specification);
  181. *input_data += number_of_values * sizeof(O);
  182. return pixel_values_to_components(values.span().trim(number_of_values), m_input_specification.pixel_type);
  183. };
  184. switch (m_input_specification.pixel_type.data_type) {
  185. case GPU::PixelDataType::Bitmap:
  186. VERIFY_NOT_REACHED();
  187. case GPU::PixelDataType::Byte:
  188. return read_components.template operator()<i8, i8>();
  189. case GPU::PixelDataType::Float:
  190. return read_components.template operator()<float, float>();
  191. case GPU::PixelDataType::HalfFloat:
  192. return read_components.template operator()<u16, float>();
  193. case GPU::PixelDataType::Int:
  194. return read_components.template operator()<i32, i32>();
  195. case GPU::PixelDataType::Short:
  196. return read_components.template operator()<i16, i16>();
  197. case GPU::PixelDataType::UnsignedByte:
  198. return read_components.template operator()<u8, u8>();
  199. case GPU::PixelDataType::UnsignedInt:
  200. return read_components.template operator()<u32, u32>();
  201. case GPU::PixelDataType::UnsignedShort:
  202. return read_components.template operator()<u16, u16>();
  203. }
  204. VERIFY_NOT_REACHED();
  205. }
  206. static constexpr void write_pixel_as_type(u8** output_data, float value, GPU::ImageDataLayout layout)
  207. {
  208. auto write_value = [&output_data, &layout]<typename T>(T value) -> void {
  209. if constexpr (sizeof(T) == 2 || sizeof(T) == 4)
  210. value = reverse_component_bytes_if_needed(value, layout);
  211. **reinterpret_cast<T**>(output_data) = value;
  212. (*output_data) += sizeof(T);
  213. };
  214. auto constexpr float_to_signed = []<typename T>(float value) -> T {
  215. auto const signed_max = 1ull << (sizeof(T) * 8 - 1);
  216. auto const unsigned_max = 2 * signed_max - 1;
  217. return round_to<T>((static_cast<double>(value) + 1.) / 2. * unsigned_max - signed_max);
  218. };
  219. auto constexpr float_to_unsigned = []<typename T>(float value) -> T {
  220. auto const unsigned_max = (1ull << (sizeof(T) * 8)) - 1;
  221. return round_to<T>(static_cast<double>(value) * unsigned_max);
  222. };
  223. switch (layout.pixel_type.data_type) {
  224. case GPU::PixelDataType::Bitmap:
  225. VERIFY_NOT_REACHED();
  226. case GPU::PixelDataType::Byte:
  227. write_value(float_to_signed.operator()<i8>(value));
  228. break;
  229. case GPU::PixelDataType::Float:
  230. write_value(value);
  231. break;
  232. case GPU::PixelDataType::HalfFloat:
  233. write_value(static_cast<u16>(convert_from_native_float<FloatingPointBits<1, 5, 10>>(value).bits()));
  234. break;
  235. case GPU::PixelDataType::Int:
  236. write_value(float_to_signed.operator()<i32>(value));
  237. break;
  238. case GPU::PixelDataType::Short:
  239. write_value(float_to_signed.operator()<i16>(value));
  240. break;
  241. case GPU::PixelDataType::UnsignedByte:
  242. write_value(float_to_unsigned.operator()<u8>(value));
  243. break;
  244. case GPU::PixelDataType::UnsignedInt:
  245. write_value(float_to_unsigned.operator()<u32>(value));
  246. break;
  247. case GPU::PixelDataType::UnsignedShort:
  248. write_value(float_to_unsigned.operator()<u16>(value));
  249. break;
  250. }
  251. }
  252. void constexpr write_pixel_as_bitfield(u8** output_data, FloatVector4 const& components, GPU::PixelType const& pixel_type)
  253. {
  254. auto constexpr float_to_unsigned = [](float value, u8 bits) {
  255. auto unsigned_max = (1ull << bits) - 1;
  256. return round_to<u64>(value * unsigned_max);
  257. };
  258. // Construct value with concatenated bitfields - first component has most significant bits
  259. auto bitfields = pixel_component_bitfield_lengths(pixel_type.bits);
  260. u64 value = 0;
  261. u8 bitsize = 0;
  262. for (auto i = 0; i < 4; ++i) {
  263. value <<= bitsize;
  264. bitsize = bitfields[i];
  265. if (bitsize == 0)
  266. break;
  267. value |= float_to_unsigned(components[i], bitsize);
  268. }
  269. // Write out the value in the requested data type
  270. auto write_value = [&output_data]<typename T>(T value) -> void {
  271. **reinterpret_cast<T**>(output_data) = value;
  272. (*output_data) += sizeof(T);
  273. };
  274. switch (pixel_type.data_type) {
  275. case GPU::PixelDataType::UnsignedByte:
  276. write_value.operator()<u8>(value);
  277. break;
  278. case GPU::PixelDataType::UnsignedInt:
  279. write_value.operator()<u32>(value);
  280. break;
  281. case GPU::PixelDataType::UnsignedShort:
  282. write_value.operator()<u16>(value);
  283. break;
  284. default:
  285. VERIFY_NOT_REACHED();
  286. }
  287. }
  288. void PixelConverter::write_pixel(u8** output_data, FloatVector4 const& components)
  289. {
  290. // NOTE: `components` is already clamped to 0.f..1.f
  291. // Reorder float components to data order
  292. auto const& pixel_type = m_output_specification.pixel_type;
  293. auto output_components = encode_component_order_for_format(components, pixel_type.format);
  294. if (pixel_type.components_order == GPU::ComponentsOrder::Reversed)
  295. output_components = { output_components[3], output_components[2], output_components[1], output_components[0] };
  296. // Write components as full data types
  297. auto const number_of_components_in_pixel = number_of_components(pixel_type.format);
  298. if (pixel_type.bits == GPU::PixelComponentBits::AllBits) {
  299. for (u8 i = 0; i < number_of_components_in_pixel; ++i)
  300. write_pixel_as_type(output_data, output_components[i], m_output_specification);
  301. return;
  302. }
  303. // Write components as a concatenated bitfield value
  304. VERIFY(number_of_components_in_pixel == number_of_components(pixel_type.bits));
  305. write_pixel_as_bitfield(output_data, output_components, pixel_type);
  306. }
  307. static constexpr GPU::ImageSelection restrain_selection_within_dimensions(GPU::ImageSelection selection, GPU::DimensionSpecification const& dimensions)
  308. {
  309. if (selection.offset_x < 0) {
  310. selection.width += selection.offset_x;
  311. selection.offset_x = 0;
  312. }
  313. if (selection.offset_y < 0) {
  314. selection.height += selection.offset_y;
  315. selection.offset_y = 0;
  316. }
  317. if (selection.offset_z < 0) {
  318. selection.depth += selection.offset_z;
  319. selection.offset_z = 0;
  320. }
  321. if (selection.offset_x + selection.width > dimensions.width)
  322. selection.width = dimensions.width - selection.offset_x;
  323. if (selection.offset_y + selection.height > dimensions.height)
  324. selection.height = dimensions.height - selection.offset_y;
  325. if (selection.offset_z + selection.depth > dimensions.depth)
  326. selection.depth = dimensions.depth - selection.offset_z;
  327. return selection;
  328. }
  329. ErrorOr<void> PixelConverter::convert(void const* input_data, void* output_data, Function<void(FloatVector4&)> transform)
  330. {
  331. // Verify pixel data specifications
  332. auto validate_image_data_layout = [](GPU::ImageDataLayout const& specification) -> ErrorOr<void> {
  333. if (specification.packing.row_stride > 0
  334. && specification.dimensions.width > specification.packing.row_stride)
  335. return Error::from_string_view("Width exceeds the row stride"sv);
  336. if (specification.packing.depth_stride > 0
  337. && specification.dimensions.height > specification.packing.depth_stride)
  338. return Error::from_string_view("Height exceeds the depth stride"sv);
  339. // NOTE: GL_BITMAP is removed from current OpenGL specs. Since it is largely unsupported and it
  340. // requires extra logic (i.e. 8 vs. 1 pixel packing/unpacking), we also do not support it.
  341. if (specification.pixel_type.data_type == GPU::PixelDataType::Bitmap)
  342. return Error::from_string_view("Bitmap is unsupported"sv);
  343. return {};
  344. };
  345. TRY(validate_image_data_layout(m_input_specification));
  346. TRY(validate_image_data_layout(m_output_specification));
  347. // Restrain input and output selection:
  348. // - selection dimensions should be equal
  349. // - selection offsets cannot be negative
  350. // - selection bounds cannot exceed the image dimensions
  351. auto const& input_dimensions = m_input_specification.dimensions;
  352. auto const& output_dimensions = m_output_specification.dimensions;
  353. auto input_selection = restrain_selection_within_dimensions(m_input_specification.selection, input_dimensions);
  354. auto const& output_selection = restrain_selection_within_dimensions(m_output_specification.selection, output_dimensions);
  355. input_selection.width = min(input_selection.width, output_selection.width);
  356. input_selection.height = min(input_selection.height, output_selection.height);
  357. input_selection.depth = min(input_selection.depth, output_selection.depth);
  358. // Set up copy parameters
  359. auto const& input_packing = m_input_specification.packing;
  360. auto const input_pixels_per_row = input_packing.row_stride > 0 ? input_packing.row_stride : input_dimensions.width;
  361. auto const input_pixel_size_in_bytes = pixel_size_in_bytes(m_input_specification.pixel_type);
  362. auto const input_row_width_bytes = input_pixels_per_row * input_pixel_size_in_bytes;
  363. auto const input_byte_alignment = input_packing.byte_alignment;
  364. auto const input_row_stride = input_row_width_bytes + (input_byte_alignment - input_row_width_bytes % input_byte_alignment) % input_byte_alignment;
  365. auto const input_rows_per_image = input_packing.depth_stride > 0 ? input_packing.depth_stride : input_dimensions.height;
  366. auto const input_depth_stride = input_rows_per_image * input_row_stride;
  367. auto const& output_packing = m_output_specification.packing;
  368. auto const output_pixels_per_row = output_packing.row_stride > 0 ? output_packing.row_stride : output_dimensions.width;
  369. auto const output_pixel_size_in_bytes = pixel_size_in_bytes(m_output_specification.pixel_type);
  370. auto const output_row_width_bytes = output_pixels_per_row * output_pixel_size_in_bytes;
  371. auto const output_byte_alignment = output_packing.byte_alignment;
  372. auto const output_row_stride = output_row_width_bytes + (output_byte_alignment - output_row_width_bytes % output_byte_alignment) % output_byte_alignment;
  373. auto const output_rows_per_image = output_packing.depth_stride > 0 ? output_packing.depth_stride : output_dimensions.height;
  374. auto const output_depth_stride = output_rows_per_image * output_row_stride;
  375. // Copy all pixels from input to output
  376. auto input_bytes = reinterpret_cast<u8 const*>(input_data);
  377. auto output_bytes = reinterpret_cast<u8*>(output_data);
  378. auto output_z = output_selection.offset_z;
  379. for (u32 input_z = input_selection.offset_z; input_z < input_selection.offset_z + input_selection.depth; ++input_z) {
  380. auto output_y = output_selection.offset_y;
  381. for (u32 input_y = input_selection.offset_y; input_y < input_selection.offset_y + input_selection.height; ++input_y) {
  382. auto const* input_scanline = &input_bytes[input_z * input_depth_stride
  383. + input_y * input_row_stride
  384. + input_selection.offset_x * input_pixel_size_in_bytes];
  385. auto* output_scanline = &output_bytes[output_z * output_depth_stride
  386. + output_y * output_row_stride
  387. + output_selection.offset_x * output_pixel_size_in_bytes];
  388. for (u32 input_x = input_selection.offset_x; input_x < input_selection.offset_x + input_selection.width; ++input_x) {
  389. auto pixel_components = read_pixel(&input_scanline);
  390. if (transform)
  391. transform(pixel_components);
  392. write_pixel(&output_scanline, pixel_components);
  393. }
  394. ++output_y;
  395. }
  396. ++output_z;
  397. }
  398. return {};
  399. }
  400. }