@@ -268,6 +268,11 @@ class RadialGradientCache
268268
269269class RectangleListSpriteBatch
270270{
271+ struct TransformCallback
272+ {
273+ virtual Rectangle<float > transform (Rectangle<float >) const = 0;
274+ };
275+
271276public:
272277 RectangleListSpriteBatch () = default ;
273278
@@ -282,105 +287,26 @@ class RectangleListSpriteBatch
282287 TransformRectangle&& transformRectangle,
283288 [[maybe_unused]] Direct2DMetrics* metrics)
284289 {
285- if (rectangles.isEmpty ())
286- return true ;
287-
288- JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, spriteBatchTime)
289-
290- auto numRectanglesPainted = 0 ;
291- while (numRectanglesPainted < rectangles.getNumRectangles ())
290+ struct Callback : public TransformCallback
292291 {
293- auto numRectanglesRemaining = rectangles.getNumRectangles () - numRectanglesPainted;
294- auto spriteBatchSize = isPowerOfTwo (numRectanglesRemaining) ? numRectanglesRemaining : (nextPowerOfTwo (numRectanglesRemaining) >> 1 );
295-
296- {
297- JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, spriteBatchSetupTime);
298-
299- if (destinationsCapacity < (size_t ) spriteBatchSize)
300- {
301- destinations.calloc (spriteBatchSize);
302- destinationsCapacity = (size_t ) spriteBatchSize;
303- }
304-
305- auto destination = destinations.getData ();
306-
307- for (int i = numRectanglesPainted; i < numRectanglesPainted + spriteBatchSize; ++i)
308- {
309- auto r = rectangles.getRectangle (i);
310- r = transformRectangle (r);
311-
312- if (r.getWidth () < 1 .0f || r.getHeight () < 1 .0f )
313- return false ;
314-
315- *destination = D2DUtilities::toRECT_F (r);
316- ++destination;
317- }
318- }
319-
320- if (! whiteRectangle)
321- {
322- JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, createSpriteSourceTime);
323-
324- auto hr = deviceContext->CreateCompatibleRenderTarget (D2D1_SIZE_F { (float ) rectangleSize, (float ) rectangleSize },
325- D2D1_SIZE_U { rectangleSize, rectangleSize },
326- D2D1_PIXEL_FORMAT { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
327- whiteRectangle.resetAndGetPointerAddress ());
328- if (FAILED (hr))
329- return false ;
330-
331- whiteRectangle->BeginDraw ();
332- whiteRectangle->Clear (D2D1_COLOR_F { 1 .0f , 1 .0f , 1 .0f , 1 .0f });
333- whiteRectangle->EndDraw ();
334- }
292+ explicit Callback (TransformRectangle&& x) : fn (x) {}
293+ Rectangle<float > transform (Rectangle<float > x) const override { return fn (x); }
294+ TransformRectangle fn;
295+ };
335296
336- ComSmartPtr<ID2D1Bitmap> bitmap;
337-
338- if (auto hr = whiteRectangle->GetBitmap (bitmap.resetAndGetPointerAddress ()); SUCCEEDED (hr))
339- {
340- ComSmartPtr<ID2D1DeviceContext3> deviceContext3;
341-
342- if (hr = deviceContext->QueryInterface <ID2D1DeviceContext3> (deviceContext3.resetAndGetPointerAddress ()); SUCCEEDED (hr))
343- {
344- auto d2dColour = D2DUtilities::toCOLOR_F (colour);
345- auto spriteBatch = getSpriteBatch (*deviceContext3, (uint32) spriteBatchSize);
346-
347- if (spriteBatch == nullptr )
348- return false ;
349-
350- auto setCount = jmin ((uint32) spriteBatchSize, spriteBatch->GetSpriteCount ());
351- auto addCount = (uint32) spriteBatchSize > setCount ? (uint32) spriteBatchSize - setCount : 0 ;
352-
353- if (setCount != 0 )
354- {
355- JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, setSpritesTime);
356-
357- spriteBatch->SetSprites (0 , setCount, destinations.getData (), nullptr , &d2dColour, nullptr , sizeof (D2D1_RECT_F), 0 , 0 , 0 );
358- }
359-
360- if (addCount != 0 )
361- {
362- JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, addSpritesTime);
363-
364- spriteBatch->AddSprites (addCount, destinations.getData () + setCount, nullptr , &d2dColour, nullptr , sizeof (D2D1_RECT_F), 0 , 0 , 0 );
365- }
366-
367- JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, drawSpritesTime);
368-
369- deviceContext3->SetAntialiasMode (D2D1_ANTIALIAS_MODE_ALIASED);
370- deviceContext3->DrawSpriteBatch (spriteBatch, bitmap);
371- deviceContext3->SetAntialiasMode (D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
372- }
373- }
374-
375- numRectanglesPainted += spriteBatchSize;
376- }
377-
378- return true ;
297+ const Callback callback { std::forward<TransformRectangle> (transformRectangle) };
298+ return fillRectanglesImpl (deviceContext, rectangles, colour, callback, metrics);
379299 }
380300
381301private:
382302 ComSmartPtr<ID2D1SpriteBatch> getSpriteBatch (ID2D1DeviceContext3& dc, uint32 key);
383303
304+ bool fillRectanglesImpl (ComSmartPtr<ID2D1DeviceContext1> deviceContext,
305+ const RectangleList<float >& rectangles,
306+ Colour colour,
307+ const TransformCallback& transformRectangle,
308+ [[maybe_unused]] Direct2DMetrics* metrics);
309+
384310 static constexpr uint32 rectangleSize = 32 ;
385311 ComSmartPtr<ID2D1BitmapRenderTarget> whiteRectangle;
386312 HeapBlock<D2D1_RECT_F> destinations;
0 commit comments