Skip to content

Commit 243d375

Browse files
reukOli
authored andcommitted
Direct2D: Hide implementation of RectangleListSpriteBatch::fillRectangles
1 parent 49948d5 commit 243d375

File tree

2 files changed

+120
-92
lines changed

2 files changed

+120
-92
lines changed

modules/juce_graphics/native/juce_DirectX_windows.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,108 @@ ComSmartPtr<ID2D1SpriteBatch> RectangleListSpriteBatch::getSpriteBatch (ID2D1Dev
496496
});
497497
}
498498

499+
bool RectangleListSpriteBatch::fillRectanglesImpl (ComSmartPtr<ID2D1DeviceContext1> deviceContext,
500+
const RectangleList<float>& rectangles,
501+
const Colour colour,
502+
const TransformCallback& transformRectangle,
503+
[[maybe_unused]] Direct2DMetrics* metrics)
504+
{
505+
if (rectangles.isEmpty())
506+
return true;
507+
508+
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, spriteBatchTime)
509+
510+
auto numRectanglesPainted = 0;
511+
while (numRectanglesPainted < rectangles.getNumRectangles())
512+
{
513+
auto numRectanglesRemaining = rectangles.getNumRectangles() - numRectanglesPainted;
514+
auto spriteBatchSize = isPowerOfTwo (numRectanglesRemaining) ? numRectanglesRemaining : (nextPowerOfTwo (numRectanglesRemaining) >> 1);
515+
516+
{
517+
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, spriteBatchSetupTime);
518+
519+
if (destinationsCapacity < (size_t) spriteBatchSize)
520+
{
521+
destinations.calloc (spriteBatchSize);
522+
destinationsCapacity = (size_t) spriteBatchSize;
523+
}
524+
525+
auto destination = destinations.getData();
526+
527+
for (int i = numRectanglesPainted; i < numRectanglesPainted + spriteBatchSize; ++i)
528+
{
529+
auto r = rectangles.getRectangle (i);
530+
r = transformRectangle.transform (r);
531+
532+
if (r.getWidth() < 1.0f || r.getHeight() < 1.0f)
533+
return false;
534+
535+
*destination = D2DUtilities::toRECT_F (r);
536+
++destination;
537+
}
538+
}
539+
540+
if (! whiteRectangle)
541+
{
542+
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, createSpriteSourceTime);
543+
544+
auto hr = deviceContext->CreateCompatibleRenderTarget (D2D1_SIZE_F { (float) rectangleSize, (float) rectangleSize },
545+
D2D1_SIZE_U { rectangleSize, rectangleSize },
546+
D2D1_PIXEL_FORMAT { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
547+
whiteRectangle.resetAndGetPointerAddress());
548+
if (FAILED (hr))
549+
return false;
550+
551+
whiteRectangle->BeginDraw();
552+
whiteRectangle->Clear (D2D1_COLOR_F { 1.0f, 1.0f, 1.0f, 1.0f });
553+
whiteRectangle->EndDraw();
554+
}
555+
556+
ComSmartPtr<ID2D1Bitmap> bitmap;
557+
558+
if (auto hr = whiteRectangle->GetBitmap (bitmap.resetAndGetPointerAddress()); SUCCEEDED (hr))
559+
{
560+
ComSmartPtr<ID2D1DeviceContext3> deviceContext3;
561+
562+
if (hr = deviceContext->QueryInterface<ID2D1DeviceContext3> (deviceContext3.resetAndGetPointerAddress()); SUCCEEDED (hr))
563+
{
564+
auto d2dColour = D2DUtilities::toCOLOR_F (colour);
565+
auto spriteBatch = getSpriteBatch (*deviceContext3, (uint32) spriteBatchSize);
566+
567+
if (spriteBatch == nullptr)
568+
return false;
569+
570+
auto setCount = jmin ((uint32) spriteBatchSize, spriteBatch->GetSpriteCount());
571+
auto addCount = (uint32) spriteBatchSize > setCount ? (uint32) spriteBatchSize - setCount : 0;
572+
573+
if (setCount != 0)
574+
{
575+
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, setSpritesTime);
576+
577+
spriteBatch->SetSprites (0, setCount, destinations.getData(), nullptr, &d2dColour, nullptr, sizeof (D2D1_RECT_F), 0, 0, 0);
578+
}
579+
580+
if (addCount != 0)
581+
{
582+
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, addSpritesTime);
583+
584+
spriteBatch->AddSprites (addCount, destinations.getData() + setCount, nullptr, &d2dColour, nullptr, sizeof (D2D1_RECT_F), 0, 0, 0);
585+
}
586+
587+
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, drawSpritesTime);
588+
589+
deviceContext3->SetAntialiasMode (D2D1_ANTIALIAS_MODE_ALIASED);
590+
deviceContext3->DrawSpriteBatch (spriteBatch, bitmap);
591+
deviceContext3->SetAntialiasMode (D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
592+
}
593+
}
594+
595+
numRectanglesPainted += spriteBatchSize;
596+
}
597+
598+
return true;
599+
}
600+
499601
//==============================================================================
500602
DxgiAdapter::Ptr Direct2DDeviceResources::findAdapter (const DxgiAdapters& adapters,
501603
ID2D1Bitmap1* bitmap)

modules/juce_graphics/native/juce_DirectX_windows.h

Lines changed: 18 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ class RadialGradientCache
268268

269269
class RectangleListSpriteBatch
270270
{
271+
struct TransformCallback
272+
{
273+
virtual Rectangle<float> transform (Rectangle<float>) const = 0;
274+
};
275+
271276
public:
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

381301
private:
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

Comments
 (0)