From c7d03a85df157b0f291b17eca0c8b88b81812896 Mon Sep 17 00:00:00 2001 From: Kimball Thurston Date: Mon, 23 Sep 2024 23:57:26 +1200 Subject: [PATCH] Initial api to provide stateless read api for scanline things This enables reading of scanlines in a "stateless" manner, where a framebuffer does not have to be stored, then the call to readPixels made. Signed-off-by: Kimball Thurston --- src/lib/OpenEXR/ImfInputFile.cpp | 40 ++++++++++++++++++++++++ src/lib/OpenEXR/ImfInputFile.h | 21 +++++++++++++ src/lib/OpenEXR/ImfInputPart.cpp | 7 +++++ src/lib/OpenEXR/ImfInputPart.h | 3 ++ src/lib/OpenEXR/ImfMultiPartInputFile.h | 2 +- src/lib/OpenEXR/ImfScanLineInputFile.cpp | 7 +++++ src/lib/OpenEXR/ImfScanLineInputFile.h | 12 +++++++ 7 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/lib/OpenEXR/ImfInputFile.cpp b/src/lib/OpenEXR/ImfInputFile.cpp index 2f984bb4c2..7dedf2327c 100644 --- a/src/lib/OpenEXR/ImfInputFile.cpp +++ b/src/lib/OpenEXR/ImfInputFile.cpp @@ -77,10 +77,14 @@ struct InputFile::Data } void setFrameBuffer (const FrameBuffer& frameBuffer); + void lockedSetFrameBuffer (const FrameBuffer& frameBuffer); void readPixels (int scanline1, int scanline2); void bufferedReadPixels (int scanline1, int scanline2); + void readPixels ( + const FrameBuffer& frameBuffer, int scanline1, int scanline2); + void deleteCachedBuffer (void); void copyCachedBuffer (FrameBuffer::ConstIterator to, FrameBuffer::ConstIterator from, @@ -224,6 +228,13 @@ InputFile::readPixels (int scanLine) _data->readPixels (scanLine, scanLine); } +void +InputFile::readPixels ( + const FrameBuffer& frameBuffer, int scanLine1, int scanLine2) +{ + _data->readPixels (frameBuffer, scanLine1, scanLine2); +} + void InputFile::rawPixelData ( int firstScanLine, const char*& pixelData, int& pixelDataSize) @@ -317,7 +328,12 @@ InputFile::Data::setFrameBuffer (const FrameBuffer& frameBuffer) #if ILMTHREAD_THREADING_ENABLED std::lock_guard lk (_mx); #endif + lockedSetFrameBuffer (frameBuffer); +} +void +InputFile::Data::lockedSetFrameBuffer (const FrameBuffer& frameBuffer) +{ if (_storage == EXR_STORAGE_TILED) { // @@ -430,6 +446,30 @@ InputFile::Data::readPixels (int scanLine1, int scanLine2) else { _sFile->readPixels (scanLine1, scanLine2); } } +void +InputFile::Data::readPixels ( + const FrameBuffer& frameBuffer, int scanLine1, int scanLine2) +{ + if (_compositor) + { +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_mx); +#endif + _compositor->setFrameBuffer (frameBuffer); + _compositor->readPixels (scanLine1, scanLine2); + } + else if (_storage == EXR_STORAGE_TILED) + { +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_mx); +#endif + + lockedSetFrameBuffer (frameBuffer); + bufferedReadPixels (scanLine1, scanLine2); + } + else { _sFile->readPixels (frameBuffer, scanLine1, scanLine2); } +} + void InputFile::Data::bufferedReadPixels (int scanLine1, int scanLine2) { diff --git a/src/lib/OpenEXR/ImfInputFile.h b/src/lib/OpenEXR/ImfInputFile.h index 3e9da65c8d..f5d67ddb32 100644 --- a/src/lib/OpenEXR/ImfInputFile.h +++ b/src/lib/OpenEXR/ImfInputFile.h @@ -200,6 +200,27 @@ class IMF_EXPORT_TYPE InputFile IMF_EXPORT void readPixels (int scanLine); + //---------------------------------------------- + // Combines the setFrameBuffer and readPixels into a singular + // call. This does more than that in that it can, with the right + // conditions, not require a lock on the file, such that multiple + // (external to OpenEXR) threads can read at the same time on + // different framebuffers + // + // NB: if the underlying file is deep or tiled, that requires + // translation, so will not do the pass through, but will behave + // in a threadsafe manner (where the only way that was possible + // before was to have a larger framebuffer, set the framebuffer + // once, then call readPixels by the external threads, although + // that occured with a mutex and so the reads were serialized. + // There are reasons why that might still be serialized, such as a + // non-threadable stream. + //---------------------------------------------- + + IMF_EXPORT + void readPixels ( + const FrameBuffer& frameBuffer, int scanLine1, int scanLine2); + //---------------------------------------------- // Read a block of raw pixel data from the file, // without uncompressing it (this function is diff --git a/src/lib/OpenEXR/ImfInputPart.cpp b/src/lib/OpenEXR/ImfInputPart.cpp index acfd20db26..8b8d4ef952 100644 --- a/src/lib/OpenEXR/ImfInputPart.cpp +++ b/src/lib/OpenEXR/ImfInputPart.cpp @@ -70,6 +70,13 @@ InputPart::readPixels (int scanLine) file->readPixels (scanLine); } +void +InputPart::readPixels ( + const FrameBuffer& frameBuffer, int scanLine1, int scanLine2) +{ + file->readPixels (frameBuffer, scanLine1, scanLine2); +} + void InputPart::rawPixelData ( int firstScanLine, const char*& pixelData, int& pixelDataSize) diff --git a/src/lib/OpenEXR/ImfInputPart.h b/src/lib/OpenEXR/ImfInputPart.h index 440cc80bed..c25a4fa63f 100644 --- a/src/lib/OpenEXR/ImfInputPart.h +++ b/src/lib/OpenEXR/ImfInputPart.h @@ -41,6 +41,9 @@ class IMF_EXPORT_TYPE InputPart IMF_EXPORT void readPixels (int scanLine); IMF_EXPORT + void readPixels ( + const FrameBuffer& frameBuffer, int scanLine1, int scanLine2); + IMF_EXPORT void rawPixelData ( int firstScanLine, const char*& pixelData, int& pixelDataSize); diff --git a/src/lib/OpenEXR/ImfMultiPartInputFile.h b/src/lib/OpenEXR/ImfMultiPartInputFile.h index 22911ed3b1..0b1fc07a5e 100644 --- a/src/lib/OpenEXR/ImfMultiPartInputFile.h +++ b/src/lib/OpenEXR/ImfMultiPartInputFile.h @@ -99,7 +99,7 @@ class IMF_EXPORT_TYPE MultiPartInputFile // // used internally by 'Part' types to access individual parts of the multipart file // - // TODO: change these to value / reference semantics + // TODO: change these to value / reference semantics (smart ptr) template IMF_HIDDEN T* getInputPart (int partNumber); IMF_HIDDEN InputPartData* getPart (int) const; diff --git a/src/lib/OpenEXR/ImfScanLineInputFile.cpp b/src/lib/OpenEXR/ImfScanLineInputFile.cpp index e0db6de0b9..28ca979bb7 100644 --- a/src/lib/OpenEXR/ImfScanLineInputFile.cpp +++ b/src/lib/OpenEXR/ImfScanLineInputFile.cpp @@ -285,6 +285,13 @@ ScanLineInputFile::readPixels (int scanLine1, int scanLine2) _data->readPixels (frameBuffer (), scanLine1, scanLine2); } +void +ScanLineInputFile::readPixels ( + const FrameBuffer& frame, int scanLine1, int scanLine2) +{ + _data->readPixels (frame, scanLine1, scanLine2); +} + //////////////////////////////////////// void diff --git a/src/lib/OpenEXR/ImfScanLineInputFile.h b/src/lib/OpenEXR/ImfScanLineInputFile.h index c4e5ee5504..f9b5645039 100644 --- a/src/lib/OpenEXR/ImfScanLineInputFile.h +++ b/src/lib/OpenEXR/ImfScanLineInputFile.h @@ -140,6 +140,18 @@ class IMF_EXPORT_TYPE ScanLineInputFile IMF_EXPORT void readPixels (int scanLine); + //---------------------------------------------- + // Combines the setFrameBuffer and readPixels into a singular + // call. This does more than that in that it can, with the right + // conditions, not require a lock on the file, such that multiple + // (external to OpenEXR) threads can read at the same time on + // different framebuffers + //---------------------------------------------- + + IMF_EXPORT + void readPixels ( + const FrameBuffer& frame, int scanLine1, int scanLine2); + //---------------------------------------------- // Read a block of raw pixel data from the file, // without uncompressing it (this function is