GR32_Polygons.Direct2D.pas 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. unit GR32_Polygons.Direct2D;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Direct2D Polygon Rasterizer for Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Anders Melander
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2025
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. *
  32. * ***** END LICENSE BLOCK ***** *)
  33. interface
  34. {$include GR32.inc}
  35. {$IFDEF FPC}
  36. {$DEFINE PUREPASCAL}
  37. {$ENDIF}
  38. uses
  39. Types,
  40. Direct2D,
  41. D2D1,
  42. GR32,
  43. GR32_Polygons;
  44. //------------------------------------------------------------------------------
  45. //
  46. // TPolygonRenderer32Direct2D
  47. //
  48. //------------------------------------------------------------------------------
  49. // Direct2D polygon rasterizer.
  50. //------------------------------------------------------------------------------
  51. // Note: The Filler property of TPolygonRenderer32 is ignored; Fills are always
  52. // solid.
  53. //------------------------------------------------------------------------------
  54. type
  55. TPolygonRenderer32Direct2D = class(TPolygonRenderer32, IPolygonRendererBatching)
  56. private
  57. FD2DCanvas: TDirect2DCanvas;
  58. FBatchLevel: integer;
  59. protected
  60. procedure SetBitmap(const Value: TCustomBitmap32); override;
  61. procedure SetColor(const Value: TColor32); override;
  62. procedure ApplyColor;
  63. public
  64. destructor Destroy; override;
  65. procedure BeginDraw;
  66. procedure EndDraw;
  67. procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect); override;
  68. end;
  69. //------------------------------------------------------------------------------
  70. //------------------------------------------------------------------------------
  71. //------------------------------------------------------------------------------
  72. implementation
  73. uses
  74. Math,
  75. SysUtils,
  76. GR32_VectorUtils,
  77. GR32_Backends;
  78. //------------------------------------------------------------------------------
  79. //
  80. // TPolygonRenderer32Direct2D
  81. //
  82. //------------------------------------------------------------------------------
  83. destructor TPolygonRenderer32Direct2D.Destroy;
  84. begin
  85. FD2DCanvas.Free;
  86. inherited;
  87. end;
  88. //------------------------------------------------------------------------------
  89. procedure TPolygonRenderer32Direct2D.BeginDraw;
  90. begin
  91. Inc(FBatchLevel);
  92. if (FBatchLevel = 1) and (FD2DCanvas <> nil) then
  93. FD2DCanvas.BeginDraw;
  94. end;
  95. procedure TPolygonRenderer32Direct2D.EndDraw;
  96. begin
  97. Dec(FBatchLevel);
  98. if (FBatchLevel = 0) and (FD2DCanvas <> nil) then
  99. FD2DCanvas.EndDraw;
  100. end;
  101. //------------------------------------------------------------------------------
  102. procedure TPolygonRenderer32Direct2D.SetBitmap(const Value: TCustomBitmap32);
  103. var
  104. DeviceContextSupport: IDeviceContextSupport;
  105. begin
  106. // Bitmap is set for each call to TCanvas32.DrawPath so we need
  107. // to test for change in value or the recreation of the D2D
  108. // canvas will kill our performance.
  109. if (Value = Bitmap) then
  110. exit;
  111. if (FD2DCanvas <> nil) then
  112. begin
  113. if (FBatchLevel > 0) then
  114. FD2DCanvas.EndDraw;
  115. FD2DCanvas.Free;
  116. FD2DCanvas := nil;
  117. end;
  118. inherited;
  119. if (Bitmap <> nil) and (Supports(Bitmap.Backend, IDeviceContextSupport, DeviceContextSupport)) then
  120. begin
  121. FD2DCanvas := TDirect2DCanvas.Create(DeviceContextSupport.Handle, Bitmap.BoundsRect);
  122. ApplyColor;
  123. if (FBatchLevel > 0) then
  124. FD2DCanvas.BeginDraw;
  125. end;
  126. end;
  127. procedure TPolygonRenderer32Direct2D.ApplyColor;
  128. const
  129. OneOver255: Single = 1 / 255;
  130. begin
  131. if (FD2DCanvas = nil) then
  132. exit;
  133. FD2DCanvas.Brush.Color := WinColor(Color);
  134. FD2DCanvas.Brush.Handle.SetOpacity((Color shr 24) * OneOver255);
  135. end;
  136. //------------------------------------------------------------------------------
  137. procedure TPolygonRenderer32Direct2D.SetColor(const Value: TColor32);
  138. begin
  139. if (Value = Color) then
  140. exit;
  141. inherited;
  142. ApplyColor;
  143. end;
  144. //------------------------------------------------------------------------------
  145. type
  146. TBitmap32Access = class(TBitmap32);
  147. procedure TPolygonRenderer32Direct2D.PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect);
  148. const
  149. d2dFillMode: array[TPolyFillMode] of TD2D1FillMode = (D2D1_FILL_MODE_ALTERNATE, D2D1_FILL_MODE_WINDING);
  150. var
  151. i: Integer;
  152. {$IFDEF CHANGENOTIFICATIONS}
  153. ChangeRect: TRect;
  154. {$ENDIF}
  155. Geometry: ID2D1PathGeometry;
  156. Sink: ID2D1GeometrySink;
  157. begin
  158. if (Length(Points) = 0) then
  159. Exit;
  160. if (FD2DCanvas = nil) then
  161. exit;
  162. if (not Bitmap.MeasuringMode) then
  163. begin
  164. // Calling FD2DCanvas.BeginDraw at this low level absolutely kills performance but
  165. // unfortunately our paint framework doesn't provide any granularity that involves
  166. // the polygon rasterizer.
  167. BeginDraw;
  168. D2DFactory.CreatePathGeometry(Geometry);
  169. Geometry.Open(Sink);
  170. Sink.SetFillMode(d2dFillMode[FillMode]);
  171. for i := 0 to High(Points) do
  172. if (Length(Points[i]) > 1) then
  173. begin
  174. Sink.BeginFigure(TD2D1Point2F(Points[i, 0]), D2D1_FIGURE_BEGIN_FILLED);
  175. Sink.AddLines(PD2D1Point2F(@Points[i, 1]), Length(Points[i])-1);
  176. Sink.EndFigure(D2D1_FIGURE_END_CLOSED);
  177. end;
  178. Sink.Close;
  179. FD2DCanvas.RenderTarget.FillGeometry(Geometry, FD2DCanvas.Brush.Handle);
  180. EndDraw;
  181. end;
  182. {$IFDEF CHANGENOTIFICATIONS}
  183. if (TBitmap32Access(Bitmap).LockUpdateCount = 0) and
  184. ((Bitmap.MeasuringMode) or (TBitmap32Access(Bitmap).UpdateCount = 0)) then
  185. begin
  186. for i := 0 to High(Points) do
  187. if (Length(Points[i]) > 1) then
  188. begin
  189. if (GR32.IntersectRect(ChangeRect, MakeRect(ClipRect, rrOutside), MakeRect(PolygonBounds(Points[i])))) then
  190. Bitmap.Changed(ChangeRect);
  191. end;
  192. end;
  193. {$ENDIF}
  194. end;
  195. //------------------------------------------------------------------------------
  196. initialization
  197. RegisterPolygonRenderer(TPolygonRenderer32Direct2D);
  198. end.