Fixes an issue where primitives such as text could end up with sharp
edges when creating temporary contexts:
void paint (Graphics& g)
{
g.fillAll (Colours::white);
const auto preferredType = g.getInternalContext().getPreferredImageTypeForTemporaryImages();
Image img (Image::ARGB, getWidth(), getHeight(), false, *preferredType);
{
Graphics g2 (img);
}
g.setColour (Colours::black);
g.setFont (32);
g.drawText ("test", getLocalBounds(), Justification::centred);
}
The crash fixed by this commit could be triggered by attaching an OpenGL
context to a component, calling setBufferedToImage (true) on one of its
child components, and then detaching the OpenGL context from the parent.
Since 4ba01a80a0 we are creating images
with the current rendering context's native image type, so the above
scenario would leave an image buffer that references the detached
context.
A change introduced in 00836d1e94 meant
that GL renderers could sometimes assert in
StateHelpers::ActiveTextures::bindTexture() when ending a transparency
layer.
Specifically, the issue was provoked by adding the ScopedTextureBinding
in the constructor of OpenGLFrameBuffer. This reset the bound texture
after creating a new transparency layer.
I think the previous implementation worked by accident, not by design.
It so happens that when rendering multiple transparency layers within
the same frame (i.e. calling begin/end several times in that order,
*not* nesting the calls), the same texture ID will generally get reused.
From the graphics context's (GC's) perspective, we create a texture with
ID "2", then call bindTexture() to bind it, and the GC remembers that
this ID is bound. We draw the frame, and the texture gets destroyed. The
call to glDeleteTextures() will cause the default texture, "0", to be
bound if the texture being destroyed is bound at the point of
destruction. So, after the texture is destroyed, the GC's stored binding
no longer reflects reality, since texture "0" is now bound.
The next time we create a texture, that texture also gets created with
ID "2". Previously, we would leave this texture bound after
construction, but now we re-bind the previously-bound texture, "0". This
causes the assertion in bindTexture() to fire when we next attempt to
bind texture "2", since the actual bound texture is "0".
The solution added in this patch will bind texture "0" when the
transparency layer image is destroyed, in order to keep the GC's view of
the GL context consistent with the real state.
This addresses an issue where OpenGL-backed image content could get lost
when putting and Android app into an inactive state. This happens
because the GL context gets destroyed, freeing all associated resources.
The workaround introduced here will listen for OpenGL state-change
events, and attempt to save and restore framebuffer content into main
memory, so that the content can be restored once the app is reactivated.
JUCE convention is that BitmapData holds the lines of the image ordered
from top to bottom, but OpenGL orders lines in the reverse direction.
By returning a negative line stride, we can iterate lines in the
expected order as long as we always increment the current pointer
position by the line stride after processing each line.
Fixes a regression introduced in
bd26d79b17
The issue was observed in the DemoRunner when enabling the OpenGL
renderer and then switching to the LookAndFeel V1.
The cause of the problem was the creation of a secondary OpenGL-backed
Graphics instance in the DropShadowEffect. This temporary context could
modify the OpenGL context state without restoring the state
appropriately on destruction. As a result, when the outer long-lived
OpenGL context resumed drawing, properties such as the viewport, bound
shader, shader uniform values, and bound framebuffer could all be
incorrect.
This also fixes a bug introduced in f7c7225f5c
where the condition guarding the definition of traitCollectionDidChange
was incorrect. This function is never required if the deployment target
is at least 17.0.
There were a few "ambiguous operator new/delete" errors that were due to
inheriting from a private base class that used the leak detector. These
errors are resolved by adding the leak detector to the derived classes.
JUCE_API was missing from a few useful types, notably the ARA hosting
types.
Previously, code such as the following (where MyGLComponent is rendering
using an OpenGLContext) could result in GL errors, as the destruction of
the inner context unbound the array buffer and element array buffer
after use, instead of setting them to the previous values set up by the
outer context.
Additionally, a VAO was only set up in the OpenGLContext, so rendering
into a GL-backed LowLevel graphics context could fail if no VAO was
bound.
void MyGLComponent::paint (juce::Graphics& g)
{
juce::Image image { juce::Image::PixelFormat::ARGB, width, height, false, juce::OpenGLImageType() };
{
juce::Graphics innerContext { image };
// draw into innerContext
}
g.drawImage (image, juce::Rectangle<float> { width, height });
}