Add an initial rhi implementation that mimics the opengl implementation

This commit is contained in:
luisangelsm
2026-01-17 22:46:27 +01:00
parent 91b8a31727
commit 3381754c12
25 changed files with 2739 additions and 21 deletions

View File

@ -1,7 +1,5 @@
#include "opengl_checker.h"
#include "QsLog.h"
OpenGLChecker::OpenGLChecker()
: compatibleOpenGLVersion(true)
{

287
common/rhi/README.md Normal file
View File

@ -0,0 +1,287 @@
# YACReader Flow RHI Implementation
This directory contains the QRhiWidget-based implementation of the YACReader 3D cover flow, providing cross-platform 3D rendering support for Qt 6.7+.
## Overview
The RHI (Rendering Hardware Interface) implementation is a modern replacement for the OpenGL-based flow (`yacreader_flow_gl`) that:
- ✅ Supports **multiple graphics APIs**: Vulkan, Metal, Direct3D 11/12, OpenGL
- ✅ Provides **native performance** on modern platforms (Metal on macOS, D3D on Windows)
- ✅ Maintains **100% API compatibility** with the OpenGL version
- ✅ Works seamlessly with **Qt 6.7+** while Qt5 continues using OpenGL
- ✅ Enables **future-proof** rendering infrastructure
## Architecture
### Class Hierarchy
```
QRhiWidget (Qt base class)
└── YACReaderFlow3D (Base implementation)
├── YACReaderComicFlow3D (File path-based loading for library)
└── YACReaderPageFlow3D (Byte array-based loading for viewer)
```
### Files
- **yacreader_flow_rhi.h** - Header with class definitions
- **yacreader_flow_rhi.cpp** - Implementation
- **shaders/** - GLSL 450 shaders and compiled .qsb files
- **README.md** - This file
## Key Features
### Graphics Pipeline
The implementation uses:
- **Instanced rendering** for efficient batch drawing
- **Dual-pass rendering** (reflections + covers)
- **MSAA** (4x by default) for anti-aliasing
- **Depth testing** and back-face culling
- **Alpha blending** for transparency
### Resource Management
QRhi resources managed:
- `QRhiBuffer` for vertices, instance data, and uniforms
- `QRhiTexture` for cover images, marks, and default texture
- `QRhiSampler` for texture filtering
- `QRhiGraphicsPipeline` for render state
- `QRhiShaderResourceBindings` for uniform/texture bindings
### Shader System
Shaders are written in **GLSL 4.50** and compiled to `.qsb` format supporting:
- OpenGL ES 2.0, 3.0
- OpenGL 2.1, 3.0+
- HLSL (Direct3D 11/12)
- Metal Shading Language (macOS/iOS)
## Integration
### Qt5 vs Qt6 Selection
The build system automatically selects the appropriate implementation:
**Qt 5.x**: Uses `YACReaderFlowGL` (OpenGL-based)
**Qt 6.0-6.6**: Uses `YACReaderFlowGL` (OpenGL-based)
**Qt 6.7+**: Uses `YACReaderFlow3D` (RHI-based) if `YACREADER_USE_RHI` is defined
### Type Aliases
Applications use type aliases for seamless switching:
```cpp
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) && defined(YACREADER_USE_RHI)
using YACReaderPageFlowImpl = YACReaderPageFlow3D;
using YACReaderComicFlowImpl = YACReaderComicFlow3D;
#else
using YACReaderPageFlowImpl = YACReaderPageFlowGL;
using YACReaderComicFlowImpl = YACReaderComicFlowGL;
#endif
```
### Example Usage (YACReader Viewer)
```cpp
// goto_flow_gl.cpp
flow = new YACReaderPageFlowImpl(this);
flow->setShowMarks(false);
flow->populate(numPages);
connect(flow, &YACReaderPageFlowImpl::selected, this, &GoToFlowGL::goToPage);
```
### Example Usage (YACReaderLibrary)
```cpp
// comic_flow_widget.cpp
flow = new YACReaderComicFlowImpl(parent);
flow->setImagePaths(pathsList);
connect(flow, &YACReaderComicFlowImpl::centerIndexChanged,
this, &ComicFlowWidget::centerIndexChanged);
```
## API Compatibility
All public methods from `YACReaderFlowGL` are preserved:
### Navigation
- `showPrevious()`, `showNext()`
- `setCurrentIndex(int)`, `setCenterIndex(unsigned int)`
- `showSlide(int)`, `centerIndex()`
### Configuration
- `setPreset(const Preset &)`
- `setPerformance(Performance)`
- `setFlowRightToLeft(bool)`
- `setZoom(int)`, `setRotation(int)`
- `setCF_RX/RY/RZ(int)`, `setCF_Y/Z(int)`
- `setX_Distance(int)`, `setCenter_Distance(int)`, etc.
### Appearance
- `setBackgroundColor(const QColor &)`
- `setTextColor(const QColor &)`
- `setShadingColor(const QColor &)`
- `setShowMarks(bool)`, `setMarks(QVector<...>)`
### Content Management
- `populate(int)`, `clear()`, `reset()`, `reload()`
- `insert()`, `remove(int)`, `add(int)`, `replace()`
- Subclass-specific: `setImagePaths()`, `resortCovers()`, etc.
## Building
### Prerequisites
1. **Qt 6.7 or later**
2. **qsb tool** (Qt Shader Baker) in PATH
3. **C++17 compiler**
### Compile Shaders
Before building YACReader, compile the shaders:
```bash
cd common/rhi/shaders
# Windows
compile_shaders.bat
# Unix/macOS
chmod +x compile_shaders.sh
./compile_shaders.sh
```
This generates `flow.vert.qsb` and `flow.frag.qsb` which are embedded via `shaders.qrc`.
### Build YACReader
The `.pro` files automatically include RHI sources for Qt 6.7+:
```bash
qmake YACReader.pro
make
```
For Qt 5 builds, the OpenGL version is used automatically.
## Graphics API Selection
QRhiWidget auto-selects the best API per platform:
- **macOS/iOS**: Metal (native)
- **Windows**: Direct3D 11 (default) or Direct3D 12
- **Linux**: Vulkan or OpenGL
- **Android**: OpenGL ES 3.0 or Vulkan
You can force a specific API via environment variables (for testing):
```bash
# Force OpenGL
export QSG_RHI_BACKEND=opengl
# Force Vulkan
export QSG_RHI_BACKEND=vulkan
# Force Direct3D 11 (Windows)
set QSG_RHI_BACKEND=d3d11
```
## Performance
Performance tiers match the OpenGL version:
- **Low**: 8 covers loaded, 128px textures (page flow) / 200px (comic flow)
- **Medium**: 10 covers, 196px / 256px textures
- **High**: 12 covers, 256px / 320px textures
- **Ultra High**: 14-16 covers, full resolution textures
Texture loading happens asynchronously via worker threads (`ImageLoader3D`, `ImageLoaderByteArray3D`).
## Debugging
### Enable Validation Layers
For debugging graphics issues, enable validation:
```cpp
flow->setDebugLayerEnabled(true); // Call before widget is shown
```
This activates:
- **Vulkan**: VK_LAYER_KHRONOS_validation
- **Direct3D**: D3D11 debug layer
- **Metal**: Metal API validation
### Check Active Graphics API
```cpp
QRhi *rhi = flow->rhi();
qDebug() << "Backend:" << rhi->backend();
qDebug() << "Driver:" << rhi->driverInfo();
```
### Common Issues
**Problem**: Shaders fail to load
**Solution**: Ensure `.qsb` files are compiled and included in resources
**Problem**: Black screen on Qt 6.7
**Solution**: Check if `YACREADER_USE_RHI` is defined in build
**Problem**: Crashes on resize/reparent
**Solution**: `releaseResources()` properly cleans up all QRhi objects
## Migration from OpenGL
The RHI version is a **drop-in replacement** requiring no application code changes beyond the build system.
### What's Different (Internal)
| OpenGL API | QRhi Equivalent |
|------------|-----------------|
| `glDrawArraysInstanced()` | `cb->drawIndexed(instanceCount)` |
| `glUniform*()` | Update `QRhiBuffer` with uniform data |
| `glBindTexture()` | `QRhiShaderResourceBindings` |
| `glBlendFunc()` | `QRhiGraphicsPipeline::setTargetBlends()` |
| `glEnable(GL_DEPTH_TEST)` | `pipeline->setDepthTest(true)` |
### What's the Same
- All public API methods and signatures
- Animation system and timing
- Preset configurations
- Event handling (mouse, keyboard, wheel)
- Worker thread texture loading
- Performance tiers
## Known Limitations
1. **Qt Version**: Requires Qt 6.7+ (released April 2024)
2. **QRhi Stability**: QRhi APIs may change in minor Qt releases
3. **Mixed Renderers**: Only one graphics API per window
4. **Shader Compilation**: Must recompile shaders when modifying source
## Future Improvements
Potential enhancements:
- [ ] GPU-side frustum culling
- [ ] Compute shader for texture generation
- [ ] HDR/wide color gamut support
- [ ] Ray-traced reflections (via RHI compute)
- [ ] Dynamic LOD based on distance
## References
- [QRhiWidget Class Documentation](https://doc.qt.io/qt-6/qrhiwidget.html)
- [QRhi Overview](https://doc.qt.io/qt-6/qrhi.html)
- [Qt RHI Examples](https://doc.qt.io/qt-6/qtwidgets-rhi-cuberhiwidget-example.html)
- [Qt Shader Tools (qsb)](https://doc.qt.io/qt-6/qtshadertools-index.html)
## License
Same as YACReader project license.
## Author
Generated as part of the YACReader OpenGL modernization initiative.

View File

@ -0,0 +1,49 @@
# YACReader Flow RHI Shaders
This directory contains the GLSL 4.50 shaders for the QRhiWidget-based flow implementation.
## Files
- `flow.vert` - Vertex shader (GLSL 450)
- `flow.frag` - Fragment shader (GLSL 450)
- `flow.vert.qsb` - Compiled vertex shader (multi-platform)
- `flow.frag.qsb` - Compiled fragment shader (multi-platform)
- `compile_shaders.bat` - Windows compilation script
- `compile_shaders.sh` - Unix/macOS compilation script
- `shaders.qrc` - Qt resource file
## Compiling Shaders
The shaders must be compiled to `.qsb` format using Qt's `qsb` tool before building YACReader.
### Prerequisites
Ensure `qsb` is in your PATH. It's typically located in:
- Windows: `C:\Qt\6.x.x\msvc2019_64\bin\qsb.exe`
- macOS: `/opt/Qt/6.x.x/macos/bin/qsb`
- Linux: `/opt/Qt/6.x.x/gcc_64/bin/qsb`
### Compilation
**Windows:**
```cmd
cd common/rhi/shaders
compile_shaders.bat
```
**Unix/macOS:**
```bash
cd common/rhi/shaders
chmod +x compile_shaders.sh
./compile_shaders.sh
```
The compiled `.qsb` files contain shader variants for:
- OpenGL ES 2.0, 3.0
- OpenGL 2.1, 3.0+
- HLSL (Direct3D 11/12)
- Metal Shading Language (macOS/iOS)
## Note
The `.qsb` files are included in the repository for convenience. Recompile only if you modify the shader source.

View File

@ -0,0 +1,19 @@
@echo off
REM Compile shaders to .qsb format for Qt RHI
REM Requires qsb tool from Qt installation
echo Compiling flow vertex shader...
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o flow.vert.qsb flow.vert
if %ERRORLEVEL% NEQ 0 (
echo Error compiling vertex shader
exit /b 1
)
echo Compiling flow fragment shader...
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o flow.frag.qsb flow.frag
if %ERRORLEVEL% NEQ 0 (
echo Error compiling fragment shader
exit /b 1
)
echo Shader compilation complete!

View File

@ -0,0 +1,19 @@
#!/bin/bash
# Compile shaders to .qsb format for Qt RHI
# Requires qsb tool from Qt installation
echo "Compiling flow vertex shader..."
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o flow.vert.qsb flow.vert
if [ $? -ne 0 ]; then
echo "Error compiling vertex shader"
exit 1
fi
echo "Compiling flow fragment shader..."
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o flow.frag.qsb flow.frag
if [ $? -ne 0 ]; then
echo "Error compiling fragment shader"
exit 1
fi
echo "Shader compilation complete!"

View File

@ -0,0 +1,44 @@
#version 450
// Inputs from vertex shader
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec4 vColor;
layout(location = 2) in float vIsReflection;
// Output
layout(location = 0) out vec4 fragColor;
// Uniform buffer
layout(std140, binding = 0) uniform UniformBuffer
{
mat4 viewProjectionMatrix;
vec3 backgroundColor;
float _pad0;
vec3 shadingColor;
float _pad1;
float reflectionUp;
float reflectionDown;
int isReflection;
float _pad2;
};
// Texture and sampler
layout(binding = 1) uniform sampler2D coverTexture;
void main()
{
vec4 texColor = texture(coverTexture, vTexCoord);
// Apply shading: multiply texture by vColor.r to darken
float shadingAmount = vColor.r;
// For reflections, apply gradient fade (darker at bottom, fading to black)
if (vIsReflection > 0.5) {
// vTexCoord.y goes from 1 (top of reflection, near cover) to 0 (bottom, far from cover)
// We want it brightest near the cover and fading away
float gradientFade = mix(0.0, 0.33, vTexCoord.y);
shadingAmount *= gradientFade;
}
fragColor = vec4(texColor.rgb * shadingAmount, texColor.a);
}

Binary file not shown.

View File

@ -0,0 +1,59 @@
#version 450
// Per-vertex attributes
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
// Per-instance attributes (mat4 split into 4 vec4s for better D3D11 compatibility)
layout(location = 2) in vec4 instanceModel_row0;
layout(location = 3) in vec4 instanceModel_row1;
layout(location = 4) in vec4 instanceModel_row2;
layout(location = 5) in vec4 instanceModel_row3;
layout(location = 6) in vec4 instanceShading1;
layout(location = 7) in float instanceOpacity;
layout(location = 8) in float instanceFlip;
// Outputs to fragment shader
layout(location = 0) out vec2 vTexCoord;
layout(location = 1) out vec4 vColor;
layout(location = 2) out float vIsReflection;
// Uniform buffer
layout(std140, binding = 0) uniform UniformBuffer
{
mat4 viewProjectionMatrix;
vec3 backgroundColor;
float _pad0;
vec3 shadingColor;
float _pad1;
float reflectionUp;
float reflectionDown;
int isReflection;
float _pad2;
};
void main()
{
// Reconstruct instance model matrix from 4 vec4 rows
mat4 instanceModel = mat4(instanceModel_row0, instanceModel_row1, instanceModel_row2, instanceModel_row3);
gl_Position = viewProjectionMatrix * instanceModel * vec4(position, 1.0);
vTexCoord = texCoord;
// Flip texture vertically per-instance when requested (reflection)
if (instanceFlip != 0.0) {
vTexCoord.y = 1.0 - texCoord.y;
}
float leftUpShading = instanceShading1.x;
float leftDownShading = instanceShading1.y;
float rightUpShading = instanceShading1.z;
float rightDownShading = instanceShading1.w;
float leftShading = mix(leftDownShading, leftUpShading, (position.y + 0.5));
float rightShading = mix(rightDownShading, rightUpShading, (position.y + 0.5));
float shading = mix(leftShading, rightShading, (position.x + 0.5));
vColor = vec4(shading * instanceOpacity);
vIsReflection = instanceFlip;
}

Binary file not shown.

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/shaders">
<file>flow.vert.qsb</file>
<file>flow.frag.qsb</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,394 @@
// Qt RHI-based Coverflow for YACReader
// Compatible with Qt 6.7+ using QRhiWidget
#ifndef __YACREADER_FLOW_RHI_H
#define __YACREADER_FLOW_RHI_H
#include <QtGlobal>
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
#include <QRhiWidget>
#include <QtWidgets>
#include <QtGui>
#include <rhi/qrhi.h>
#include "pictureflow.h"
#include "scroll_management.h"
// Reuse enums and structs from OpenGL version
enum Performance {
low = 0,
medium,
high,
ultraHigh
};
// Cover Vector
struct YACReader3DVector {
float x;
float y;
float z;
float rot;
};
// the image/texture info struct
struct YACReader3DImageRHI {
QRhiTexture *texture;
float width;
float height;
int index;
YACReader3DVector current;
YACReader3DVector animEnd;
};
struct Preset {
/*** Animation Settings ***/
float animationStep;
float animationSpeedUp;
float animationStepMax;
float animationFadeOutDist;
float preRotation;
float viewRotateLightStrenght;
float viewRotateAdd;
float viewRotateSub;
float viewAngle;
/*** Position Configuration ***/
float cfX;
float cfY;
float cfZ;
float cfRX;
float cfRY;
float cfRZ;
float rotation;
float xDistance;
float centerDistance;
float zDistance;
float yDistance;
float zoom;
};
extern struct Preset defaultYACReaderFlowConfig;
extern struct Preset presetYACReaderFlowClassicConfig;
extern struct Preset presetYACReaderFlowStripeConfig;
extern struct Preset presetYACReaderFlowOverlappedStripeConfig;
extern struct Preset pressetYACReaderFlowUpConfig;
extern struct Preset pressetYACReaderFlowDownConfig;
class ImageLoader3D;
class ImageLoaderByteArray3D;
class YACReaderFlow3D : public QRhiWidget, public ScrollManagement
{
Q_OBJECT
protected:
int timerId;
/*** System variables ***/
YACReader3DImageRHI dummy;
int viewRotateActive;
float stepBackup;
/*functions*/
void calcPos(YACReader3DImageRHI &image, int pos);
void calcVector(YACReader3DVector &vector, int pos);
bool animate(YACReader3DVector &currentVector, YACReader3DVector &toVector);
void prepareInstanceData(const YACReader3DImageRHI &image, bool isReflection, QVector<float> &data);
int updateCount;
int fontSize;
// RHI resources
QRhiTexture *defaultTexture = nullptr;
QRhiTexture *markTexture = nullptr;
QRhiTexture *readingTexture = nullptr;
QRhiBuffer *vertexBuffer = nullptr;
QRhiBuffer *instanceBuffer = nullptr;
QRhiBuffer *uniformBuffer = nullptr;
int alignedUniformSize = 0; // Cached aligned uniform buffer size
int uniformBufferCapacity = 0; // Number of uniform slots allocated
QRhiSampler *sampler = nullptr;
QRhiGraphicsPipeline *pipeline = nullptr;
QRhiShaderResourceBindings *shaderBindings = nullptr;
// Cache of shader resource bindings per texture (to avoid recreating every frame)
QMap<QRhiTexture *, QRhiShaderResourceBindings *> shaderBindingsCache;
// Pending texture uploads (for async image loading)
struct PendingTextureUpload {
int index;
QImage image;
float x;
float y;
};
QVector<PendingTextureUpload> pendingTextureUploads;
// Uniform buffer data structure
struct UniformData {
QMatrix4x4 viewProjectionMatrix;
QVector3D backgroundColor;
float _pad0;
QVector3D shadingColor;
float _pad1;
float reflectionUp;
float reflectionDown;
int isReflection;
float _pad2;
};
void timerEvent(QTimerEvent *);
int numObjects;
int lazyPopulateObjects;
bool showMarks;
QVector<bool> loaded;
QVector<YACReaderComicReadStatus> marks;
QVector<YACReader3DImageRHI> images;
bool hasBeenInitialized;
Performance performance;
/*** Animation Settings ***/
Preset config;
int currentSelected;
YACReader3DVector centerPos;
/*** Style ***/
float shadingTop;
float shadingBottom;
float reflectionUp;
float reflectionBottom;
/*** Theme Colors ***/
QColor backgroundColor;
QColor textColor;
QColor shadingColor;
/*** System info ***/
float viewRotate;
static int updateInterval;
bool flowRightToLeft;
void startAnimationTimer();
void stopAnimationTimer();
// QRhiWidget overrides
void initialize(QRhiCommandBuffer *cb) override;
void render(QRhiCommandBuffer *cb) override;
void releaseResources() override;
void showEvent(QShowEvent *event) override;
// Helper methods
QRhiTexture *createTextureFromImage(QRhiCommandBuffer *cb, const QImage &image);
void updateUniformBuffer(QRhiCommandBuffer *cb, const UniformData &data);
void prepareMarkInstanceData(const YACReader3DImageRHI &image, QVector<float> &data);
void ensureUniformBufferCapacity(int requiredSlots);
void prepareDrawData(const YACReader3DImageRHI &image, bool isReflection, bool isMark,
const QMatrix4x4 &viewProjectionMatrix, float *outInstanceData,
UniformData &outUniformData);
void executeDrawWithOffset(QRhiCommandBuffer *cb, QRhiTexture *texture,
const float *instanceData, int uniformSlot);
protected:
QRhi *m_rhi = nullptr;
std::unique_ptr<QRhiBuffer> m_vbuf;
std::unique_ptr<QRhiBuffer> m_ubuf;
std::unique_ptr<QRhiShaderResourceBindings> m_srb;
std::unique_ptr<QRhiGraphicsPipeline> m_pipeline;
QMatrix4x4 m_viewProjection;
float m_rotation = 0.0f;
public:
YACReaderFlow3D(QWidget *parent = nullptr, struct Preset p = pressetYACReaderFlowDownConfig);
virtual ~YACReaderFlow3D();
QSize minimumSizeHint() const override;
void showPrevious();
void showNext();
void setCurrentIndex(int pos);
void cleanupAnimation();
void draw();
void updatePositions();
void insert(char *name, QRhiTexture *texture, float x, float y, int item = -1);
virtual void remove(int item);
void add(int item);
void replace(char *name, QRhiTexture *texture, float x, float y, int item);
void populate(int n);
YACReader3DImageRHI getCurrentSelected();
public slots:
void setCF_RX(int value);
void setCF_RY(int value);
void setCF_RZ(int value);
void setZoom(int zoom);
void setRotation(int angle);
void setX_Distance(int distance);
void setCenter_Distance(int distance);
void setZ_Distance(int distance);
void setCF_Y(int value);
void setCF_Z(int value);
void setY_Distance(int value);
void setFadeOutDist(int value);
void setLightStrenght(int value);
void setMaxAngle(int value);
void setPreset(const Preset &p);
void setPerformance(Performance performance);
void useVSync(bool b); // Compatibility method (no-op for RHI)
void setFlowRightToLeft(bool b);
// Theme color setters
void setBackgroundColor(const QColor &color);
void setTextColor(const QColor &color);
void setShadingColor(const QColor &color);
virtual void updateImageData() = 0;
void reset();
void reload();
void setShowMarks(bool value);
void setMarks(QVector<YACReader::YACReaderComicReadStatus> marks);
void setMarkImage(QImage &image);
void markSlide(int index, YACReader::YACReaderComicReadStatus status);
void unmarkSlide(int index);
void setSlideSize(QSize size);
void clear();
void setCenterIndex(unsigned int index);
void showSlide(int index);
int centerIndex();
void updateMarks();
void render(); // Compatibility method (triggers update())
void resizeGL(int width, int height); // Compatibility method (no-op for RHI)
QVector3D getPlaneIntersection(int x, int y, YACReader3DImageRHI plane);
void mouseDoubleClickEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
friend class ImageLoader3D;
friend class ImageLoaderByteArray3D;
signals:
void centerIndexChanged(int);
void selected(unsigned int);
};
class YACReaderComicFlow3D : public YACReaderFlow3D
{
public:
YACReaderComicFlow3D(QWidget *parent = nullptr, struct Preset p = defaultYACReaderFlowConfig);
void setImagePaths(QStringList paths);
void updateImageData() override;
void remove(int item) override;
void add(const QString &path, int index);
void resortCovers(QList<int> newOrder);
friend class ImageLoader3D;
private:
ImageLoader3D *worker;
protected:
QList<QString> paths;
};
class YACReaderPageFlow3D : public YACReaderFlow3D
{
public:
YACReaderPageFlow3D(QWidget *parent = nullptr, struct Preset p = defaultYACReaderFlowConfig);
~YACReaderPageFlow3D();
void updateImageData() override;
void populate(int n);
QVector<bool> imagesReady;
QVector<QByteArray> rawImages;
QVector<bool> imagesSetted;
friend class ImageLoaderByteArray3D;
private:
ImageLoaderByteArray3D *worker;
};
class ImageLoader3D : public QThread
{
public:
ImageLoader3D(YACReaderFlow3D *flow);
~ImageLoader3D();
bool busy() const;
void generate(int index, const QString &fileName);
void reset()
{
idx = -1;
fileName = "";
}
int index() const { return idx; }
void lock();
void unlock();
QImage result();
YACReaderFlow3D *flow;
QImage loadImage(const QString &fileName);
protected:
void run() override;
private:
QMutex mutex;
QWaitCondition condition;
bool restart;
bool working;
int idx;
QString fileName;
QSize size;
QImage img;
};
class ImageLoaderByteArray3D : public QThread
{
public:
ImageLoaderByteArray3D(YACReaderFlow3D *flow);
~ImageLoaderByteArray3D();
bool busy() const;
void generate(int index, const QByteArray &raw);
void reset()
{
idx = -1;
rawData.clear();
}
int index() const { return idx; }
QImage result();
YACReaderFlow3D *flow;
QImage loadImage(const QByteArray &rawData);
protected:
void run() override;
private:
QMutex mutex;
QWaitCondition condition;
bool restart;
bool working;
int idx;
QByteArray rawData;
QSize size;
QImage img;
};
#endif // QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
#endif // __YACREADER_FLOW_RHI_H