Workaround in AMD OpenGL driver bug
AMD OpenGL driver on Windows doesn't generate mipmaps for sRGB textures correctly
This commit is contained in:
+43
-3
@@ -11,6 +11,7 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
struct RawImageType
|
struct RawImageType
|
||||||
{
|
{
|
||||||
@@ -36,6 +37,8 @@ const RawImageType rawImageTypes[] = {
|
|||||||
{QOpenGLTexture::RGB, QOpenGLTexture::RGB32F, QOpenGLTexture::Float32, false}
|
{QOpenGLTexture::RGB, QOpenGLTexture::RGB32F, QOpenGLTexture::Float32, false}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool MANUAL_MIPMAP_GEN = false;
|
||||||
|
|
||||||
void setScrollRange(QScrollBar *scrollBar, int newRange)
|
void setScrollRange(QScrollBar *scrollBar, int newRange)
|
||||||
{
|
{
|
||||||
int page = scrollBar->pageStep();
|
int page = scrollBar->pageStep();
|
||||||
@@ -105,8 +108,11 @@ void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index)
|
|||||||
m_currentImg = index;
|
m_currentImg = index;
|
||||||
|
|
||||||
const RawImageType &rawImageType = rawImageTypes[image->type()];
|
const RawImageType &rawImageType = rawImageTypes[image->type()];
|
||||||
|
m_srgb = rawImageType.textureFormat == QOpenGLTexture::SRGB8 || rawImageType.textureFormat == QOpenGLTexture::SRGB8_Alpha8;
|
||||||
|
m_bwImg = rawImageType.bw;
|
||||||
|
|
||||||
m_image->destroy();
|
m_image->destroy();
|
||||||
|
m_image->setAutoMipMapGenerationEnabled(false);
|
||||||
m_image->setFormat(rawImageType.textureFormat);
|
m_image->setFormat(rawImageType.textureFormat);
|
||||||
m_image->setSize(image->width(), image->height());
|
m_image->setSize(image->width(), image->height());
|
||||||
m_image->setMipLevels([&](){ int c = 0; int s = std::min(m_imgWidth, m_imgHeight); while(s>>=1)c++; return c; }());
|
m_image->setMipLevels([&](){ int c = 0; int s = std::min(m_imgWidth, m_imgHeight); while(s>>=1)c++; return c; }());
|
||||||
@@ -115,10 +121,42 @@ void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index)
|
|||||||
m_image->setWrapMode(QOpenGLTexture::ClampToEdge);
|
m_image->setWrapMode(QOpenGLTexture::ClampToEdge);
|
||||||
m_image->setBorderColor(0, 0, 0, 0);
|
m_image->setBorderColor(0, 0, 0, 0);
|
||||||
m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, (const void*)image->data(), m_transferOptions.get());
|
m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, (const void*)image->data(), m_transferOptions.get());
|
||||||
|
|
||||||
|
auto sRGB_linear = [](cv::Point3f &pixel, const int *pos)
|
||||||
|
{
|
||||||
|
pixel.x = pixel.x <= 0.04045f ? pixel.x / 12.92f : std::pow((pixel.x + 0.055) / 1.055f, 2.4f);
|
||||||
|
pixel.y = pixel.y <= 0.04045f ? pixel.y / 12.92f : std::pow((pixel.y + 0.055) / 1.055f, 2.4f);
|
||||||
|
pixel.z = pixel.z <= 0.04045f ? pixel.z / 12.92f : std::pow((pixel.z + 0.055) / 1.055f, 2.4f);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto linear_sRGB = [](cv::Point3f &pixel, const int *pos)
|
||||||
|
{
|
||||||
|
pixel.x = pixel.x <= 0.0031308f ? pixel.x * 12.92f : 1.055f * std::pow(pixel.x , 1/2.4f) - 0.055f;
|
||||||
|
pixel.y = pixel.y <= 0.0031308f ? pixel.y * 12.92f : 1.055f * std::pow(pixel.y , 1/2.4f) - 0.055f;
|
||||||
|
pixel.z = pixel.z <= 0.0031308f ? pixel.z * 12.92f : 1.055f * std::pow(pixel.z , 1/2.4f) - 0.055f;
|
||||||
|
};
|
||||||
|
|
||||||
|
//AMD OpenGL driver on Windows doesn't generate mipmaps for sRGB textures correctly
|
||||||
|
if(m_srgb && MANUAL_MIPMAP_GEN)
|
||||||
|
{
|
||||||
|
cv::Mat img = image->mat();
|
||||||
|
img.convertTo(img, CV_32FC3, 1/255.0);
|
||||||
|
img.forEach<cv::Point3f>(sRGB_linear);
|
||||||
|
cv::Size size(img.cols, img.rows);
|
||||||
|
for(int i=1; i<m_image->mipLevels(); i++)
|
||||||
|
{
|
||||||
|
cv::Mat mip;
|
||||||
|
size /= 2;
|
||||||
|
cv::resize(img, mip, size);
|
||||||
|
mip.copyTo(img);
|
||||||
|
mip.forEach<cv::Point3f>(linear_sRGB);
|
||||||
|
mip.convertTo(mip, CV_8UC3, 255);
|
||||||
|
m_image->setData(i, rawImageType.pixelFormat, rawImageType.dataType, (const void*)mip.ptr(), m_transferOptions.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else m_image->generateMipMaps();
|
||||||
|
|
||||||
m_image->setLevelOfDetailRange(m_superpixel ? 1 : 0, m_image->mipMaxLevel());
|
m_image->setLevelOfDetailRange(m_superpixel ? 1 : 0, m_image->mipMaxLevel());
|
||||||
m_image->generateMipMaps();
|
|
||||||
m_bwImg = rawImageType.bw;
|
|
||||||
m_srgb = rawImageType.textureFormat == QOpenGLTexture::SRGB8 || rawImageType.textureFormat == QOpenGLTexture::SRGB8_Alpha8;
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,6 +389,8 @@ void ImageWidget::initializeGL()
|
|||||||
qDebug() << (char*)f->glGetString(GL_RENDERER);
|
qDebug() << (char*)f->glGetString(GL_RENDERER);
|
||||||
qDebug() << (char*)f->glGetString(GL_VERSION);
|
qDebug() << (char*)f->glGetString(GL_VERSION);
|
||||||
|
|
||||||
|
MANUAL_MIPMAP_GEN = QString((const char*)f->glGetString(GL_VENDOR)).startsWith("ATI Technologies Inc", Qt::CaseInsensitive);
|
||||||
|
|
||||||
qDebug() << context()->format();
|
qDebug() << context()->format();
|
||||||
|
|
||||||
// each vertex is x,y 2D position and s,t texture coordinates
|
// each vertex is x,y 2D position and s,t texture coordinates
|
||||||
|
|||||||
Reference in New Issue
Block a user