mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-09 04:30:09 +00:00
Direct2D: Move bitmap helpers to shared DirectX header
This commit is contained in:
parent
f0f77db261
commit
f3a74896fc
3 changed files with 92 additions and 90 deletions
|
|
@ -351,7 +351,7 @@ public:
|
|||
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (Direct2DMetricsHub::getInstance()->imageContextMetrics, createBitmapTime);
|
||||
|
||||
return Direct2DBitmap::fromImage (fillType.image, deviceResources.deviceContext.context, Image::ARGB);
|
||||
return Direct2DBitmap::toBitmap (fillType.image, deviceResources.deviceContext.context, Image::ARGB);
|
||||
}();
|
||||
|
||||
if (d2d1Bitmap != nullptr)
|
||||
|
|
@ -1188,7 +1188,7 @@ void Direct2DGraphicsContext::clipToImageAlpha (const Image& sourceImage, const
|
|||
if (! d2d1Bitmap)
|
||||
{
|
||||
// Convert sourceImage to single-channel alpha-only maskImage
|
||||
d2d1Bitmap = Direct2DBitmap::fromImage (sourceImage, deviceContext, Image::SingleChannel);
|
||||
d2d1Bitmap = Direct2DBitmap::toBitmap (sourceImage, deviceContext, Image::SingleChannel);
|
||||
}
|
||||
|
||||
if (d2d1Bitmap)
|
||||
|
|
@ -1474,7 +1474,7 @@ void Direct2DGraphicsContext::drawImage (const Image& image, const AffineTransfo
|
|||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (Direct2DMetricsHub::getInstance()->imageContextMetrics, createBitmapTime);
|
||||
|
||||
d2d1Bitmap = Direct2DBitmap::fromImage (image, deviceContext, Image::ARGB);
|
||||
d2d1Bitmap = Direct2DBitmap::toBitmap (image, deviceContext, Image::ARGB);
|
||||
imageClipArea = image.getBounds();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,93 +74,6 @@ struct Direct2DDeviceContext
|
|||
ComSmartPtr<ID2D1DeviceContext1> context;
|
||||
};
|
||||
|
||||
class Direct2DBitmap final
|
||||
{
|
||||
public:
|
||||
static ComSmartPtr<ID2D1Bitmap1> fromImage (const Image& image,
|
||||
ComSmartPtr<ID2D1DeviceContext1> deviceContext,
|
||||
Image::PixelFormat outputFormat)
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (Direct2DMetricsHub::getInstance()->imageContextMetrics, createBitmapTime);
|
||||
|
||||
jassert (outputFormat == Image::ARGB || outputFormat == Image::SingleChannel);
|
||||
|
||||
JUCE_TRACE_LOG_D2D_PAINT_CALL (etw::createDirect2DBitmapFromImage, etw::graphicsKeyword);
|
||||
|
||||
// Calling Image::convertedToFormat could cause unchecked recursion since convertedToFormat
|
||||
// calls Graphics::drawImageAt which calls Direct2DGraphicsContext::drawImage which calls this function...
|
||||
//
|
||||
// Use a software image for the conversion instead so the Graphics::drawImageAt call doesn't go
|
||||
// through the Direct2D renderer
|
||||
//
|
||||
// Be sure to explicitly set the DPI to 96.0 for the image; otherwise it will default to the screen DPI
|
||||
// and may be scaled incorrectly
|
||||
const auto convertedImage = SoftwareImageType{}.convert (image).convertedToFormat (outputFormat);
|
||||
|
||||
if (! convertedImage.isValid())
|
||||
return {};
|
||||
|
||||
Image::BitmapData bitmapData { convertedImage, Image::BitmapData::readWrite };
|
||||
|
||||
D2D1_BITMAP_PROPERTIES1 bitmapProperties{};
|
||||
bitmapProperties.pixelFormat.format = outputFormat == Image::SingleChannel
|
||||
? DXGI_FORMAT_A8_UNORM
|
||||
: DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
bitmapProperties.pixelFormat.alphaMode = outputFormat == Image::RGB
|
||||
? D2D1_ALPHA_MODE_IGNORE
|
||||
: D2D1_ALPHA_MODE_PREMULTIPLIED;
|
||||
bitmapProperties.dpiX = USER_DEFAULT_SCREEN_DPI;
|
||||
bitmapProperties.dpiY = USER_DEFAULT_SCREEN_DPI;
|
||||
|
||||
const D2D1_SIZE_U size { (UINT32) image.getWidth(), (UINT32) image.getHeight() };
|
||||
|
||||
ComSmartPtr<ID2D1Bitmap1> bitmap;
|
||||
deviceContext->CreateBitmap (size,
|
||||
bitmapData.data,
|
||||
(UINT32) bitmapData.lineStride,
|
||||
bitmapProperties,
|
||||
bitmap.resetAndGetPointerAddress());
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static ComSmartPtr<ID2D1Bitmap1> createBitmap (ComSmartPtr<ID2D1DeviceContext1> deviceContext,
|
||||
Image::PixelFormat format,
|
||||
D2D_SIZE_U size,
|
||||
D2D1_BITMAP_OPTIONS options)
|
||||
{
|
||||
JUCE_TRACE_LOG_D2D_PAINT_CALL (etw::createDirect2DBitmap, etw::graphicsKeyword);
|
||||
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (Direct2DMetricsHub::getInstance()->imageContextMetrics, createBitmapTime);
|
||||
|
||||
#if JUCE_DEBUG
|
||||
// Verify that the GPU can handle a bitmap of this size
|
||||
//
|
||||
// If you need a bitmap larger than this, you'll need to either split it up into multiple bitmaps
|
||||
// or use a software image (see SoftwareImageType).
|
||||
auto maxBitmapSize = deviceContext->GetMaximumBitmapSize();
|
||||
jassert (size.width <= maxBitmapSize && size.height <= maxBitmapSize);
|
||||
#endif
|
||||
|
||||
const auto pixelFormat = D2D1::PixelFormat (format == Image::SingleChannel
|
||||
? DXGI_FORMAT_A8_UNORM
|
||||
: DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
format == Image::RGB
|
||||
? D2D1_ALPHA_MODE_IGNORE
|
||||
: D2D1_ALPHA_MODE_PREMULTIPLIED);
|
||||
const auto bitmapProperties = D2D1::BitmapProperties1 (options, pixelFormat);
|
||||
|
||||
ComSmartPtr<ID2D1Bitmap1> bitmap;
|
||||
deviceContext->CreateBitmap (size,
|
||||
{},
|
||||
{},
|
||||
bitmapProperties,
|
||||
bitmap.resetAndGetPointerAddress());
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
Direct2DBitmap() = delete;
|
||||
};
|
||||
|
||||
static ComSmartPtr<ID2D1GradientStopCollection> makeGradientStopCollection (const ColourGradient& gradient,
|
||||
ComSmartPtr<ID2D1DeviceContext1> deviceContext,
|
||||
[[maybe_unused]] Direct2DMetrics* metrics) noexcept
|
||||
|
|
|
|||
|
|
@ -327,4 +327,93 @@ struct D2DUtilities
|
|||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct Direct2DBitmap
|
||||
{
|
||||
Direct2DBitmap() = delete;
|
||||
|
||||
static ComSmartPtr<ID2D1Bitmap1> toBitmap (const Image& image,
|
||||
ComSmartPtr<ID2D1DeviceContext1> deviceContext,
|
||||
Image::PixelFormat outputFormat)
|
||||
{
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (Direct2DMetricsHub::getInstance()->imageContextMetrics, createBitmapTime);
|
||||
|
||||
jassert (outputFormat == Image::ARGB || outputFormat == Image::SingleChannel);
|
||||
|
||||
JUCE_TRACE_LOG_D2D_PAINT_CALL (etw::createDirect2DBitmapFromImage, etw::graphicsKeyword);
|
||||
|
||||
// Calling Image::convertedToFormat could cause unchecked recursion since convertedToFormat
|
||||
// calls Graphics::drawImageAt which calls Direct2DGraphicsContext::drawImage which calls this function...
|
||||
//
|
||||
// Use a software image for the conversion instead so the Graphics::drawImageAt call doesn't go
|
||||
// through the Direct2D renderer
|
||||
//
|
||||
// Be sure to explicitly set the DPI to 96.0 for the image; otherwise it will default to the screen DPI
|
||||
// and may be scaled incorrectly
|
||||
const auto convertedImage = SoftwareImageType{}.convert (image).convertedToFormat (outputFormat);
|
||||
|
||||
if (! convertedImage.isValid())
|
||||
return {};
|
||||
|
||||
Image::BitmapData bitmapData { convertedImage, Image::BitmapData::readWrite };
|
||||
|
||||
D2D1_BITMAP_PROPERTIES1 bitmapProperties{};
|
||||
bitmapProperties.pixelFormat.format = outputFormat == Image::SingleChannel
|
||||
? DXGI_FORMAT_A8_UNORM
|
||||
: DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
bitmapProperties.pixelFormat.alphaMode = outputFormat == Image::RGB
|
||||
? D2D1_ALPHA_MODE_IGNORE
|
||||
: D2D1_ALPHA_MODE_PREMULTIPLIED;
|
||||
bitmapProperties.dpiX = USER_DEFAULT_SCREEN_DPI;
|
||||
bitmapProperties.dpiY = USER_DEFAULT_SCREEN_DPI;
|
||||
|
||||
const D2D1_SIZE_U size { (UINT32) image.getWidth(), (UINT32) image.getHeight() };
|
||||
|
||||
ComSmartPtr<ID2D1Bitmap1> bitmap;
|
||||
deviceContext->CreateBitmap (size,
|
||||
bitmapData.data,
|
||||
(UINT32) bitmapData.lineStride,
|
||||
bitmapProperties,
|
||||
bitmap.resetAndGetPointerAddress());
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static ComSmartPtr<ID2D1Bitmap1> createBitmap (ComSmartPtr<ID2D1DeviceContext1> deviceContext,
|
||||
Image::PixelFormat format,
|
||||
D2D_SIZE_U size,
|
||||
D2D1_BITMAP_OPTIONS options)
|
||||
{
|
||||
JUCE_TRACE_LOG_D2D_PAINT_CALL (etw::createDirect2DBitmap, etw::graphicsKeyword);
|
||||
|
||||
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (Direct2DMetricsHub::getInstance()->imageContextMetrics, createBitmapTime);
|
||||
|
||||
#if JUCE_DEBUG
|
||||
// Verify that the GPU can handle a bitmap of this size
|
||||
//
|
||||
// If you need a bitmap larger than this, you'll need to either split it up into multiple bitmaps
|
||||
// or use a software image (see SoftwareImageType).
|
||||
auto maxBitmapSize = deviceContext->GetMaximumBitmapSize();
|
||||
jassert (size.width <= maxBitmapSize && size.height <= maxBitmapSize);
|
||||
#endif
|
||||
|
||||
const auto pixelFormat = D2D1::PixelFormat (format == Image::SingleChannel
|
||||
? DXGI_FORMAT_A8_UNORM
|
||||
: DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
format == Image::RGB
|
||||
? D2D1_ALPHA_MODE_IGNORE
|
||||
: D2D1_ALPHA_MODE_PREMULTIPLIED);
|
||||
const auto bitmapProperties = D2D1::BitmapProperties1 (options, pixelFormat);
|
||||
|
||||
ComSmartPtr<ID2D1Bitmap1> bitmap;
|
||||
const auto hr = deviceContext->CreateBitmap (size,
|
||||
{},
|
||||
{},
|
||||
bitmapProperties,
|
||||
bitmap.resetAndGetPointerAddress());
|
||||
|
||||
jassertquiet (SUCCEEDED (hr) && bitmap != nullptr);
|
||||
return bitmap;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue