answered
2014-03-20 14:48:33 +0200
lbt 6514 ●41 ●48 ●51 moderator
I'm assuming you're interested in the GLES aspect, not C or Wayland. Jolla's native apps are mainly Qt/C++ so I'll assume that's what you'll end up with.
Here's some code I use. I expect there's a lot wrong with it but it works for me :)
One day I plan to create a minimal setup for using GLES for the main graphics and QML for the chrome.
See http://qt-project.org/doc/qt-5.1/qtopengl/cube.html too
You need to create your own Myitem class which extends the GLItem
in main.cpp
int main(int argc, char *argv[])
{
QScopedPointer<QGuiApplication> app(SailfishApp::application(argc, argv));
QScopedPointer<QQuickView> view(SailfishApp::createView());
qmlRegisterType<Myitem>("harbour.app.", 1, 0, "Myitem");
view->setSource(SailfishApp::pathTo("qml/harbour-myitem.qml"));
view->show();
return app->exec();
}
in glitem.h
#ifndef GLITEM_H
#define GLITEM_H
#include <QtQuick/QQuickItem>
#include <QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
class GLItem : public QQuickItem, protected QOpenGLFunctions
{
Q_OBJECT
public:
GLItem();
protected:
virtual void prep() = 0;
virtual void render() = 0;
public slots:
void paint();
void cleanup();
void sync();
private slots:
void handleWindowChanged(QQuickWindow *win);
protected:
QOpenGLShaderProgram *m_program;
};
#endif // GLITEM_H
in glitem.cpp
#include <QtQuick/qquickwindow.h>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLContext>
#include <QFile>
#include <QSurfaceFormat>
#include <QDebug>
GLItem::GLItem()
: m_program(0)
{
connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
}
void GLItem::handleWindowChanged(QQuickWindow *win)
{
if (win) {
// Connect the beforeRendering signal to our paint function.
// Since this call is executed on the rendering thread it must be
// a Qt::DirectConnection
bool before = true;
if (before)
connect(win, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
else
connect(win, SIGNAL(afterRendering()), this, SLOT(paint()), Qt::DirectConnection);
connect(win, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
// If we allow QML to do the clearing, they would clear what we paint
// and nothing would show.
if (before)
win->setClearBeforeRendering(false);
else
win->setClearBeforeRendering(true);
}
}
void GLItem::paint()
{
if (!m_program) {
m_program = new QOpenGLShaderProgram();
connect(window()->openglContext(), SIGNAL(aboutToBeDestroyed()),
this, SLOT(cleanup()), Qt::DirectConnection);
initializeOpenGLFunctions();
this->prep(); // Called once - setup here (eg create VBOs, shaders, load textures etc)
}
QRectF vpr = mapRectToScene(QRectF(0.0,0.0,width(),height()));
glViewport( vpr.x(), (window()->height() -( vpr.y() + vpr.height())),
vpr.width(), vpr.height());
// save (not sure this is needed)
float depthrange[2];
glGetFloatv(GL_DEPTH_RANGE, depthrange);
glDepthRangef(0.0, 1.0);
float depthclear;
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &depthclear);
glClearDepthf(1.0);
glClearColor(0, 0, 0, 0);
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
// actually clear all depth information
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// Bind the program and render
if (m_program->isLinked())
m_program->bind();
this->render(); // called every screendraw - do your rendering here
// restore
glDepthRangef(depthrange[0], depthrange[1]);
glClearDepthf(depthclear);
}
void GLItem::cleanup()
{
if (m_program) {
delete m_program;
m_program = 0;
}
}
void GLItem::sync(){
}
in the qml:
Myitem { id: myitem
anchors.fill: parent
MouseArea { id: bgMA
anchors.fill: parent
preventStealing: true
Connections { // eg if you add touch handlers to your c++ code
onPositionChanged: myitem.handlePositionChanged(mouse.x,mouse.y)
onPressed: myitem.handlePressed(mouse.x,mouse.y)
onReleased: myitem.handleReleased(mouse.x,mouse.y)
}
}
}