mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
OpenGLFrameBuffer: Add a row order parameter for reading and writing pixels
This also fixes a bug where saving and restoring the framebuffer state could unexpectedly apply a vertical flip to the buffer content.
This commit is contained in:
parent
c77e8a73cc
commit
f5a6c510c0
4 changed files with 74 additions and 18 deletions
|
|
@ -58,6 +58,8 @@ public:
|
|||
{
|
||||
int width = 0, height = 0;
|
||||
std::vector<PixelARGB> data;
|
||||
|
||||
static constexpr auto order = RowOrder::fromBottomUp;
|
||||
};
|
||||
|
||||
~Pimpl() override
|
||||
|
|
@ -97,7 +99,7 @@ public:
|
|||
Image::BitmapData bitmap (image, Image::BitmapData::readOnly);
|
||||
|
||||
return initialise (context, bitmap.width, bitmap.height)
|
||||
&& writePixels ((const PixelARGB*) bitmap.data, image.getBounds());
|
||||
&& writePixels ((const PixelARGB*) bitmap.data, image.getBounds(), RowOrder::fromTopDown);
|
||||
}
|
||||
|
||||
bool initialise (OpenGLFrameBuffer& other)
|
||||
|
|
@ -233,7 +235,7 @@ public:
|
|||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
|
||||
bool readPixels (PixelARGB* target, const Rectangle<int>& area)
|
||||
bool readPixels (PixelARGB* target, const Rectangle<int>& area, RowOrder order)
|
||||
{
|
||||
auto* transientState = makeAndGetCurrentRenderingTarget();
|
||||
|
||||
|
|
@ -246,10 +248,25 @@ public:
|
|||
glReadPixels (area.getX(), area.getY(), area.getWidth(), area.getHeight(),
|
||||
JUCE_RGBA_FORMAT, GL_UNSIGNED_BYTE, target);
|
||||
|
||||
if (order == RowOrder::fromTopDown)
|
||||
{
|
||||
auto* end = target + area.getWidth() * area.getHeight();
|
||||
|
||||
for (auto y = 0; y < area.getHeight() / 2; ++y)
|
||||
{
|
||||
const auto offset = area.getWidth() * y;
|
||||
auto* rowA = target + offset;
|
||||
auto* rowB = end - offset - area.getWidth();
|
||||
|
||||
for (auto x = 0; x < area.getWidth(); ++x)
|
||||
std::swap (rowA[x], rowB[x]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writePixels (const PixelARGB* data, const Rectangle<int>& area)
|
||||
bool writePixels (const PixelARGB* data, const Rectangle<int>& area, RowOrder order)
|
||||
{
|
||||
if (associatedContext == nullptr)
|
||||
return false;
|
||||
|
|
@ -275,7 +292,7 @@ public:
|
|||
tex.getHeight()),
|
||||
transientState->width,
|
||||
transientState->height,
|
||||
true,
|
||||
order == RowOrder::fromTopDown,
|
||||
false);
|
||||
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
|
|
@ -422,7 +439,9 @@ private:
|
|||
if (! initialise (context, savedState.width, savedState.height))
|
||||
return false;
|
||||
|
||||
writePixels (savedState.data.data(), Rectangle (savedState.width, savedState.height));
|
||||
writePixels (savedState.data.data(),
|
||||
Rectangle (savedState.width, savedState.height),
|
||||
SavedState::order);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -432,7 +451,7 @@ private:
|
|||
area.getHeight(),
|
||||
std::vector<PixelARGB> ((size_t) area.getWidth() * (size_t) area.getHeight()) };
|
||||
|
||||
if (! readPixels (result.data.data(), area))
|
||||
if (! readPixels (result.data.data(), area, SavedState::order))
|
||||
return {};
|
||||
|
||||
return result;
|
||||
|
|
@ -551,14 +570,14 @@ void OpenGLFrameBuffer::makeCurrentAndClear()
|
|||
pimpl->makeCurrentAndClear();
|
||||
}
|
||||
|
||||
bool OpenGLFrameBuffer::readPixels (PixelARGB* targetData, const Rectangle<int>& sourceArea)
|
||||
bool OpenGLFrameBuffer::readPixels (PixelARGB* targetData, const Rectangle<int>& sourceArea, RowOrder order)
|
||||
{
|
||||
return pimpl->readPixels (targetData, sourceArea);
|
||||
return pimpl->readPixels (targetData, sourceArea, order);
|
||||
}
|
||||
|
||||
bool OpenGLFrameBuffer::writePixels (const PixelARGB* srcData, const Rectangle<int>& targetArea)
|
||||
bool OpenGLFrameBuffer::writePixels (const PixelARGB* srcData, const Rectangle<int>& targetArea, RowOrder order)
|
||||
{
|
||||
return pimpl->writePixels (srcData, targetArea);
|
||||
return pimpl->writePixels (srcData, targetArea, order);
|
||||
}
|
||||
|
||||
GLuint OpenGLFrameBuffer::getCurrentFrameBufferTarget() noexcept
|
||||
|
|
|
|||
|
|
@ -116,17 +116,24 @@ public:
|
|||
/** Selects the framebuffer as the current target, and clears it to transparent. */
|
||||
void makeCurrentAndClear();
|
||||
|
||||
enum class RowOrder
|
||||
{
|
||||
fromBottomUp, //< Standard order for OpenGL, the bottom-most row of pixels is first.
|
||||
//< Using this pixel ordering may be faster, but may be incompatible
|
||||
//< with other JUCE functions that operate on image pixel data, as these
|
||||
//< generally expect the rows to be ordered top-down.
|
||||
fromTopDown, //< Standard order for JUCE images, the top-most row of pixels is first.
|
||||
};
|
||||
|
||||
/** Reads an area of pixels from the framebuffer into a 32-bit ARGB pixel array.
|
||||
The lineStride is measured as a number of pixels, not bytes - pass a stride
|
||||
of 0 to indicate a packed array.
|
||||
The RowOrder parameter specifies the order of rows in the resulting array.
|
||||
*/
|
||||
bool readPixels (PixelARGB* targetData, const Rectangle<int>& sourceArea);
|
||||
bool readPixels (PixelARGB* targetData, const Rectangle<int>& sourceArea, RowOrder);
|
||||
|
||||
/** Writes an area of pixels into the framebuffer from a specified pixel array.
|
||||
The lineStride is measured as a number of pixels, not bytes - pass a stride
|
||||
of 0 to indicate a packed array.
|
||||
The RowOrder parameter specifies the order of rows in srcData.
|
||||
*/
|
||||
bool writePixels (const PixelARGB* srcData, const Rectangle<int>& targetArea);
|
||||
bool writePixels (const PixelARGB* srcData, const Rectangle<int>& targetArea, RowOrder);
|
||||
|
||||
private:
|
||||
class Pimpl;
|
||||
|
|
|
|||
|
|
@ -116,13 +116,13 @@ private:
|
|||
mode (modeIn)
|
||||
{
|
||||
if (mode != Image::BitmapData::writeOnly)
|
||||
self->frameBuffer.readPixels (data.get(), getArea());
|
||||
self->frameBuffer.readPixels (data.get(), getArea(), order);
|
||||
}
|
||||
|
||||
~DataReleaser() override
|
||||
{
|
||||
if (mode != Image::BitmapData::readOnly)
|
||||
self->frameBuffer.writePixels (data, getArea());
|
||||
self->frameBuffer.writePixels (data, getArea(), order);
|
||||
}
|
||||
|
||||
Rectangle<int> getArea() const
|
||||
|
|
@ -134,6 +134,8 @@ private:
|
|||
HeapBlock<PixelARGB> data;
|
||||
Rectangle<int> area;
|
||||
Image::BitmapData::ReadWriteMode mode;
|
||||
|
||||
static constexpr auto order = OpenGLFrameBuffer::RowOrder::fromBottomUp;
|
||||
};
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLFrameBufferImage)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue