💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
9.0 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_GL_IMAGE_HPP
  20. #define ANTKEEPER_GL_IMAGE_HPP
  21. #include <engine/gl/format.hpp>
  22. #include <engine/gl/image-flag.hpp>
  23. #include <array>
  24. #include <cstddef>
  25. #include <cstdint>
  26. #include <limits>
  27. #include <span>
  28. namespace gl {
  29. /**
  30. *
  31. */
  32. class image
  33. {
  34. public:
  35. /// Destructs an image.
  36. virtual ~image() = 0;
  37. image(const image&) = delete;
  38. image(image&&) = delete;
  39. image& operator=(const image&) = delete;
  40. image& operator=(image&&) = delete;
  41. /**
  42. * Reads pixel data from the image.
  43. *
  44. * @param mip_level Level-of-detail number. Level `0` is the base image level. Level `n` is the nth mipmap reduction image.
  45. * @param offset_x Texel offset in the X-direction.
  46. * @param offset_y Texel offset in the Y-direction.
  47. * @param offset_z Texel offset in the Z-direction.
  48. * @param width Width of the subimage.
  49. * @param height Height of the subimage.
  50. * @param depth Depth of the subimage.
  51. * @param format Format of the image data.
  52. * @param data Buffer into which image data will be read.
  53. *
  54. * @except std::out_of_range Image read operation mip level out of range.
  55. * @except std::invalid_argument Image read operation used unsupported format.
  56. */
  57. void read
  58. (
  59. std::uint32_t mip_level,
  60. std::uint32_t offset_x,
  61. std::uint32_t offset_y,
  62. std::uint32_t offset_z,
  63. std::uint32_t width,
  64. std::uint32_t height,
  65. std::uint32_t depth,
  66. gl::format format,
  67. std::span<std::byte> data
  68. ) const;
  69. /**
  70. * Writes pixel data to the image.
  71. *
  72. * @param mip_level Level-of-detail number. Level `0` is the base image level. Level `n` is the nth mipmap reduction image.
  73. * @param offset_x Texel offset in the X-direction.
  74. * @param offset_y Texel offset in the Y-direction.
  75. * @param offset_z Texel offset in the Z-direction.
  76. * @param width Width of the subimage.
  77. * @param height Height of the subimage.
  78. * @param depth Depth of the subimage.
  79. * @param format Format of the image data.
  80. * @param data Image data to write.
  81. *
  82. * @except std::out_of_range Image write operation mip level out of range.
  83. * @except std::invalid_argument Image write operation used unsupported format.
  84. * @except std::out_of_range Image write operation exceeded image bounds.
  85. */
  86. void write
  87. (
  88. std::uint32_t mip_level,
  89. std::uint32_t offset_x,
  90. std::uint32_t offset_y,
  91. std::uint32_t offset_z,
  92. std::uint32_t width,
  93. std::uint32_t height,
  94. std::uint32_t depth,
  95. gl::format format,
  96. std::span<const std::byte> data
  97. );
  98. /**
  99. * Copies pixel data from this image into another the image.
  100. *
  101. * @param src_mip_level Source image level-of-detail number. Level `0` is the base image level. Level `n` is the nth mipmap reduction image.
  102. * @param src_x Source image texel offset in the X-direction.
  103. * @param src_y Source image texel offset in the Y-direction.
  104. * @param src_z Source image texel offset in the Z-direction.
  105. * @param dst_image Destination image.
  106. * @param dst_mip_level Destination image level-of-detail number. Level `0` is the base image level. Level `n` is the nth mipmap reduction image.
  107. * @param dst_x Destination image texel offset in the X-direction.
  108. * @param dst_y Destination image texel offset in the Y-direction.
  109. * @param dst_z Destination image texel offset in the Z-direction.
  110. * @param width Width of the subimage to copy.
  111. * @param height Height of the subimage to copy.
  112. * @param depth Depth of the subimage to copy.
  113. */
  114. void copy
  115. (
  116. std::uint32_t src_mip_level,
  117. std::uint32_t src_x,
  118. std::uint32_t src_y,
  119. std::uint32_t src_z,
  120. image& dst_image,
  121. std::uint32_t dst_mip_level,
  122. std::uint32_t dst_x,
  123. std::uint32_t dst_y,
  124. std::uint32_t dst_z,
  125. std::uint32_t width,
  126. std::uint32_t height,
  127. std::uint32_t depth
  128. ) const;
  129. /**
  130. * Generates mip subimages.
  131. */
  132. void generate_mipmaps();
  133. /// Returns the dimensionality of the image.
  134. [[nodiscard]] inline constexpr std::uint8_t get_dimensionality() const noexcept
  135. {
  136. return m_dimensionality;
  137. }
  138. /// Returns `true` if the image is 1D, `false` otherwise.
  139. [[nodiscard]] inline constexpr bool is_1d() const noexcept
  140. {
  141. return m_dimensionality == 1;
  142. }
  143. /// Returns `true` if the image is 2D, `false` otherwise.
  144. [[nodiscard]] inline constexpr bool is_2d() const noexcept
  145. {
  146. return m_dimensionality == 2;
  147. }
  148. /// Returns `true` if the image is 3D, `false` otherwise.
  149. [[nodiscard]] inline constexpr bool is_3d() const noexcept
  150. {
  151. return m_dimensionality == 3;
  152. }
  153. /// Returns the format and type of the texel blocks contained in the image.
  154. [[nodiscard]] inline constexpr format get_format() const noexcept
  155. {
  156. return m_format;
  157. }
  158. /// Returns the dimensions of the image.
  159. [[nodiscard]] inline constexpr const std::array<std::uint32_t, 3>& get_dimensions() const noexcept
  160. {
  161. return m_dimensions;
  162. }
  163. /// Returns the number of levels of detail available for minified sampling of the image.
  164. [[nodiscard]] inline constexpr std::uint32_t get_mip_levels() const noexcept
  165. {
  166. return m_mip_levels;
  167. }
  168. /// Returns the number of layers in the image.
  169. [[nodiscard]] inline constexpr std::uint32_t get_array_layers() const noexcept
  170. {
  171. return m_array_layers;
  172. }
  173. /// Returns the image flags.
  174. [[nodiscard]] inline constexpr std::uint8_t get_flags() const noexcept
  175. {
  176. return m_flags;
  177. }
  178. /// Returns `true` if the image is cube map compatible, `false` otherwise.
  179. [[nodiscard]] inline constexpr bool is_cube_compatible() const noexcept
  180. {
  181. return m_flags & std::to_underlying(image_flag::cube_compatible);
  182. }
  183. protected:
  184. /**
  185. * Constructs an image.
  186. *
  187. * @param dimensionality Image dimensionality, on `[1, 3]`.
  188. * @param format Format and type of the texel blocks that will be contained in the image.
  189. * @param width Width of the image.
  190. * @param height Height of the image.
  191. * @param depth Depth of the image.
  192. * @param mip_levels Number of levels of detail available for minified sampling of the image.
  193. * @param array_layers Number of layers in the image.
  194. * @param flags Image flags.
  195. *
  196. * @except std::invalid_argument Image constructed with unsupported format.
  197. * @except std::invalid_argument Image dimensions must be nonzero.
  198. * @except std::invalid_argument Image mip levels must be nonzero.
  199. * @except std::out_of_range Image mip levels exceed `1 + log2(max(width, height, depth))`.
  200. * @except std::invalid_argument Image array layers must be nonzero.
  201. * @except std::invalid_argument 1D image must have a height and depth of `1`.
  202. * @except std::invalid_argument 2D image must have a depth of `1`.
  203. * @except std::invalid_argument 3D image arrays not supported.
  204. * @except std::invalid_argument Cube compatible image must be 2D.
  205. * @except std::invalid_argument Cube compatible image width and height must be equal.
  206. * @except std::invalid_argument Cube compatible image array layers must be a multiple of 6.
  207. */
  208. image
  209. (
  210. std::uint8_t dimensionality,
  211. gl::format format,
  212. std::uint32_t width,
  213. std::uint32_t height,
  214. std::uint32_t depth,
  215. std::uint32_t mip_levels,
  216. std::uint32_t array_layers,
  217. std::uint32_t flags
  218. );
  219. private:
  220. unsigned int m_gl_texture_target{0};
  221. unsigned int m_gl_texture_name{0};
  222. std::uint8_t m_dimensionality{0};
  223. format m_format{format::undefined};
  224. std::array<std::uint32_t, 3> m_dimensions{0, 0, 0};
  225. std::uint32_t m_mip_levels{0};
  226. std::uint32_t m_array_layers{0};
  227. std::uint8_t m_flags{0};
  228. friend class image_view;
  229. };
  230. /**
  231. * 1D image.
  232. */
  233. class image_1d: public image
  234. {
  235. public:
  236. /// @copydoc image::image
  237. image_1d
  238. (
  239. gl::format format,
  240. std::uint32_t width,
  241. std::uint32_t mip_levels = 1,
  242. std::uint32_t array_layers = 1,
  243. std::uint32_t flags = 0
  244. );
  245. };
  246. /**
  247. * 2D image.
  248. */
  249. class image_2d: public image
  250. {
  251. public:
  252. /// @copydoc image::image
  253. image_2d
  254. (
  255. gl::format format,
  256. std::uint32_t width,
  257. std::uint32_t height,
  258. std::uint32_t mip_levels = 1,
  259. std::uint32_t array_layers = 1,
  260. std::uint32_t flags = 0
  261. );
  262. };
  263. /**
  264. * 3D image.
  265. */
  266. class image_3d: public image
  267. {
  268. public:
  269. /// @copydoc image::image
  270. image_3d
  271. (
  272. gl::format format,
  273. std::uint32_t width,
  274. std::uint32_t height,
  275. std::uint32_t depth,
  276. std::uint32_t mip_levels = 1,
  277. std::uint32_t flags = 0
  278. );
  279. };
  280. /**
  281. * Cube-compatible 2D image.
  282. */
  283. class image_cube: public image_2d
  284. {
  285. public:
  286. /// @copydoc image_2d::image_2d
  287. image_cube
  288. (
  289. gl::format format,
  290. std::uint32_t width,
  291. std::uint32_t mip_levels = 1,
  292. std::uint32_t array_layers = 6
  293. );
  294. };
  295. } // namespace gl
  296. #endif // ANTKEEPER_GL_IMAGE_HPP