mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 04:59:54 +02:00
commit
a8ec4bb844
6 changed files with 67 additions and 64 deletions
|
@ -12,13 +12,13 @@
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
#include <gl/Config.h>
|
#include <gl/Config.h>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtx/component_wise.hpp>
|
#include <glm/gtx/component_wise.hpp>
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
#include <glm/gtx/vector_angle.hpp>
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include <Qt>
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QJsonDocument>
|
#include <QtCore/QJsonDocument>
|
||||||
#include <QtCore/QJsonObject>
|
#include <QtCore/QJsonObject>
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtCore/QAbstractNativeEventFilter>
|
#include <QtCore/QAbstractNativeEventFilter>
|
||||||
#include <QtCore/QMimeData>
|
#include <QtCore/QMimeData>
|
||||||
|
#include <QtCore/QThreadPool>
|
||||||
|
|
||||||
#include <QtGui/QScreen>
|
#include <QtGui/QScreen>
|
||||||
#include <QtGui/QImage>
|
#include <QtGui/QImage>
|
||||||
|
@ -419,6 +420,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
_maxOctreePPS(maxOctreePacketsPerSecond.get()),
|
_maxOctreePPS(maxOctreePacketsPerSecond.get()),
|
||||||
_lastFaceTrackerUpdate(0)
|
_lastFaceTrackerUpdate(0)
|
||||||
{
|
{
|
||||||
|
// FIXME this may be excessivly conservative. On the other hand
|
||||||
|
// maybe I'm used to having an 8-core machine
|
||||||
|
// Perhaps find the ideal thread count and subtract 2 or 3
|
||||||
|
// (main thread, present thread, random OS load)
|
||||||
|
// More threads == faster concurrent loads, but also more concurrent
|
||||||
|
// load on the GPU until we can serialize GPU transfers (off the main thread)
|
||||||
|
QThreadPool::globalInstance()->setMaxThreadCount(2);
|
||||||
|
thread()->setPriority(QThread::HighPriority);
|
||||||
thread()->setObjectName("Main Thread");
|
thread()->setObjectName("Main Thread");
|
||||||
|
|
||||||
setInstance(this);
|
setInstance(this);
|
||||||
|
@ -1287,6 +1296,9 @@ void Application::initializeUi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::paintGL() {
|
void Application::paintGL() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// paintGL uses a queued connection, so we can get messages from the queue even after we've quit
|
// paintGL uses a queued connection, so we can get messages from the queue even after we've quit
|
||||||
// and the plugins have shutdown
|
// and the plugins have shutdown
|
||||||
if (_aboutToQuit) {
|
if (_aboutToQuit) {
|
||||||
|
@ -4762,8 +4774,11 @@ void Application::updateDisplayMode() {
|
||||||
foreach(auto displayPlugin, standard) {
|
foreach(auto displayPlugin, standard) {
|
||||||
addDisplayPluginToMenu(displayPlugin, first);
|
addDisplayPluginToMenu(displayPlugin, first);
|
||||||
// This must be a queued connection to avoid a deadlock
|
// This must be a queued connection to avoid a deadlock
|
||||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::requestRender,
|
QObject::connect(displayPlugin.get(), &DisplayPlugin::requestRender, [=] {
|
||||||
this, &Application::paintGL, Qt::QueuedConnection);
|
postEvent(this, new LambdaEvent([=] {
|
||||||
|
paintGL();
|
||||||
|
}), Qt::HighEventPriority);
|
||||||
|
});
|
||||||
|
|
||||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
||||||
resizeGL();
|
resizeGL();
|
||||||
|
|
|
@ -47,6 +47,11 @@ AnimationReader::AnimationReader(const QUrl& url, const QByteArray& data) :
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationReader::run() {
|
void AnimationReader::run() {
|
||||||
|
auto originalPriority = QThread::currentThread()->priority();
|
||||||
|
if (originalPriority == QThread::InheritPriority) {
|
||||||
|
originalPriority = QThread::NormalPriority;
|
||||||
|
}
|
||||||
|
QThread::currentThread()->setPriority(QThread::LowPriority);
|
||||||
try {
|
try {
|
||||||
if (_data.isEmpty()) {
|
if (_data.isEmpty()) {
|
||||||
throw QString("Reply is NULL ?!");
|
throw QString("Reply is NULL ?!");
|
||||||
|
@ -73,6 +78,7 @@ void AnimationReader::run() {
|
||||||
} catch (const QString& error) {
|
} catch (const QString& error) {
|
||||||
emit onError(299, error);
|
emit onError(299, error);
|
||||||
}
|
}
|
||||||
|
QThread::currentThread()->setPriority(originalPriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Animation::isLoaded() const {
|
bool Animation::isLoaded() const {
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
#if THREADED_PRESENT
|
#if THREADED_PRESENT
|
||||||
|
|
||||||
|
// FIXME, for display plugins that don't block on something like vsync, just
|
||||||
|
// cap the present rate at 200
|
||||||
|
// const static unsigned int MAX_PRESENT_RATE = 200;
|
||||||
|
|
||||||
class PresentThread : public QThread, public Dependency {
|
class PresentThread : public QThread, public Dependency {
|
||||||
using Mutex = std::mutex;
|
using Mutex = std::mutex;
|
||||||
using Condition = std::condition_variable;
|
using Condition = std::condition_variable;
|
||||||
|
@ -66,8 +71,10 @@ public:
|
||||||
_context->moveToThread(this);
|
_context->moveToThread(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void run() override {
|
virtual void run() override {
|
||||||
OpenGLDisplayPlugin* currentPlugin{ nullptr };
|
OpenGLDisplayPlugin* currentPlugin{ nullptr };
|
||||||
|
thread()->setPriority(QThread::HighestPriority);
|
||||||
Q_ASSERT(_context);
|
Q_ASSERT(_context);
|
||||||
while (!_shutdown) {
|
while (!_shutdown) {
|
||||||
if (_pendingMainThreadOperation) {
|
if (_pendingMainThreadOperation) {
|
||||||
|
@ -450,4 +457,4 @@ void OpenGLDisplayPlugin::enableDeactivate() {
|
||||||
_uncustomized = true;
|
_uncustomized = true;
|
||||||
_deactivateWait.notify_one();
|
_deactivateWait.notify_one();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -50,6 +50,11 @@ GeometryReader::GeometryReader(const QUrl& url, const QByteArray& data, const QV
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryReader::run() {
|
void GeometryReader::run() {
|
||||||
|
auto originalPriority = QThread::currentThread()->priority();
|
||||||
|
if (originalPriority == QThread::InheritPriority) {
|
||||||
|
originalPriority = QThread::NormalPriority;
|
||||||
|
}
|
||||||
|
QThread::currentThread()->setPriority(QThread::LowPriority);
|
||||||
try {
|
try {
|
||||||
if (_data.isEmpty()) {
|
if (_data.isEmpty()) {
|
||||||
throw QString("Reply is NULL ?!");
|
throw QString("Reply is NULL ?!");
|
||||||
|
@ -82,6 +87,8 @@ void GeometryReader::run() {
|
||||||
qCDebug(modelnetworking) << "Error reading " << _url << ": " << error;
|
qCDebug(modelnetworking) << "Error reading " << _url << ": " << error;
|
||||||
emit onError(NetworkGeometry::ModelParseError, error);
|
emit onError(NetworkGeometry::ModelParseError, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QThread::currentThread()->setPriority(originalPriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkGeometry::NetworkGeometry(const QUrl& url, bool delayLoad, const QVariantHash& mapping, const QUrl& textureBaseUrl) :
|
NetworkGeometry::NetworkGeometry(const QUrl& url, bool delayLoad, const QVariantHash& mapping, const QUrl& textureBaseUrl) :
|
||||||
|
|
|
@ -268,6 +268,12 @@ void ImageReader::listSupportedImageFormats() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageReader::run() {
|
void ImageReader::run() {
|
||||||
|
auto originalPriority = QThread::currentThread()->priority();
|
||||||
|
if (originalPriority == QThread::InheritPriority) {
|
||||||
|
originalPriority = QThread::NormalPriority;
|
||||||
|
}
|
||||||
|
QThread::currentThread()->setPriority(QThread::LowPriority);
|
||||||
|
|
||||||
auto texture = _texture.toStrongRef();
|
auto texture = _texture.toStrongRef();
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
qCWarning(modelnetworking) << "Could not get strong ref";
|
qCWarning(modelnetworking) << "Could not get strong ref";
|
||||||
|
@ -306,6 +312,7 @@ void ImageReader::run() {
|
||||||
Q_ARG(const QImage&, image),
|
Q_ARG(const QImage&, image),
|
||||||
Q_ARG(void*, theTexture),
|
Q_ARG(void*, theTexture),
|
||||||
Q_ARG(int, originalWidth), Q_ARG(int, originalHeight));
|
Q_ARG(int, originalWidth), Q_ARG(int, originalHeight));
|
||||||
|
QThread::currentThread()->setPriority(originalPriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkTexture::setImage(const QImage& image, void* voidTexture, int originalWidth,
|
void NetworkTexture::setImage(const QImage& image, void* voidTexture, int originalWidth,
|
||||||
|
|
|
@ -50,88 +50,49 @@ void TextureMap::setLightmapOffsetScale(float offset, float scale) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME why is this in the model library? Move to GPU or GPU_GL
|
||||||
|
|
||||||
gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
|
gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
|
||||||
QImage image = srcImage;
|
QImage image = srcImage;
|
||||||
|
bool validAlpha = false;
|
||||||
int imageArea = image.width() * image.height();
|
if (image.hasAlphaChannel()) {
|
||||||
|
|
||||||
int opaquePixels = 0;
|
|
||||||
int translucentPixels = 0;
|
|
||||||
//bool isTransparent = false;
|
|
||||||
int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0;
|
|
||||||
const int EIGHT_BIT_MAXIMUM = 255;
|
|
||||||
QColor averageColor(EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM);
|
|
||||||
|
|
||||||
if (!image.hasAlphaChannel()) {
|
|
||||||
if (image.format() != QImage::Format_RGB888) {
|
|
||||||
image = image.convertToFormat(QImage::Format_RGB888);
|
|
||||||
}
|
|
||||||
// int redTotal = 0, greenTotal = 0, blueTotal = 0;
|
|
||||||
for (int y = 0; y < image.height(); y++) {
|
|
||||||
for (int x = 0; x < image.width(); x++) {
|
|
||||||
QRgb rgb = image.pixel(x, y);
|
|
||||||
redTotal += qRed(rgb);
|
|
||||||
greenTotal += qGreen(rgb);
|
|
||||||
blueTotal += qBlue(rgb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (imageArea > 0) {
|
|
||||||
averageColor.setRgb(redTotal / imageArea, greenTotal / imageArea, blueTotal / imageArea);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (image.format() != QImage::Format_ARGB32) {
|
if (image.format() != QImage::Format_ARGB32) {
|
||||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for translucency/false transparency
|
// Actual alpha channel?
|
||||||
// int opaquePixels = 0;
|
for (int y = 0; y < image.height(); ++y) {
|
||||||
// int translucentPixels = 0;
|
const QRgb* data = reinterpret_cast<const QRgb*>(image.constScanLine(y));
|
||||||
// int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0;
|
for (int x = 0; x < image.width(); ++x) {
|
||||||
for (int y = 0; y < image.height(); y++) {
|
auto alpha = qAlpha(data[x]);
|
||||||
for (int x = 0; x < image.width(); x++) {
|
if (alpha != 255) {
|
||||||
QRgb rgb = image.pixel(x, y);
|
validAlpha = true;
|
||||||
redTotal += qRed(rgb);
|
break;
|
||||||
greenTotal += qGreen(rgb);
|
|
||||||
blueTotal += qBlue(rgb);
|
|
||||||
int alpha = qAlpha(rgb);
|
|
||||||
alphaTotal += alpha;
|
|
||||||
if (alpha == EIGHT_BIT_MAXIMUM) {
|
|
||||||
opaquePixels++;
|
|
||||||
} else if (alpha != 0) {
|
|
||||||
translucentPixels++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (opaquePixels == imageArea) {
|
}
|
||||||
qCDebug(modelLog) << "Image with alpha channel is completely opaque:" << QString(srcImageName.c_str());
|
|
||||||
image = image.convertToFormat(QImage::Format_RGB888);
|
if (!validAlpha && image.format() != QImage::Format_RGB888) {
|
||||||
}
|
image = image.convertToFormat(QImage::Format_RGB888);
|
||||||
|
|
||||||
averageColor = QColor(redTotal / imageArea,
|
|
||||||
greenTotal / imageArea, blueTotal / imageArea, alphaTotal / imageArea);
|
|
||||||
|
|
||||||
//isTransparent = (translucentPixels >= imageArea / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::Texture* theTexture = nullptr;
|
gpu::Texture* theTexture = nullptr;
|
||||||
if ((image.width() > 0) && (image.height() > 0)) {
|
if ((image.width() > 0) && (image.height() > 0)) {
|
||||||
|
|
||||||
// bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
|
// bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
|
||||||
bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
|
bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
|
||||||
|
|
||||||
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
||||||
gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
||||||
if (image.hasAlphaChannel()) {
|
if (image.hasAlphaChannel()) {
|
||||||
formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
|
formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
|
||||||
formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
|
formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||||
theTexture->autoGenerateMips(-1);
|
theTexture->autoGenerateMips(-1);
|
||||||
|
|
||||||
|
// FIXME queue for transfer to GPU and block on completion
|
||||||
}
|
}
|
||||||
|
|
||||||
return theTexture;
|
return theTexture;
|
||||||
|
|
Loading…
Reference in a new issue