1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Direct2DImage: Update interface to accept a Device instead of a DeviceContext

This commit is contained in:
reuk 2024-12-09 18:45:08 +00:00
parent 21357f26b5
commit 336dcfc08c
6 changed files with 60 additions and 47 deletions

View file

@ -341,7 +341,7 @@ public:
const auto d2d1Bitmap = [&]
{
if (auto direct2DPixelData = dynamic_cast<Direct2DPixelData*> (fillType.image.getPixelData().get()))
if (const auto page = direct2DPixelData->getFirstPageForContext (context))
if (const auto page = direct2DPixelData->getFirstPageForDevice (D2DUtilities::getDeviceForContext (context)))
if (page->GetPixelFormat().format == DXGI_FORMAT_B8G8R8A8_UNORM)
return page;
@ -1171,7 +1171,7 @@ void Direct2DGraphicsContext::clipToImageAlpha (const Image& sourceImage, const
ComSmartPtr<ID2D1Bitmap> d2d1Bitmap;
if (auto direct2DPixelData = dynamic_cast<Direct2DPixelData*> (sourceImage.getPixelData().get()))
d2d1Bitmap = direct2DPixelData->getFirstPageForContext (deviceContext);
d2d1Bitmap = direct2DPixelData->getFirstPageForDevice (D2DUtilities::getDeviceForContext (deviceContext));
if (! d2d1Bitmap)
{
@ -1481,7 +1481,7 @@ void Direct2DGraphicsContext::drawImage (const Image& imageIn, const AffineTrans
auto drawTiles = [&] (const auto& pixelData, auto&& getRect)
{
for (const auto& page : pixelData->getPagesForContext (deviceContext))
for (const auto& page : pixelData->getPagesForDevice (D2DUtilities::getDeviceForContext (deviceContext)))
{
const auto pageBounds = page.getBounds();
const auto intersection = pageBounds.toFloat().getIntersection (imageClipArea.toFloat());

View file

@ -366,7 +366,7 @@ public:
if (const auto hr = snapshot->CopyFromBitmap (&p, buffer, &sourceRect); FAILED (hr))
return {};
const Image result { new Direct2DPixelData { deviceContext, snapshot } };
const Image result { new Direct2DPixelData { D2DUtilities::getDeviceForContext (deviceContext), snapshot } };
swap.getChain()->Present (0, DXGI_PRESENT_DO_NOT_WAIT);

View file

@ -42,16 +42,6 @@ Rectangle<int> Direct2DPixelDataPage::getBounds() const
}
//==============================================================================
static ComSmartPtr<ID2D1Device1> getDeviceForContext (ComSmartPtr<ID2D1DeviceContext1> context)
{
if (context == nullptr)
return {};
ComSmartPtr<ID2D1Device> device;
context->GetDevice (device.resetAndGetPointerAddress());
return device.getInterface<ID2D1Device1>();
}
static std::vector<Direct2DPixelDataPage> makePages (ComSmartPtr<ID2D1Device1> device,
ImagePixelData::Ptr backingData,
bool needsClear)
@ -236,11 +226,11 @@ Direct2DPixelDataPages::Direct2DPixelDataPages (ComSmartPtr<ID2D1Bitmap1> bitmap
jassert (image->createType()->getTypeID() == SoftwareImageType{}.getTypeID());
}
Direct2DPixelDataPages::Direct2DPixelDataPages (ComSmartPtr<ID2D1DeviceContext1> context,
Direct2DPixelDataPages::Direct2DPixelDataPages (ComSmartPtr<ID2D1Device1> device,
ImagePixelData::Ptr image,
State initialState)
: backingData (image),
pages (makePages (getDeviceForContext (context), backingData, initialState == State::cleared)),
pages (makePages (device, backingData, initialState == State::cleared)),
upToDate (initialState != State::unsuitableToRead)
{
// The backup image must be a software image
@ -284,12 +274,11 @@ Direct2DPixelData::Direct2DPixelData (ImagePixelData::Ptr ptr, State initialStat
directX->adapters.addListener (*this);
}
Direct2DPixelData::Direct2DPixelData (ComSmartPtr<ID2D1DeviceContext1> context,
Direct2DPixelData::Direct2DPixelData (ComSmartPtr<ID2D1Device1> device,
ComSmartPtr<ID2D1Bitmap1> page)
: Direct2DPixelData (readFromDirect2DBitmap (context, page), State::drawn)
: Direct2DPixelData (readFromDirect2DBitmap (Direct2DDeviceContext::create (device), page), State::drawn)
{
if (const auto device1 = getDeviceForContext (context))
pagesForDevice.emplace (device1, Direct2DPixelDataPages { page, backingData });
pagesForDevice.emplace (device, Direct2DPixelDataPages { page, backingData });
}
Direct2DPixelData::Direct2DPixelData (Image::PixelFormat formatToUse, int w, int h, bool clearIn)
@ -303,14 +292,12 @@ Direct2DPixelData::~Direct2DPixelData()
directX->adapters.removeListener (*this);
}
auto Direct2DPixelData::getIteratorForContext (ComSmartPtr<ID2D1DeviceContext1> context)
auto Direct2DPixelData::getIteratorForDevice (ComSmartPtr<ID2D1Device1> device)
{
const auto device1 = getDeviceForContext (context);
if (device1 == nullptr)
if (device == nullptr)
return pagesForDevice.end();
const auto iter = pagesForDevice.find (device1);
const auto iter = pagesForDevice.find (device);
if (iter != pagesForDevice.end())
return iter;
@ -350,7 +337,7 @@ auto Direct2DPixelData::getIteratorForContext (ComSmartPtr<ID2D1DeviceContext1>
return Pages::State::unsuitableToRead;
}();
const auto pair = pagesForDevice.emplace (device1, Pages { context, backingData, initialState });
const auto pair = pagesForDevice.emplace (device, Pages { device, backingData, initialState });
return pair.first;
}
@ -422,7 +409,12 @@ std::unique_ptr<LowLevelGraphicsContext> Direct2DPixelData::createLowLevelContex
if (adapter == nullptr)
return invalidateAllAndReturnSoftwareContext();
const auto context = Direct2DDeviceContext::create (adapter);
const auto device = adapter->direct2DDevice;
if (device == nullptr)
return invalidateAllAndReturnSoftwareContext();
const auto context = Direct2DDeviceContext::create (device);
if (context == nullptr)
return invalidateAllAndReturnSoftwareContext();
@ -432,7 +424,7 @@ std::unique_ptr<LowLevelGraphicsContext> Direct2DPixelData::createLowLevelContex
if (maxSize < width || maxSize < height)
return invalidateAllAndReturnSoftwareContext();
const auto iter = getIteratorForContext (context);
const auto iter = getIteratorForDevice (device);
jassert (iter != pagesForDevice.end());
const auto pages = iter->second.getPages();
@ -448,7 +440,7 @@ std::unique_ptr<LowLevelGraphicsContext> Direct2DPixelData::createLowLevelContex
struct FlushingContext : public Direct2DImageContext
{
FlushingContext (Direct2DPixelData::Ptr selfIn,
FlushingContext (Ptr selfIn,
ComSmartPtr<ID2D1DeviceContext1> context,
ComSmartPtr<ID2D1Bitmap1> target)
: Direct2DImageContext (context, target, D2DUtilities::rectFromSize (target->GetPixelSize())),
@ -473,7 +465,7 @@ std::unique_ptr<LowLevelGraphicsContext> Direct2DPixelData::createLowLevelContex
ComSmartPtr<ID2D1DeviceContext1> storedContext;
ComSmartPtr<ID2D1Bitmap1> storedTarget;
Direct2DPixelData::Ptr self;
Ptr self;
ImagePixelData::Ptr backup;
};
@ -534,7 +526,12 @@ void Direct2DPixelData::applyGaussianBlurEffect (float radius, Image& result)
return;
}
const auto context = Direct2DDeviceContext::create (adapter);
const auto device = adapter->direct2DDevice;
if (device == nullptr)
return;
const auto context = Direct2DDeviceContext::create (device);
const auto maxSize = (int) context->GetMaximumBitmapSize();
if (context == nullptr || maxSize < width || maxSize < height)
@ -551,7 +548,7 @@ void Direct2DPixelData::applyGaussianBlurEffect (float radius, Image& result)
return;
}
effect->SetInput (0, getFirstPageForContext (context));
effect->SetInput (0, getFirstPageForDevice (device));
effect->SetValue (D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, radius / 3.0f);
const auto outputPixelData = Direct2DBitmap::createBitmap (context,
@ -565,7 +562,7 @@ void Direct2DPixelData::applyGaussianBlurEffect (float radius, Image& result)
context->DrawImage (effect);
context->EndDraw();
result = Image { new Direct2DPixelData { context, outputPixelData } };
result = Image { new Direct2DPixelData { device, outputPixelData } };
}
void Direct2DPixelData::applySingleChannelBoxBlurEffect (int radius, Image& result)
@ -581,7 +578,12 @@ void Direct2DPixelData::applySingleChannelBoxBlurEffect (int radius, Image& resu
return;
}
const auto context = Direct2DDeviceContext::create (adapter);
const auto device = adapter->direct2DDevice;
if (device == nullptr)
return;
const auto context = Direct2DDeviceContext::create (device);
const auto maxSize = (int) context->GetMaximumBitmapSize();
if (context == nullptr || maxSize < width || maxSize < height)
@ -629,7 +631,7 @@ void Direct2DPixelData::applySingleChannelBoxBlurEffect (int radius, Image& resu
return;
}
begin->SetInput (0, getFirstPageForContext (context));
begin->SetInput (0, getFirstPageForDevice (device));
const auto outputPixelData = Direct2DBitmap::createBitmap (context,
Image::ARGB,
@ -642,12 +644,12 @@ void Direct2DPixelData::applySingleChannelBoxBlurEffect (int radius, Image& resu
context->DrawImage (end);
context->EndDraw();
result = Image { new Direct2DPixelData { context, outputPixelData } };
result = Image { new Direct2DPixelData { device, outputPixelData } };
}
auto Direct2DPixelData::getPagesForContext (ComSmartPtr<ID2D1DeviceContext1> context) -> Span<const Page>
auto Direct2DPixelData::getPagesForDevice (ComSmartPtr<ID2D1Device1> device) -> Span<const Page>
{
return getIteratorForContext (context)->second.getPages();
return getIteratorForDevice (device)->second.getPages();
}
//==============================================================================
@ -753,7 +755,8 @@ public:
beginTest ("Ensure data parity across mapped page boundaries");
{
const auto adapterToUse = directX->adapters.getDefaultAdapter();
const auto contextToUse = Direct2DDeviceContext::create (adapterToUse);
const auto deviceToUse = adapterToUse->direct2DDevice;
const auto contextToUse = Direct2DDeviceContext::create (deviceToUse);
for (auto sourceFormat : formats)
{
@ -779,7 +782,7 @@ public:
const auto maxPageBounds = [&]
{
if (auto* data = dynamic_cast<Direct2DPixelData*> (d2dImage.getPixelData().get()))
if (auto pages = data->getPagesForContext (contextToUse); ! pages.empty())
if (auto pages = data->getPagesForDevice (deviceToUse); ! pages.empty())
return pages.front().getBounds();
return Rectangle<int>{};

View file

@ -77,7 +77,7 @@ public:
- mark the GPU images as up-to-date, or
- clear the GPU images, then mark them as up-to-date
*/
Direct2DPixelDataPages (ComSmartPtr<ID2D1DeviceContext1>, ImagePixelData::Ptr, State);
Direct2DPixelDataPages (ComSmartPtr<ID2D1Device1>, ImagePixelData::Ptr, State);
/* Returns all pages included in this set.
This will be called before reading from the pages (e.g. when drawing them).
@ -132,7 +132,7 @@ public:
This will immediately copy the content of the image to the software backup, so that the
image can still be drawn if original device goes away.
*/
Direct2DPixelData (ComSmartPtr<ID2D1DeviceContext1>, ComSmartPtr<ID2D1Bitmap1>);
Direct2DPixelData (ComSmartPtr<ID2D1Device1>, ComSmartPtr<ID2D1Bitmap1>);
/* Creates software image storage of the requested size. */
Direct2DPixelData (Image::PixelFormat, int, int, bool);
@ -178,14 +178,14 @@ public:
through the Direct2D API will have unpredictable results.
If you want to render into this image using D2D, call createLowLevelContext.
*/
Span<const Page> getPagesForContext (ComSmartPtr<ID2D1DeviceContext1>);
Span<const Page> getPagesForDevice (ComSmartPtr<ID2D1Device1>);
/* Utility function that just returns a pointer to the bitmap for the first page returned from
getPagesForContext.
*/
ComSmartPtr<ID2D1Bitmap1> getFirstPageForContext (ComSmartPtr<ID2D1DeviceContext1> context)
ComSmartPtr<ID2D1Bitmap1> getFirstPageForDevice (ComSmartPtr<ID2D1Device1> device)
{
const auto pages = getPagesForContext (context);
const auto pages = getPagesForDevice (device);
return ! pages.empty() ? pages.front().bitmap : nullptr;
}
@ -199,7 +199,7 @@ private:
};
Direct2DPixelData (ImagePixelData::Ptr, State);
auto getIteratorForContext (ComSmartPtr<ID2D1DeviceContext1>);
auto getIteratorForDevice (ComSmartPtr<ID2D1Device1>);
void adapterCreated (DxgiAdapter::Ptr) override {}
void adapterRemoved (DxgiAdapter::Ptr adapter) override

View file

@ -333,6 +333,16 @@ struct D2DUtilities
{
return { (int) s.width, (int) s.height };
}
static ComSmartPtr<ID2D1Device1> getDeviceForContext (ComSmartPtr<ID2D1DeviceContext1> context)
{
if (context == nullptr)
return {};
ComSmartPtr<ID2D1Device> device;
context->GetDevice (device.resetAndGetPointerAddress());
return device.getInterface<ID2D1Device1>();
}
};
//==============================================================================

View file

@ -5277,7 +5277,7 @@ private:
Image getImage() const
{
return Image { new Direct2DPixelData { deviceContext, bitmap } };
return Image { new Direct2DPixelData { adapter->direct2DDevice, bitmap } };
}
ComSmartPtr<ID2D1Bitmap1> getBitmap() const