JUCE8 : Strange behaviour with drawImageAt on Windows

Hello

I just made the transition between JUCE 7 and JUCE 8.
I develop an application that runs on Windows, Linux and MacOS.
In this application, I use juce::Image to store float values. An ARGB image contains 32 bits pixels … a float is also 32 bits.
I built several images that I assemble in one main image.
For building each image, I use juce::Image::BitmapData in order to access directly the 32 bits value.
In order to assemble the images, I use something like that:

m_RawDtm.clear(juce::Rectangle<int>(R0, S0, wout, hout));
juce::Graphics g(m_RawDtm);
g.setOpacity(1.f);
g.drawImageAt(tmpImage, R0, S0);

m_RawDtm is my main image.

It works perfectly on JUCE 7.
On JUCE 8, it works also perfectly on Linux and MacOS, but not on Windows.
I suppose the new Direct2D is the problem.
On Windows now the main image (m_RawDtm) just contains 0 values !

I tried to debug … but I am not a Direct2D specialist :worried:

After several tests, the problem is not with drawImageAt but with the juce::Image::BitmapData.
With JUCE 8 on Windows, it seems impossible to have several BitmapData at the same time on the same image, even if the readOnly / writeOnly flags are logically set.
It was not a problem with JUCE 7. I do not understand this regression.

In order to reproduce this behaviour:

this code does not work:

juce::Image tmpImage(m_RawDtm.getFormat(), wout, hout, true);
juce::Image::BitmapData bitmap(tmpImage, juce::Image::BitmapData::readWrite);
// do something with bitmap ...
juce::Graphics g(m_RawDtm);
g.setOpacity(1.f);
g.drawImageAt(tmpImage, 0, 0);

This code works:

juce::Image tmpImage(m_RawDtm.getFormat(), wout, hout, true);
{
    juce::Image::BitmapData bitmap(tmpImage, juce::Image::BitmapData::readWrite);
    // do something with bitmap ...
}
juce::Graphics g(m_RawDtm);
g.setOpacity(1.f);
g.drawImageAt(tmpImage, 0, 0);

The bitmap object is now deleted before calling drawImageAt … and now everything works perfectly !

The D2D renderer, like the OpenGL renderer, does not draw/copy directly into images. Instead, drawing commands are buffered so that they can be executed more efficiently. When modifying an Image, updates to the image will not be flushed until the BitmapData or Graphics object that is modifying the image goes out of scope.

A similar issue was previously discussed here:

1 Like

Thank you @reuk !

Perhaps an update of the documentation of juce::Image::BitmapData could be useful because it is a new behaviour that can break existing code.

2 Likes