PaintingCommandExecutorGPU.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibAccelGfx/GlyphAtlas.h>
  7. #include <LibWeb/Painting/PaintingCommandExecutorGPU.h>
  8. namespace Web::Painting {
  9. PaintingCommandExecutorGPU::PaintingCommandExecutorGPU(Gfx::Bitmap& bitmap)
  10. : m_target_bitmap(bitmap)
  11. {
  12. auto painter = AccelGfx::Painter::create();
  13. auto canvas = AccelGfx::Canvas::create(bitmap.size());
  14. painter->set_target_canvas(canvas);
  15. m_stacking_contexts.append({ .canvas = canvas,
  16. .painter = move(painter),
  17. .opacity = 1.0f,
  18. .destination = {},
  19. .transform = {} });
  20. }
  21. PaintingCommandExecutorGPU::~PaintingCommandExecutorGPU()
  22. {
  23. VERIFY(m_stacking_contexts.size() == 1);
  24. painter().flush(m_target_bitmap);
  25. }
  26. CommandResult PaintingCommandExecutorGPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color)
  27. {
  28. painter().draw_glyph_run(glyph_run, color);
  29. return CommandResult::Continue;
  30. }
  31. CommandResult PaintingCommandExecutorGPU::draw_text(Gfx::IntRect const&, String const&, Gfx::TextAlignment, Color const&, Gfx::TextElision, Gfx::TextWrapping, Optional<NonnullRefPtr<Gfx::Font>> const&)
  32. {
  33. // FIXME
  34. return CommandResult::Continue;
  35. }
  36. CommandResult PaintingCommandExecutorGPU::fill_rect(Gfx::IntRect const& rect, Color const& color)
  37. {
  38. painter().fill_rect(rect, color);
  39. return CommandResult::Continue;
  40. }
  41. static AccelGfx::Painter::ScalingMode to_accelgfx_scaling_mode(Gfx::Painter::ScalingMode scaling_mode)
  42. {
  43. switch (scaling_mode) {
  44. case Gfx::Painter::ScalingMode::NearestNeighbor:
  45. case Gfx::Painter::ScalingMode::BoxSampling:
  46. case Gfx::Painter::ScalingMode::SmoothPixels:
  47. case Gfx::Painter::ScalingMode::None:
  48. return AccelGfx::Painter::ScalingMode::NearestNeighbor;
  49. case Gfx::Painter::ScalingMode::BilinearBlend:
  50. return AccelGfx::Painter::ScalingMode::Bilinear;
  51. default:
  52. VERIFY_NOT_REACHED();
  53. }
  54. }
  55. CommandResult PaintingCommandExecutorGPU::draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode)
  56. {
  57. painter().draw_scaled_bitmap(dst_rect, bitmap, src_rect, to_accelgfx_scaling_mode(scaling_mode));
  58. return CommandResult::Continue;
  59. }
  60. CommandResult PaintingCommandExecutorGPU::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode)
  61. {
  62. painter().draw_scaled_immutable_bitmap(dst_rect, immutable_bitmap, src_rect, to_accelgfx_scaling_mode(scaling_mode));
  63. return CommandResult::Continue;
  64. }
  65. CommandResult PaintingCommandExecutorGPU::set_clip_rect(Gfx::IntRect const& rect)
  66. {
  67. painter().set_clip_rect(rect);
  68. return CommandResult::Continue;
  69. }
  70. CommandResult PaintingCommandExecutorGPU::clear_clip_rect()
  71. {
  72. painter().clear_clip_rect();
  73. return CommandResult::Continue;
  74. }
  75. CommandResult PaintingCommandExecutorGPU::set_font(Gfx::Font const&)
  76. {
  77. // FIXME
  78. return CommandResult::Continue;
  79. }
  80. CommandResult PaintingCommandExecutorGPU::push_stacking_context(float opacity, bool is_fixed_position, Gfx::IntRect const& source_paintable_rect, Gfx::IntPoint post_transform_translation, CSS::ImageRendering, StackingContextTransform transform, Optional<StackingContextMask>)
  81. {
  82. m_stacking_contexts.last().stacking_context_depth++;
  83. painter().save();
  84. if (is_fixed_position) {
  85. auto const& translation = painter().transform().translation();
  86. painter().translate(-translation);
  87. }
  88. auto stacking_context_transform = Gfx::extract_2d_affine_transform(transform.matrix);
  89. Gfx::AffineTransform inverse_origin_translation;
  90. inverse_origin_translation.translate(-transform.origin);
  91. Gfx::AffineTransform origin_translation;
  92. origin_translation.translate(transform.origin);
  93. Gfx::AffineTransform final_transform = origin_translation;
  94. final_transform.multiply(stacking_context_transform);
  95. final_transform.multiply(inverse_origin_translation);
  96. if (opacity < 1 || !stacking_context_transform.is_identity_or_translation()) {
  97. auto painter = AccelGfx::Painter::create();
  98. auto canvas = AccelGfx::Canvas::create(source_paintable_rect.size());
  99. painter->set_target_canvas(canvas);
  100. painter->translate(-source_paintable_rect.location().to_type<float>());
  101. painter->clear(Color::Transparent);
  102. m_stacking_contexts.append({ .canvas = canvas,
  103. .painter = move(painter),
  104. .opacity = opacity,
  105. .destination = source_paintable_rect,
  106. .transform = final_transform });
  107. } else {
  108. painter().translate(stacking_context_transform.translation() + post_transform_translation.to_type<float>());
  109. m_stacking_contexts.append({ .canvas = {},
  110. .painter = MaybeOwned(painter()),
  111. .opacity = opacity,
  112. .destination = {},
  113. .transform = final_transform });
  114. }
  115. return CommandResult::Continue;
  116. }
  117. CommandResult PaintingCommandExecutorGPU::pop_stacking_context()
  118. {
  119. auto stacking_context = m_stacking_contexts.take_last();
  120. VERIFY(stacking_context.stacking_context_depth == 0);
  121. if (stacking_context.painter.is_owned()) {
  122. painter().blit_canvas(stacking_context.destination, *stacking_context.canvas, stacking_context.opacity, stacking_context.transform);
  123. }
  124. painter().restore();
  125. m_stacking_contexts.last().stacking_context_depth--;
  126. return CommandResult::Continue;
  127. }
  128. CommandResult PaintingCommandExecutorGPU::paint_linear_gradient(Gfx::IntRect const& rect, Web::Painting::LinearGradientData const& data)
  129. {
  130. painter().fill_rect_with_linear_gradient(rect, data.color_stops.list, data.gradient_angle, data.color_stops.repeat_length);
  131. return CommandResult::Continue;
  132. }
  133. CommandResult PaintingCommandExecutorGPU::paint_outer_box_shadow(PaintOuterBoxShadowParams const&)
  134. {
  135. // FIXME
  136. return CommandResult::Continue;
  137. }
  138. CommandResult PaintingCommandExecutorGPU::paint_inner_box_shadow(PaintOuterBoxShadowParams const&)
  139. {
  140. // FIXME
  141. return CommandResult::Continue;
  142. }
  143. CommandResult PaintingCommandExecutorGPU::paint_text_shadow(int, Gfx::IntRect const&, Gfx::IntRect const&, String const&, Gfx::Font const&, Color const&, int, Gfx::IntPoint const&)
  144. {
  145. // FIXME
  146. return CommandResult::Continue;
  147. }
  148. CommandResult PaintingCommandExecutorGPU::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Optional<Gfx::FloatPoint> const&)
  149. {
  150. painter().fill_rect_with_rounded_corners(
  151. rect, color,
  152. { static_cast<float>(top_left_radius.horizontal_radius), static_cast<float>(top_left_radius.vertical_radius) },
  153. { static_cast<float>(top_right_radius.horizontal_radius), static_cast<float>(top_right_radius.vertical_radius) },
  154. { static_cast<float>(bottom_left_radius.horizontal_radius), static_cast<float>(bottom_left_radius.vertical_radius) },
  155. { static_cast<float>(bottom_right_radius.horizontal_radius), static_cast<float>(bottom_right_radius.vertical_radius) });
  156. return CommandResult::Continue;
  157. }
  158. CommandResult PaintingCommandExecutorGPU::fill_path_using_color(Gfx::Path const&, Color const&, Gfx::Painter::WindingRule, Optional<Gfx::FloatPoint> const&)
  159. {
  160. // FIXME
  161. return CommandResult::Continue;
  162. }
  163. CommandResult PaintingCommandExecutorGPU::fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const&, Gfx::Painter::WindingRule, float, Optional<Gfx::FloatPoint> const&)
  164. {
  165. // FIXME
  166. return CommandResult::Continue;
  167. }
  168. CommandResult PaintingCommandExecutorGPU::stroke_path_using_color(Gfx::Path const&, Color const&, float, Optional<Gfx::FloatPoint> const&)
  169. {
  170. // FIXME
  171. return CommandResult::Continue;
  172. }
  173. CommandResult PaintingCommandExecutorGPU::stroke_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const&, float, float, Optional<Gfx::FloatPoint> const&)
  174. {
  175. // FIXME
  176. return CommandResult::Continue;
  177. }
  178. CommandResult PaintingCommandExecutorGPU::draw_ellipse(Gfx::IntRect const&, Color const&, int)
  179. {
  180. // FIXME
  181. return CommandResult::Continue;
  182. }
  183. CommandResult PaintingCommandExecutorGPU::fill_ellipse(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::BlendMode)
  184. {
  185. auto horizontal_radius = static_cast<float>(rect.width() / 2);
  186. auto vertical_radius = static_cast<float>(rect.height() / 2);
  187. painter().fill_rect_with_rounded_corners(
  188. rect, color,
  189. { horizontal_radius, vertical_radius },
  190. { horizontal_radius, vertical_radius },
  191. { horizontal_radius, vertical_radius },
  192. { horizontal_radius, vertical_radius });
  193. return CommandResult::Continue;
  194. }
  195. CommandResult PaintingCommandExecutorGPU::draw_line(Color const& color, Gfx::IntPoint const& a, Gfx::IntPoint const& b, int thickness, Gfx::Painter::LineStyle, Color const&)
  196. {
  197. // FIXME: Pass line style and alternate color once AccelGfx::Painter supports it
  198. painter().draw_line(a, b, thickness, color);
  199. return CommandResult::Continue;
  200. }
  201. CommandResult PaintingCommandExecutorGPU::draw_signed_distance_field(Gfx::IntRect const&, Color const&, Gfx::GrayscaleBitmap const&, float)
  202. {
  203. // FIXME
  204. return CommandResult::Continue;
  205. }
  206. CommandResult PaintingCommandExecutorGPU::paint_progressbar(Gfx::IntRect const&, Gfx::IntRect const&, Palette const&, int, int, int, StringView const&)
  207. {
  208. // FIXME
  209. return CommandResult::Continue;
  210. }
  211. CommandResult PaintingCommandExecutorGPU::paint_frame(Gfx::IntRect const&, Palette const&, Gfx::FrameStyle)
  212. {
  213. // FIXME
  214. return CommandResult::Continue;
  215. }
  216. CommandResult PaintingCommandExecutorGPU::apply_backdrop_filter(Gfx::IntRect const&, Web::CSS::ResolvedBackdropFilter const&)
  217. {
  218. // FIXME
  219. return CommandResult::Continue;
  220. }
  221. CommandResult PaintingCommandExecutorGPU::draw_rect(Gfx::IntRect const&, Color const&, bool)
  222. {
  223. // FIXME
  224. return CommandResult::Continue;
  225. }
  226. CommandResult PaintingCommandExecutorGPU::paint_radial_gradient(Gfx::IntRect const&, Web::Painting::RadialGradientData const&, Gfx::IntPoint const&, Gfx::IntSize const&)
  227. {
  228. // FIXME
  229. return CommandResult::Continue;
  230. }
  231. CommandResult PaintingCommandExecutorGPU::paint_conic_gradient(Gfx::IntRect const&, Web::Painting::ConicGradientData const&, Gfx::IntPoint const&)
  232. {
  233. // FIXME
  234. return CommandResult::Continue;
  235. }
  236. CommandResult PaintingCommandExecutorGPU::draw_triangle_wave(Gfx::IntPoint const&, Gfx::IntPoint const&, Color const&, int, int)
  237. {
  238. // FIXME
  239. return CommandResult::Continue;
  240. }
  241. CommandResult PaintingCommandExecutorGPU::sample_under_corners(BorderRadiusCornerClipper&)
  242. {
  243. // FIXME
  244. return CommandResult::Continue;
  245. }
  246. CommandResult PaintingCommandExecutorGPU::blit_corner_clipping(BorderRadiusCornerClipper&)
  247. {
  248. // FIXME
  249. return CommandResult::Continue;
  250. }
  251. CommandResult PaintingCommandExecutorGPU::paint_borders(DevicePixelRect const& border_rect, CornerRadii const& corner_radii, BordersDataDevicePixels const& borders_data)
  252. {
  253. // FIXME: Add support for corner radiuses
  254. (void)corner_radii;
  255. Gfx::IntRect top_border_rect = {
  256. border_rect.x(),
  257. border_rect.y(),
  258. border_rect.width(),
  259. borders_data.top.width
  260. };
  261. Gfx::IntRect right_border_rect = {
  262. border_rect.x() + (border_rect.width() - borders_data.right.width),
  263. border_rect.y(),
  264. borders_data.right.width,
  265. border_rect.height()
  266. };
  267. Gfx::IntRect bottom_border_rect = {
  268. border_rect.x(),
  269. border_rect.y() + (border_rect.height() - borders_data.bottom.width),
  270. border_rect.width(),
  271. borders_data.bottom.width
  272. };
  273. Gfx::IntRect left_border_rect = {
  274. border_rect.x(),
  275. border_rect.y(),
  276. borders_data.left.width,
  277. border_rect.height()
  278. };
  279. if (borders_data.top.width > 0)
  280. painter().fill_rect(top_border_rect, borders_data.top.color);
  281. if (borders_data.right.width > 0)
  282. painter().fill_rect(right_border_rect, borders_data.right.color);
  283. if (borders_data.bottom.width > 0)
  284. painter().fill_rect(bottom_border_rect, borders_data.bottom.color);
  285. if (borders_data.left.width > 0)
  286. painter().fill_rect(left_border_rect, borders_data.left.color);
  287. return CommandResult::Continue;
  288. }
  289. bool PaintingCommandExecutorGPU::would_be_fully_clipped_by_painter(Gfx::IntRect rect) const
  290. {
  291. auto translation = painter().transform().translation().to_type<int>();
  292. return !painter().clip_rect().intersects(rect.translated(translation));
  293. }
  294. void PaintingCommandExecutorGPU::prepare_glyph_texture(HashMap<Gfx::Font const*, HashTable<u32>> const& unique_glyphs)
  295. {
  296. AccelGfx::GlyphAtlas::the().update(unique_glyphs);
  297. }
  298. void PaintingCommandExecutorGPU::update_immutable_bitmap_texture_cache(HashMap<u32, Gfx::ImmutableBitmap const*>& immutable_bitmaps)
  299. {
  300. painter().update_immutable_bitmap_texture_cache(immutable_bitmaps);
  301. }
  302. }