mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Direct2D: Hide implementation of RectangleListSpriteBatch::fillRectangles
This commit is contained in:
parent
49948d5dd4
commit
243d3756fc
2 changed files with 120 additions and 92 deletions
|
|
@ -496,6 +496,108 @@ ComSmartPtr<ID2D1SpriteBatch> RectangleListSpriteBatch::getSpriteBatch (ID2D1Dev
|
|||
});
|
||||
}
|
||||
|
||||
bool RectangleListSpriteBatch::fillRectanglesImpl (ComSmartPtr<ID2D1DeviceContext1> deviceContext,
|
||||
const RectangleList<float>& rectangles,
|
||||
const Colour colour,
|
||||
const TransformCallback& transformRectangle,
|
||||
[[maybe_unused]] Direct2DMetrics* metrics)
|
||||
{
|
||||
if (rectangles.isEmpty())
|
||||
return true;
|
||||
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, spriteBatchTime)
|
||||
|
||||
auto numRectanglesPainted = 0;
|
||||
while (numRectanglesPainted < rectangles.getNumRectangles())
|
||||
{
|
||||
auto numRectanglesRemaining = rectangles.getNumRectangles() - numRectanglesPainted;
|
||||
auto spriteBatchSize = isPowerOfTwo (numRectanglesRemaining) ? numRectanglesRemaining : (nextPowerOfTwo (numRectanglesRemaining) >> 1);
|
||||
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, spriteBatchSetupTime);
|
||||
|
||||
if (destinationsCapacity < (size_t) spriteBatchSize)
|
||||
{
|
||||
destinations.calloc (spriteBatchSize);
|
||||
destinationsCapacity = (size_t) spriteBatchSize;
|
||||
}
|
||||
|
||||
auto destination = destinations.getData();
|
||||
|
||||
for (int i = numRectanglesPainted; i < numRectanglesPainted + spriteBatchSize; ++i)
|
||||
{
|
||||
auto r = rectangles.getRectangle (i);
|
||||
r = transformRectangle.transform (r);
|
||||
|
||||
if (r.getWidth() < 1.0f || r.getHeight() < 1.0f)
|
||||
return false;
|
||||
|
||||
*destination = D2DUtilities::toRECT_F (r);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
if (! whiteRectangle)
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, createSpriteSourceTime);
|
||||
|
||||
auto hr = deviceContext->CreateCompatibleRenderTarget (D2D1_SIZE_F { (float) rectangleSize, (float) rectangleSize },
|
||||
D2D1_SIZE_U { rectangleSize, rectangleSize },
|
||||
D2D1_PIXEL_FORMAT { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
|
||||
whiteRectangle.resetAndGetPointerAddress());
|
||||
if (FAILED (hr))
|
||||
return false;
|
||||
|
||||
whiteRectangle->BeginDraw();
|
||||
whiteRectangle->Clear (D2D1_COLOR_F { 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
whiteRectangle->EndDraw();
|
||||
}
|
||||
|
||||
ComSmartPtr<ID2D1Bitmap> bitmap;
|
||||
|
||||
if (auto hr = whiteRectangle->GetBitmap (bitmap.resetAndGetPointerAddress()); SUCCEEDED (hr))
|
||||
{
|
||||
ComSmartPtr<ID2D1DeviceContext3> deviceContext3;
|
||||
|
||||
if (hr = deviceContext->QueryInterface<ID2D1DeviceContext3> (deviceContext3.resetAndGetPointerAddress()); SUCCEEDED (hr))
|
||||
{
|
||||
auto d2dColour = D2DUtilities::toCOLOR_F (colour);
|
||||
auto spriteBatch = getSpriteBatch (*deviceContext3, (uint32) spriteBatchSize);
|
||||
|
||||
if (spriteBatch == nullptr)
|
||||
return false;
|
||||
|
||||
auto setCount = jmin ((uint32) spriteBatchSize, spriteBatch->GetSpriteCount());
|
||||
auto addCount = (uint32) spriteBatchSize > setCount ? (uint32) spriteBatchSize - setCount : 0;
|
||||
|
||||
if (setCount != 0)
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, setSpritesTime);
|
||||
|
||||
spriteBatch->SetSprites (0, setCount, destinations.getData(), nullptr, &d2dColour, nullptr, sizeof (D2D1_RECT_F), 0, 0, 0);
|
||||
}
|
||||
|
||||
if (addCount != 0)
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, addSpritesTime);
|
||||
|
||||
spriteBatch->AddSprites (addCount, destinations.getData() + setCount, nullptr, &d2dColour, nullptr, sizeof (D2D1_RECT_F), 0, 0, 0);
|
||||
}
|
||||
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, drawSpritesTime);
|
||||
|
||||
deviceContext3->SetAntialiasMode (D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
deviceContext3->DrawSpriteBatch (spriteBatch, bitmap);
|
||||
deviceContext3->SetAntialiasMode (D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
|
||||
}
|
||||
}
|
||||
|
||||
numRectanglesPainted += spriteBatchSize;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
DxgiAdapter::Ptr Direct2DDeviceResources::findAdapter (const DxgiAdapters& adapters,
|
||||
ID2D1Bitmap1* bitmap)
|
||||
|
|
|
|||
|
|
@ -268,6 +268,11 @@ private:
|
|||
|
||||
class RectangleListSpriteBatch
|
||||
{
|
||||
struct TransformCallback
|
||||
{
|
||||
virtual Rectangle<float> transform (Rectangle<float>) const = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
RectangleListSpriteBatch() = default;
|
||||
|
||||
|
|
@ -282,105 +287,26 @@ public:
|
|||
TransformRectangle&& transformRectangle,
|
||||
[[maybe_unused]] Direct2DMetrics* metrics)
|
||||
{
|
||||
if (rectangles.isEmpty())
|
||||
return true;
|
||||
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, spriteBatchTime)
|
||||
|
||||
auto numRectanglesPainted = 0;
|
||||
while (numRectanglesPainted < rectangles.getNumRectangles())
|
||||
struct Callback : public TransformCallback
|
||||
{
|
||||
auto numRectanglesRemaining = rectangles.getNumRectangles() - numRectanglesPainted;
|
||||
auto spriteBatchSize = isPowerOfTwo (numRectanglesRemaining) ? numRectanglesRemaining : (nextPowerOfTwo (numRectanglesRemaining) >> 1);
|
||||
explicit Callback (TransformRectangle&& x) : fn (x) {}
|
||||
Rectangle<float> transform (Rectangle<float> x) const override { return fn (x); }
|
||||
TransformRectangle fn;
|
||||
};
|
||||
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, spriteBatchSetupTime);
|
||||
|
||||
if (destinationsCapacity < (size_t) spriteBatchSize)
|
||||
{
|
||||
destinations.calloc (spriteBatchSize);
|
||||
destinationsCapacity = (size_t) spriteBatchSize;
|
||||
}
|
||||
|
||||
auto destination = destinations.getData();
|
||||
|
||||
for (int i = numRectanglesPainted; i < numRectanglesPainted + spriteBatchSize; ++i)
|
||||
{
|
||||
auto r = rectangles.getRectangle (i);
|
||||
r = transformRectangle (r);
|
||||
|
||||
if (r.getWidth() < 1.0f || r.getHeight() < 1.0f)
|
||||
return false;
|
||||
|
||||
*destination = D2DUtilities::toRECT_F (r);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
if (! whiteRectangle)
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, createSpriteSourceTime);
|
||||
|
||||
auto hr = deviceContext->CreateCompatibleRenderTarget (D2D1_SIZE_F { (float) rectangleSize, (float) rectangleSize },
|
||||
D2D1_SIZE_U { rectangleSize, rectangleSize },
|
||||
D2D1_PIXEL_FORMAT { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
|
||||
whiteRectangle.resetAndGetPointerAddress());
|
||||
if (FAILED (hr))
|
||||
return false;
|
||||
|
||||
whiteRectangle->BeginDraw();
|
||||
whiteRectangle->Clear (D2D1_COLOR_F { 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
whiteRectangle->EndDraw();
|
||||
}
|
||||
|
||||
ComSmartPtr<ID2D1Bitmap> bitmap;
|
||||
|
||||
if (auto hr = whiteRectangle->GetBitmap (bitmap.resetAndGetPointerAddress()); SUCCEEDED (hr))
|
||||
{
|
||||
ComSmartPtr<ID2D1DeviceContext3> deviceContext3;
|
||||
|
||||
if (hr = deviceContext->QueryInterface<ID2D1DeviceContext3> (deviceContext3.resetAndGetPointerAddress()); SUCCEEDED (hr))
|
||||
{
|
||||
auto d2dColour = D2DUtilities::toCOLOR_F (colour);
|
||||
auto spriteBatch = getSpriteBatch (*deviceContext3, (uint32) spriteBatchSize);
|
||||
|
||||
if (spriteBatch == nullptr)
|
||||
return false;
|
||||
|
||||
auto setCount = jmin ((uint32) spriteBatchSize, spriteBatch->GetSpriteCount());
|
||||
auto addCount = (uint32) spriteBatchSize > setCount ? (uint32) spriteBatchSize - setCount : 0;
|
||||
|
||||
if (setCount != 0)
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, setSpritesTime);
|
||||
|
||||
spriteBatch->SetSprites (0, setCount, destinations.getData(), nullptr, &d2dColour, nullptr, sizeof (D2D1_RECT_F), 0, 0, 0);
|
||||
}
|
||||
|
||||
if (addCount != 0)
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, addSpritesTime);
|
||||
|
||||
spriteBatch->AddSprites (addCount, destinations.getData() + setCount, nullptr, &d2dColour, nullptr, sizeof (D2D1_RECT_F), 0, 0, 0);
|
||||
}
|
||||
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (metrics, drawSpritesTime);
|
||||
|
||||
deviceContext3->SetAntialiasMode (D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
deviceContext3->DrawSpriteBatch (spriteBatch, bitmap);
|
||||
deviceContext3->SetAntialiasMode (D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
|
||||
}
|
||||
}
|
||||
|
||||
numRectanglesPainted += spriteBatchSize;
|
||||
}
|
||||
|
||||
return true;
|
||||
const Callback callback { std::forward<TransformRectangle> (transformRectangle) };
|
||||
return fillRectanglesImpl (deviceContext, rectangles, colour, callback, metrics);
|
||||
}
|
||||
|
||||
private:
|
||||
ComSmartPtr<ID2D1SpriteBatch> getSpriteBatch (ID2D1DeviceContext3& dc, uint32 key);
|
||||
|
||||
bool fillRectanglesImpl (ComSmartPtr<ID2D1DeviceContext1> deviceContext,
|
||||
const RectangleList<float>& rectangles,
|
||||
Colour colour,
|
||||
const TransformCallback& transformRectangle,
|
||||
[[maybe_unused]] Direct2DMetrics* metrics);
|
||||
|
||||
static constexpr uint32 rectangleSize = 32;
|
||||
ComSmartPtr<ID2D1BitmapRenderTarget> whiteRectangle;
|
||||
HeapBlock<D2D1_RECT_F> destinations;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue