I'm trying to unit test some code that relies standard opengl operations such as shader compiling, buffer creation and shader binding . My issue is our automated system that runs the test only has access to QCoreApplication. As such, whenever I use my unit tests with QApplication or QGuiApplication it all works fine but using it with QCoreApplication, nothing works. Does anybody know if it's possible to get OpenGL running with QCoreApplication.
The simple setup is below for reference
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
_app = std::make_shared<QApplication>(argc, nullptr);
QSurfaceFormat format;
format.setMajorVersion(3);
format.setMinorVersion(0);
context = std::make_shared<QOpenGLContext>();
context->setFormat(format);
context->create();
surface = std::make_shared<QOffscreenSurface>();
surface->create();
std::cout << "Open Gl Surface: " << surface->isValid() << "\n";
context->makeCurrent(surface.get());
Related
I'm currently working with a program for predicting the locations of satellites in real-time. Something similar to this. The underlying library uses system time as input.
time_t now(time(0));
This program accurately predicts the real-time position of satellites when I run it on a C++ console application using Qt Creator.
The problem is when I use it in a fully-fledged Qt Gui application with a QApplication object in the main function. In the program, the prediction function is periodically by the timer event function. That way I update the positions every 2 seconds. Unfortunately, The output doesn't match (either on the GUI or when I print it). It is like the orbital propagator is using a different time when calculating the satellite positions.
void TrackingManager::timerEvent(QTimerEvent *event)
{
int nNumSats = m_Satellites.size() ;
//std::cout << __func__ << " - Number of satellites = " << nNumSats << std::endl;
std::vector<SatPosition> vSatPositions;
if (nNumSats >= 0)
{
time_t now(time(0));
std::cout << __func__ << "time(0) = " << asctime(gmtime(&now)) << std::endl;
for(int i = 0; i < nNumSats; i++)
{
// Get satellite names and calculate position, altitude etc
SatPosition spPos;
GetInstantPredict(m_Satellites[i], now, spPos);
vSatPositions.push_back(spPos);
}
emit UpdateSatPosition(vSatPositions);
}
}
Even more confusing, the program works fine when I run the debugger (GDB on Ubuntu). It is as if GDB somehow manages to "fix" the problem. Does this make any sense?
I have no idea why, but i canĀ“t get the simplest example of QTemporaryFile to run... My real intent is to write data from QAudioInput into a temporary file before it is processed later.
After trying several times I realized that neither .read(), .readLine(), .readAll() or .write() would have any effect... The error string is always "Unknown Error" and it neither works for QFile or QTemporaryFile.
#include <QCoreApplication>
#include <QTemporaryFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTemporaryFile tf;
tf.open();
tf.write("Test");
QTextStream in(&tf);
qDebug() << "Testprogramm";
qDebug() << tf.isOpen();
qDebug() << tf.errorString();
qDebug() << in.readLine();
qDebug() << tf.readAll();
tf.close();
return a.exec();
}
The debug posts:
Testprogramm
true
"Unknown error"
""
""
Thank you in advance!
You need to move the file pointer back to the beginning of the file. This has to be done on the file itself when there's no stream on the file, or using the stream when one exists. Also - QFile is a proper C++ class that manages the file resource. There's no need to manually close the file. QFile::~QFile does that job.
The following works just fine:
#include <QtCore>
int main() {
auto line = QLatin1String("Test");
QTemporaryFile tf;
tf.open();
Q_ASSERT(tf.isOpen());
tf.write(line.data());
tf.reset(); // or tf.seek(0)
QTextStream in(&tf);
Q_ASSERT(in.readLine() == line);
in.seek(0); // not in.reset() nor tf.reset()!
Q_ASSERT(in.readLine() == line);
}
The above also demonstrates the following techniques applicable to sscce-style code:
Inclusion of entire Qt module(s). Remember that modules include their dependencies, i.e. #include <QtWidgets> is sufficient by itself.
Absence of main() arguments where unnecessary.
Absence of QCoreApplication instance where unnecessary. You will get clear runtime errors if you need the application instance but don't have one.
Use of asserts to indicate conditions that are expected to be true - that way you don't need to look at the output to verify that it is correct.
Use of QLatin1String over QStringLiteral where ASCII strings need to be compared to both C strings and QStrings. Implicit ASCII casts can be a source of bugs and are discouraged.
QLatin1String is a constant (read-only) wrapper, designed to wrap C string literals - thus there's no need to make line additionally const, although in real projects you'd want to follow the project's style guide here.
I'm making a simple Qt app that reads stuff from a CSV file and generates a PCAP data file out of it for reading by some other software.
And so soon as I invoque pcap_open_dead, pcap_dump_open or pcap_dump, I get no more console output upon running my small converter. Even the Hello World that comes at the beginning of the main doesn't show up any more. From the code below, if I simply comment out those three methods, the console output and "Hello World" come back.
Being new and therefore clueless about pcap, I ask for help.
#include <QCoreApplication>
#include <iostream>
#include "pcap.h"
using namespace std;
struct pcapWriter_S
{
bool isAvailable;
int m_OutPcapIpId;
pcap_t* m_OutPcapHandle;
pcap_dumper_t* m_OutPcapFile;
}m_pcapWriter;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cout << "Hello World!" << endl;
//m_pcapWriter.m_OutPcapHandle = pcap_open_dead(DLT_EN10MB,65535);
//m_pcapWriter.m_OutPcapFile = pcap_dump_open(m_pcapWriter.m_OutPcapHandle, QString("tmp_csv_out.pcap").toAscii().data());
m_pcapWriter.m_OutPcapIpId = 1;
if (m_pcapWriter.m_OutPcapFile != 0)
{
m_pcapWriter.isAvailable = true;
}
QByteArray pkt_data;
// Omitted code to generate pkt data from input file
m_pcapWriter.m_OutPcapIpId++;
//pcap_dump((unsigned char*)m_pcapWriter.m_OutPcapFile, &header, (unsigned char*)pkt_data.data());
return a.exec();
}
Somehow this was due to me calling pcap_open but not pcap_close quite yet. In between console stuff gets lost - can't swear it gets written on the pcap thing but it blocks the console anyway.
I set a QSurfaceFormat on my window, and this surface format has "3.0" set as its GL version number. The code:
static QSurfaceFormat createSurfaceFormat() {
QSurfaceFormat format;
format.setSamples(4);
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setVersion(3, 0);
return format;
}
int main(int argc, char *argv[]) {
// ...
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QWindow* window = (QWindow*) engine.rootObjects().first();
window->setFormat(::createSurfaceFormat());
// ...
}
Also, in main() I enable OpenGL ES mode, like this:
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES);
This means I'm requesting a GL ES 3.0 context.
The ANGLE docs say (in a table near the beginning) that GL ES 3.0 -> D3D 11 API translation support is implemented. And my system supports D3D 11 according to dxdiag.exe.
But when I launch my app, which contains this QML code...
Text {
text: OpenGLInfo.majorVersion + "." + OpenGLInfo.minorVersion
}
... I see "2.0" is displayed. Also, using the method I described here, I've determined that the maximal supported shading language version on my PC is "100" aka 1.0.
At the same time, from this Qt blog post I know that Qt supports GL ES 3.0 apps.
So why can't I use OpenGL ES 3.0 in Qt?
You need to set a QSurfaceFormat on a QWindow before the window itself is created (via create()). If you create top level windows via QML you have no control on when create() gets actually called, so a solution is changing the default surface format somwhere before you create your Q(Gui)Application:
int main(int argc, char **argv) {
// createSurfaceFormat() is the function you pasted above
QSurfaceFormat::setDefaultFormat(createSurfaceFormat());
QApplication app(argc, argv);
// etc.
I'm having a problem writing directly to a disk, I'm trying to write a Qt version of the old PARTCOPY (now obsolete on systems incompatible with 16-bit)
I'm using Windows 10, and have my program elevated to Administrator privileges.
Every time I try to open "\\.\A:" in with QIODevice::WriteOnly, I get an error message "The parameter is incorrect".
Using Visual Studio step-wise debugging, I think I've found the problem occurs in QFSEnginePrivate::nativeOpen() when tring to execute CreateFile().
The line:
// WriteOnly can create files, ReadOnly cannot.
DWORD creationDisp = (openMode & QIODevice::WriteOnly) ? OPEN_ALWAYS : OPEN_EXISTING;
seems to be the cause. If I force the value of creationDisp to be OPEN_EXISTING, then I can get the file opened and I can write to the disk without any further problems. The issue is that I don't know what way I can get this working without using the debugger.
Has anyone found a solution to this?
UPDATE: (test case)
#include <QtCore/qcoreapplication.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qfile.h>
int main(int argc, char **argv) {
QCoreApplication a(argc, argv);
QTextStream cout(stdout, QIODevice::WriteOnly);
QFile f("\\\\.\\A:");
if (!f.open(QIODevice::WriteOnly)) {
cout << f.errorString();
return -1;
}
return 0;
}
You can try these two functions, I write successfully by (1).
bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags = DontCloseHandle)
bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags = DontCloseHandle)