Usable OpenGL ES
This commit is contained in:
@@ -80,13 +80,6 @@ if(COLOR_MANAGMENT)
|
||||
target_compile_definitions(tenmon PRIVATE "COLOR_MANAGMENT")
|
||||
endif(COLOR_MANAGMENT)
|
||||
|
||||
# not ready yet
|
||||
#option(USE_OPENGLES ON)
|
||||
if(USE_OPENGLES)
|
||||
target_compile_definitions(tenmon PRIVATE "NOU_GLES_CONTEXT")
|
||||
endif(USE_OPENGLES)
|
||||
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_include_directories(tenmon PRIVATE ${GIO_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
+31
-13
@@ -16,6 +16,7 @@
|
||||
#include <QElapsedTimer>
|
||||
|
||||
int FILTERING = 1;
|
||||
bool OpenGLES = false;
|
||||
|
||||
struct RawImageType
|
||||
{
|
||||
@@ -50,6 +51,13 @@ RawImageType getRawImageType(const RawImage *img)
|
||||
type.textureFormat = QOpenGLTexture::R32F;
|
||||
type.dataType = QOpenGLTexture::Float32;
|
||||
break;
|
||||
case RawImage::FLOAT16:
|
||||
if(img->channels() >= 3)
|
||||
type.textureFormat = QOpenGLTexture::RGBA16F;
|
||||
else
|
||||
type.textureFormat = QOpenGLTexture::R16F;
|
||||
type.dataType = QOpenGLTexture::Float16;
|
||||
break;
|
||||
default:
|
||||
qWarning() << "Invalid format" << img->type();
|
||||
break;
|
||||
@@ -128,9 +136,11 @@ void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index)
|
||||
m_image->allocateStorage();
|
||||
m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
|
||||
m_image->setWrapMode(QOpenGLTexture::ClampToEdge);
|
||||
m_image->setBorderColor(0, 0, 0, 0);
|
||||
m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, (const void*)image->data(), m_transferOptions.get());
|
||||
m_image->generateMipMaps();
|
||||
//m_image->setBorderColor(0, 0, 0, 0);
|
||||
m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, (const void*)image->data());
|
||||
//m_image->generateMipMaps();
|
||||
m_image->bind();
|
||||
f->glGenerateMipmap(GL_TEXTURE_2D);
|
||||
qDebug() << "setImage" << timer.elapsed();
|
||||
|
||||
m_unit_scale[0] = 1.0f;
|
||||
@@ -203,7 +213,7 @@ void ImageWidget::allocateThumbnails(const QStringList &paths)
|
||||
|
||||
m_thumbnailTexture->destroy();
|
||||
m_thumbnailTexture->create();
|
||||
m_thumbnailTexture->setFormat(QOpenGLTexture::RGBA16_UNorm);
|
||||
m_thumbnailTexture->setFormat(QOpenGLTexture::RGBA16F);
|
||||
m_thumbnailTexture->setSize(THUMB_SIZE, THUMB_SIZE);
|
||||
m_thumbnailTexture->setLayers(std::min((int)paths.size(), m_maxArrayLayers));
|
||||
m_thumbnailTexture->allocateStorage();
|
||||
@@ -301,7 +311,7 @@ void ImageWidget::thumbnailLoaded(const Image *image)
|
||||
makeCurrent();
|
||||
const RawImage *raw = image->thumbnail();
|
||||
if(!raw || !raw->valid())return;
|
||||
m_thumbnailTexture->setData(0, image->number(), QOpenGLTexture::RGBA, QOpenGLTexture::UInt16, raw->data(), m_transferOptions.get());
|
||||
m_thumbnailTexture->setData(0, image->number(), QOpenGLTexture::RGBA, QOpenGLTexture::Float16, raw->data());
|
||||
float a = raw->thumbAspect();
|
||||
int sizes[3] = { std::max(1, a > 1.0f ? THUMB_SIZE : (int)(THUMB_SIZE * a)), std::max(1, a < 1.0f ? THUMB_SIZE : (int)(THUMB_SIZE / a)), image->number() };
|
||||
m_sizesDirty = true;
|
||||
@@ -355,6 +365,7 @@ void ImageWidget::paintGL()
|
||||
mvp.ortho(rect());
|
||||
m_thumbnailProgram->setUniformValue("mvp", mvp);
|
||||
fx->glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_thumbnailCount);
|
||||
m_vaoThumb->release();
|
||||
|
||||
QPainter painter(this);
|
||||
const int w = width()/THUMB_SIZE_BORDER;
|
||||
@@ -417,6 +428,7 @@ void ImageWidget::paintGL()
|
||||
m_program->setUniformValue("srgb", m_srgb);
|
||||
#endif
|
||||
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
m_vao->release();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -439,19 +451,24 @@ void ImageWidget::initializeGL()
|
||||
if(fx == nullptr)
|
||||
QMessageBox::critical(this, tr("OpenGL error"), tr("Could not initialize OpenGL 3.3 context. Ensure that proper GPU driver is installed."));
|
||||
|
||||
OpenGLES = context()->isOpenGLES();
|
||||
|
||||
auto loadShader = [](const QString &file)
|
||||
{
|
||||
QFile fr(file);
|
||||
fr.open(QIODevice::ReadOnly);
|
||||
QByteArray src;
|
||||
#ifdef NOU_GLES_CONTEXT
|
||||
src = "#version 300 es\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2DArray;\n"
|
||||
"#line 1\n";
|
||||
#else
|
||||
src = "#version 330\n#line 1\n";
|
||||
#endif
|
||||
if(OpenGLES)
|
||||
{
|
||||
src = "#version 300 es\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2DArray;\n"
|
||||
"#line 1\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
src = "#version 330\n#line 1\n";
|
||||
}
|
||||
src.append(fr.readAll());
|
||||
return src;
|
||||
};
|
||||
@@ -551,6 +568,7 @@ void ImageWidget::initializeGL()
|
||||
m_thumbnailProgram->enableAttributeArray("imageSize_num");
|
||||
fx->glVertexAttribIPointer(m_thumbnailProgram->attributeLocation("imageSize_num"), 3, GL_INT, 0, nullptr);
|
||||
fx->glVertexAttribDivisor(m_thumbnailProgram->attributeLocation("imageSize_num"), 1);
|
||||
m_vaoThumb->release();
|
||||
|
||||
m_image = std::unique_ptr<QOpenGLTexture>(new QOpenGLTexture(QOpenGLTexture::Target2D));
|
||||
m_image->setFormat(QOpenGLTexture::RGB8U);
|
||||
|
||||
+5
-8
@@ -13,7 +13,6 @@
|
||||
#include <libxisf.h>
|
||||
#include "rawimage.h"
|
||||
#include "starfit.h"
|
||||
#include "wcslib/wcshdr.h"
|
||||
|
||||
#ifdef COLOR_MANAGMENT
|
||||
#include <QColorSpace>
|
||||
@@ -270,9 +269,6 @@ bool loadFITS(const QString path, ImageInfoData &info, std::shared_ptr<RawImage>
|
||||
else
|
||||
image = RawImage::fromPlanar(img);
|
||||
|
||||
if(image)
|
||||
image->convertToGLFormat();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -343,16 +339,14 @@ bool loadXISF(const QString &path, ImageInfoData &info, std::shared_ptr<RawImage
|
||||
{
|
||||
image = std::make_shared<RawImage>(tmpImage.width(), tmpImage.height(), 1, type);
|
||||
std::memcpy(image->data(), tmpImage.imageData(), tmpImage.imageDataSize() / tmpImage.channelCount());
|
||||
return true;
|
||||
}
|
||||
else if(tmpImage.channelCount() == 3 || tmpImage.channelCount() == 4)
|
||||
{
|
||||
image = RawImage::fromPlanar(tmpImage.imageData(), tmpImage.width(), tmpImage.height(), tmpImage.channelCount(), type);
|
||||
}
|
||||
if(image)
|
||||
{
|
||||
image->convertToGLFormat();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (LibXISF::Error &err)
|
||||
{
|
||||
@@ -381,8 +375,10 @@ void LoadRunable::run()
|
||||
if(!loadImage(m_file, info, rawImage))
|
||||
info.info.append({QObject::tr("Error"), QObject::tr("Failed to load image")});
|
||||
|
||||
|
||||
if(rawImage && !m_thumbnail)
|
||||
{
|
||||
rawImage->convertToGLFormat();
|
||||
timer.start();
|
||||
rawImage->calcStats();
|
||||
const RawImage::Stats &stats = rawImage->imageStats();
|
||||
@@ -418,6 +414,7 @@ void LoadRunable::run()
|
||||
if(QUALITY_RESIZE)
|
||||
rawImage->resize(THUMB_SIZE, THUMB_SIZE);
|
||||
|
||||
rawImage->convertToGLFormat();
|
||||
rawImage->convertToThumbnail();
|
||||
}
|
||||
QMetaObject::invokeMethod(m_receiver, "thumbnailLoadFinish", Qt::QueuedConnection, Q_ARG(std::shared_ptr<RawImage>, rawImage));
|
||||
|
||||
@@ -4,26 +4,39 @@
|
||||
#include <QTranslator>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*float h2f(unsigned short h)
|
||||
{
|
||||
unsigned int
|
||||
return f;
|
||||
}*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef __linux__
|
||||
setenv("LC_NUMERIC", "C", 1);
|
||||
#endif
|
||||
|
||||
bool useGLES = false;
|
||||
for(int i = 0; i < argc; i++)
|
||||
if(std::strcmp("-gles", argv[i]) == 0)
|
||||
{
|
||||
useGLES = true;
|
||||
}
|
||||
|
||||
QSurfaceFormat format;
|
||||
#ifdef NOU_GLES_CONTEXT
|
||||
format.setMajorVersion(3);
|
||||
format.setMinorVersion(0);
|
||||
format.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
printf("OpenGL ES\n");
|
||||
qDebug() << "Requesting OpenGL ES";
|
||||
#else
|
||||
format.setMajorVersion(3);
|
||||
format.setMinorVersion(3);
|
||||
//format.setOption(QSurfaceFormat::DebugContext);
|
||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||
printf("OpenGL\n");
|
||||
#endif
|
||||
if(useGLES)
|
||||
{
|
||||
format.setMajorVersion(3);
|
||||
format.setMinorVersion(0);
|
||||
format.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
}
|
||||
else
|
||||
{
|
||||
format.setMajorVersion(3);
|
||||
format.setMinorVersion(3);
|
||||
//format.setOption(QSurfaceFormat::DebugContext);
|
||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||
}
|
||||
QSurfaceFormat::setDefaultFormat(format);
|
||||
|
||||
QApplication a(argc, argv);
|
||||
|
||||
+44
-10
@@ -2,12 +2,16 @@
|
||||
#include <QDebug>
|
||||
#include <cstring>
|
||||
#include <QElapsedTimer>
|
||||
#include <QFloat16>
|
||||
|
||||
using F16 = qfloat16;
|
||||
|
||||
int THUMB_SIZE = 128;
|
||||
int THUMB_SIZE_BORDER = 138;
|
||||
int THUMB_SIZE_BORDER_Y = 158;
|
||||
double SATURATION = 0.95;
|
||||
bool QUALITY_RESIZE = true;
|
||||
extern bool OpenGLES;
|
||||
|
||||
#ifdef __SSE2__
|
||||
template<typename T, int ch>
|
||||
@@ -21,6 +25,7 @@ size_t RawImage::typeSize(RawImage::DataType type)
|
||||
case RawImage::UINT8:
|
||||
return 1;
|
||||
case RawImage::UINT16:
|
||||
case RawImage::FLOAT16:
|
||||
return 2;
|
||||
case RawImage::UINT32:
|
||||
case RawImage::FLOAT32:
|
||||
@@ -338,7 +343,7 @@ RawImage::DataType RawImage::type() const
|
||||
|
||||
uint32_t RawImage::norm() const
|
||||
{
|
||||
switch(m_type)
|
||||
switch(m_origType)
|
||||
{
|
||||
case UINT8:
|
||||
return UINT8_MAX;
|
||||
@@ -404,10 +409,10 @@ void RawImage::convertToThumbnail()
|
||||
|
||||
if(m_thumbAspect == 0.0f)
|
||||
m_thumbAspect = (float)width() / height();
|
||||
std::unique_ptr<PixelType[]> outptr = std::make_unique<PixelType[]>(THUMB_SIZE * THUMB_SIZE * 4 * sizeof(uint16_t));
|
||||
uint16_t *out = reinterpret_cast<uint16_t*>(outptr.get());
|
||||
std::unique_ptr<PixelType[]> outptr = std::make_unique<PixelType[]>(THUMB_SIZE * THUMB_SIZE * 4 * sizeof(qfloat16));
|
||||
F16 *out = reinterpret_cast<F16*>(outptr.get());
|
||||
|
||||
auto loop = [&](uint16_t *out, auto *in, auto scale)
|
||||
auto loop = [&](F16 *out, auto *in, float scale)
|
||||
{
|
||||
for(int i=0; i<THUMB_SIZE; i++)
|
||||
{
|
||||
@@ -426,7 +431,7 @@ void RawImage::convertToThumbnail()
|
||||
out[idx + 1] = in[idx2 + 1] * scale;;
|
||||
out[idx + 2] = in[idx2 + 2] * scale;;
|
||||
}
|
||||
out[idx + 3] = UINT16_MAX;
|
||||
out[idx + 3] = 1.0f;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -434,16 +439,19 @@ void RawImage::convertToThumbnail()
|
||||
switch(m_type)
|
||||
{
|
||||
case UINT8:
|
||||
loop(out, reinterpret_cast<uint8_t*>(m_pixels.get()), 256);
|
||||
loop(out, reinterpret_cast<uint8_t*>(m_pixels.get()), 1.0f/UINT8_MAX);
|
||||
break;
|
||||
case UINT16:
|
||||
loop(out, reinterpret_cast<uint16_t*>(m_pixels.get()), 1);
|
||||
loop(out, reinterpret_cast<uint16_t*>(m_pixels.get()), 1.0f/UINT16_MAX);
|
||||
break;
|
||||
case UINT32:
|
||||
loop(out, reinterpret_cast<uint32_t*>(m_pixels.get()), UINT16_MAX/(float)UINT32_MAX);
|
||||
loop(out, reinterpret_cast<uint32_t*>(m_pixels.get()), (float)(1.0/UINT32_MAX));
|
||||
break;
|
||||
case FLOAT16:
|
||||
loop(out, reinterpret_cast<F16*>(m_pixels.get()), 1.0f);
|
||||
break;
|
||||
case FLOAT32:
|
||||
loop(out, reinterpret_cast<float*>(m_pixels.get()), 65535.0);
|
||||
loop(out, reinterpret_cast<float*>(m_pixels.get()), 1.0f);
|
||||
break;
|
||||
default:
|
||||
qWarning() << "FLOAT64 should not happend";
|
||||
@@ -455,7 +463,7 @@ void RawImage::convertToThumbnail()
|
||||
m_height = THUMB_SIZE;
|
||||
m_ch = 4;
|
||||
m_channels = 3;
|
||||
m_type = UINT16;
|
||||
m_type = FLOAT16;
|
||||
}
|
||||
|
||||
void RawImage::convertToGLFormat()
|
||||
@@ -483,6 +491,17 @@ void RawImage::convertToGLFormat()
|
||||
for(size_t i = 0; i < s; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
else if(OpenGLES && m_type == UINT16)
|
||||
{
|
||||
m_original = std::move(m_pixels);
|
||||
allocate(m_width, m_height, m_channels, FLOAT16);
|
||||
m_origType = UINT16;
|
||||
F16 *dst = reinterpret_cast<F16*>(m_pixels.get());
|
||||
uint16_t *src = reinterpret_cast<uint16_t*>(m_original.get());
|
||||
|
||||
for(size_t i = 0; i < s; i++)
|
||||
dst[i] = src[i] / (float)UINT16_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
float RawImage::thumbAspect() const
|
||||
@@ -571,6 +590,21 @@ bool RawImage::pixel(int x, int y, double &r, double &g, double &b) const
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FLOAT16:
|
||||
{
|
||||
const F16 *v = static_cast<const F16*>(origData(y, x));
|
||||
if(m_channels == 1)
|
||||
{
|
||||
r = g = b = *v;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = v[0];
|
||||
g = v[1];
|
||||
b = v[2];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
UINT8,
|
||||
UINT16,
|
||||
UINT32,
|
||||
FLOAT16,
|
||||
FLOAT32,
|
||||
FLOAT64,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user