examples: Fix Qt/GL qglwtextureshare example for X11

We need to pass the X11 display to GstGL or else it will
use its own X11 Display pointer, and the GL Context won't get shared
correctly on newer X servers
This commit is contained in:
Jan Schmidt 2014-09-29 00:23:57 +10:00 committed by Tim-Philipp Müller
parent 491513adf6
commit 6b96a87003
7 changed files with 378 additions and 318 deletions

View file

@ -1,3 +1,6 @@
Requires: >= Qt 5.1 for the x11extras module (or else you need to
get x11extras from gitorious yourself)
This example illustrates how to integrate Gstreamer GL plugin with This example illustrates how to integrate Gstreamer GL plugin with
Qt. In particular it uses glupload with fakesink elements to create Qt. In particular it uses glupload with fakesink elements to create
texture with decoded video frame. This texture is shared with texture with decoded video frame. This texture is shared with

View file

@ -23,15 +23,15 @@
#include "gstthread.h" #include "gstthread.h"
GstThread::GstThread(GstGLContext *context, GstThread::GstThread(GstGLDisplay *display,
GstGLContext *context,
const QString &videoLocation, const QString &videoLocation,
const char *renderer_slot, const char *renderer_slot,
QObject *parent): QObject *parent):
QThread(parent), QThread(parent),
m_videoLocation(videoLocation) m_videoLocation(videoLocation)
{ {
this->context = context; m_pipeline = new Pipeline(display, context, m_videoLocation, this);
m_pipeline = new Pipeline(this->context, m_videoLocation, this);
QObject::connect(m_pipeline, SIGNAL(newFrameReady()), this->parent(), renderer_slot, Qt::QueuedConnection); QObject::connect(m_pipeline, SIGNAL(newFrameReady()), this->parent(), renderer_slot, Qt::QueuedConnection);
} }

View file

@ -34,7 +34,8 @@ class GstThread : public QThread
Q_OBJECT Q_OBJECT
public: public:
GstThread(GstGLContext *context, GstThread(GstGLDisplay *display,
GstGLContext *context,
const QString &videoLocation, const QString &videoLocation,
const char *renderer_slot, const char *renderer_slot,
QObject *parent = 0); QObject *parent = 0);
@ -50,7 +51,6 @@ protected:
void run(); void run();
private: private:
GstGLContext *context;
const QString m_videoLocation; const QString m_videoLocation;
Pipeline* m_pipeline; Pipeline* m_pipeline;
}; };

View file

@ -22,15 +22,16 @@
#include "pipeline.h" #include "pipeline.h"
Pipeline::Pipeline(GstGLContext *context, Pipeline::Pipeline (GstGLDisplay *display,
const QString &videoLocation, GstGLContext * context, const QString & videoLocation, QObject * parent)
QObject *parent) :
: QObject(parent), QObject (parent),
m_videoLocation (videoLocation), m_videoLocation (videoLocation),
m_loop (NULL), m_loop (NULL),
m_bus (NULL), m_bus (NULL),
m_pipeline (NULL) m_pipeline (NULL)
{ {
this->display = display;
this->context = context; this->context = context;
this->configure (); this->configure ();
} }
@ -47,49 +48,47 @@ Pipeline::configure()
m_loop = g_main_loop_new (NULL, FALSE); m_loop = g_main_loop_new (NULL, FALSE);
#endif #endif
if(m_videoLocation.isEmpty()) if (m_videoLocation.isEmpty ()) {
{
qDebug ("No video file specified. Using video test source."); qDebug ("No video file specified. Using video test source.");
m_pipeline = m_pipeline =
GST_PIPELINE (gst_parse_launch GST_PIPELINE (gst_parse_launch
("videotestsrc ! " ("videotestsrc ! "
"video/x-raw, width=640, height=480, " "video/x-raw, width=640, height=480, "
"framerate=(fraction)30/1 ! " "framerate=(fraction)30/1 ! "
"gleffects effect=5 ! fakesink sync=1", "gleffects effect=5 ! fakesink sync=1", NULL));
NULL)); } else {
}
else
{
QByteArray ba = m_videoLocation.toLocal8Bit (); QByteArray ba = m_videoLocation.toLocal8Bit ();
qDebug ("Loading video: %s", ba.data ()); qDebug ("Loading video: %s", ba.data ());
gchar *pipeline = g_strdup_printf ("filesrc location='%s' ! " gchar *pipeline = g_strdup_printf ("filesrc name=f ! "
"decodebin ! gleffects effect=5 ! " "decodebin ! gleffects effect=5 ! " "fakesink sync=1");
"fakesink sync=1", ba.data());
m_pipeline = GST_PIPELINE (gst_parse_launch (pipeline, NULL)); m_pipeline = GST_PIPELINE (gst_parse_launch (pipeline, NULL));
GstElement *f = gst_bin_get_by_name (GST_BIN (m_pipeline), "f");
g_object_set (G_OBJECT (f), "location", ba.data (), NULL);
gst_object_unref (GST_OBJECT (f));
g_free (pipeline); g_free (pipeline);
} }
m_bus = gst_pipeline_get_bus (GST_PIPELINE (m_pipeline)); m_bus = gst_pipeline_get_bus (GST_PIPELINE (m_pipeline));
gst_bus_add_watch (m_bus, (GstBusFunc) bus_call, this); gst_bus_add_watch (m_bus, (GstBusFunc) bus_call, this);
gst_bus_enable_sync_message_emission (m_bus);
g_signal_connect (m_bus, "sync-message", G_CALLBACK (sync_bus_call), this);
gst_object_unref (m_bus); gst_object_unref (m_bus);
/* Retrieve the last gl element */ /* Retrieve the last gl element */
GstElement *gl_element = gst_bin_get_by_name(GST_BIN(m_pipeline), "gleffects0"); GstElement *gl_element =
if(!gl_element) gst_bin_get_by_name (GST_BIN (m_pipeline), "gleffects0");
{ if (!gl_element) {
qDebug ("gl element could not be found"); qDebug ("gl element could not be found");
return; return;
} }
g_object_set(G_OBJECT (gl_element), "other-context", g_object_set (G_OBJECT (gl_element), "other-context", this->context, NULL);
this->context, NULL);
gst_object_unref (gl_element); gst_object_unref (gl_element);
gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_PAUSED); gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_PAUSED);
GstState state = GST_STATE_PAUSED; GstState state = GST_STATE_PAUSED;
if (gst_element_get_state (GST_ELEMENT (this->m_pipeline), if (gst_element_get_state (GST_ELEMENT (this->m_pipeline),
&state, NULL, GST_CLOCK_TIME_NONE) &state, NULL, GST_CLOCK_TIME_NONE)
!= GST_STATE_CHANGE_SUCCESS) != GST_STATE_CHANGE_SUCCESS) {
{
qDebug ("failed to pause pipeline"); qDebug ("failed to pause pipeline");
return; return;
} }
@ -107,14 +106,12 @@ Pipeline::start()
GstStateChangeReturn ret = GstStateChangeReturn ret =
gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_PLAYING); gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) if (ret == GST_STATE_CHANGE_FAILURE) {
{
qDebug ("Failed to start up pipeline!"); qDebug ("Failed to start up pipeline!");
/* check if there is an error message with details on the bus */ /* check if there is an error message with details on the bus */
GstMessage *msg = gst_bus_poll (this->m_bus, GST_MESSAGE_ERROR, 0); GstMessage *msg = gst_bus_poll (this->m_bus, GST_MESSAGE_ERROR, 0);
if (msg) if (msg) {
{
GError *err = NULL; GError *err = NULL;
gst_message_parse_error (msg, &err, NULL); gst_message_parse_error (msg, &err, NULL);
qDebug ("ERROR: %s", err->message); qDebug ("ERROR: %s", err->message);
@ -123,7 +120,6 @@ Pipeline::start()
} }
return; return;
} }
#ifdef Q_WS_WIN #ifdef Q_WS_WIN
g_main_loop_run (m_loop); g_main_loop_run (m_loop);
#endif #endif
@ -132,9 +128,7 @@ Pipeline::start()
/* fakesink handoff callback */ /* fakesink handoff callback */
void void
Pipeline::on_gst_buffer (GstElement * element, Pipeline::on_gst_buffer (GstElement * element,
GstBuffer * buf, GstBuffer * buf, GstPad * pad, Pipeline * p)
GstPad * pad,
Pipeline* p)
{ {
Q_UNUSED (pad) Q_UNUSED (pad)
Q_UNUSED (element) Q_UNUSED (element)
@ -147,8 +141,7 @@ Pipeline::on_gst_buffer(GstElement * element,
p->notifyNewFrame (); p->notifyNewFrame ();
/* pop then unref buffer we have finished to use in qt */ /* pop then unref buffer we have finished to use in qt */
if (p->queue_output_buf.size() > 3) if (p->queue_output_buf.size () > 3) {
{
GstBuffer *buf_old = (p->queue_output_buf.get ()); GstBuffer *buf_old = (p->queue_output_buf.get ());
if (buf_old) if (buf_old)
gst_buffer_unref (buf_old); gst_buffer_unref (buf_old);
@ -171,13 +164,11 @@ Pipeline::unconfigure()
gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_NULL); gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_NULL);
GstBuffer *buf; GstBuffer *buf;
while(this->queue_input_buf.size()) while (this->queue_input_buf.size ()) {
{
buf = (GstBuffer *) (this->queue_input_buf.get ()); buf = (GstBuffer *) (this->queue_input_buf.get ());
gst_buffer_unref (buf); gst_buffer_unref (buf);
} }
while(this->queue_output_buf.size()) while (this->queue_output_buf.size ()) {
{
buf = (GstBuffer *) (this->queue_output_buf.get ()); buf = (GstBuffer *) (this->queue_output_buf.get ());
gst_buffer_unref (buf); gst_buffer_unref (buf);
} }
@ -185,13 +176,11 @@ Pipeline::unconfigure()
gst_object_unref (m_pipeline); gst_object_unref (m_pipeline);
} }
gboolean gboolean Pipeline::bus_call (GstBus * bus, GstMessage * msg, Pipeline * p)
Pipeline::bus_call(GstBus *bus, GstMessage *msg, Pipeline* p)
{ {
Q_UNUSED (bus) Q_UNUSED (bus)
switch(GST_MESSAGE_TYPE(msg)) switch (GST_MESSAGE_TYPE (msg)) {
{
case GST_MESSAGE_EOS: case GST_MESSAGE_EOS:
qDebug ("End-of-stream received. Stopping."); qDebug ("End-of-stream received. Stopping.");
p->stop (); p->stop ();
@ -199,13 +188,14 @@ Pipeline::bus_call(GstBus *bus, GstMessage *msg, Pipeline* p)
case GST_MESSAGE_ERROR: case GST_MESSAGE_ERROR:
{ {
gchar *debug = NULL; gchar *
GError *err = NULL; debug = NULL;
GError *
err = NULL;
gst_message_parse_error (msg, &err, &debug); gst_message_parse_error (msg, &err, &debug);
qDebug ("Error: %s", err->message); qDebug ("Error: %s", err->message);
g_error_free (err); g_error_free (err);
if(debug) if (debug) {
{
qDebug ("Debug deails: %s", debug); qDebug ("Debug deails: %s", debug);
g_free (debug); g_free (debug);
} }
@ -219,3 +209,27 @@ Pipeline::bus_call(GstBus *bus, GstMessage *msg, Pipeline* p)
return TRUE; return TRUE;
} }
gboolean Pipeline::sync_bus_call (GstBus * bus, GstMessage * msg, Pipeline * p)
{
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_NEED_CONTEXT:
{
const gchar *
context_type;
gst_message_parse_context_type (msg, &context_type);
g_print ("got need context %s\n", context_type);
if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
GstContext *display_context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
gst_context_set_gl_display (display_context, p->display);
gst_element_set_context (GST_ELEMENT (msg->src), display_context);
}
break;
}
default:
break;
}
return FALSE;
}

View file

@ -34,7 +34,7 @@ class Pipeline : public QObject
Q_OBJECT Q_OBJECT
public: public:
Pipeline(GstGLContext *context, Pipeline(GstGLDisplay *display, GstGLContext *context,
const QString &videoLocation, const QString &videoLocation,
QObject *parent); QObject *parent);
~Pipeline(); ~Pipeline();
@ -53,6 +53,7 @@ Q_SIGNALS:
void stopRequested(); void stopRequested();
private: private:
GstGLDisplay *display;
GstGLContext *context; GstGLContext *context;
const QString m_videoLocation; const QString m_videoLocation;
GMainLoop* m_loop; GMainLoop* m_loop;
@ -64,6 +65,7 @@ private:
static void on_gst_buffer(GstElement * element, GstBuffer * buf, GstPad * pad, Pipeline* p); static void on_gst_buffer(GstElement * element, GstBuffer * buf, GstPad * pad, Pipeline* p);
static gboolean bus_call (GstBus *bus, GstMessage *msg, Pipeline* p); static gboolean bus_call (GstBus *bus, GstMessage *msg, Pipeline* p);
static gboolean sync_bus_call (GstBus *bus, GstMessage *msg, Pipeline* p);
}; };
#endif #endif

View file

@ -25,22 +25,27 @@
#include <QDebug> #include <QDebug>
#include <QCloseEvent> #include <QCloseEvent>
#include <GL/glx.h>
#include <gst/video/video.h> #include <gst/video/video.h>
#include <gst/gl/gstglmemory.h> #include <gst/gl/gstglmemory.h>
#if GST_GL_HAVE_PLATFORM_GLX
#include <QX11Info>
#include <gst/gl/x11/gstgldisplay_x11.h>
#endif
#include "gstthread.h" #include "gstthread.h"
#include "qglrenderer.h" #include "qglrenderer.h"
#include "pipeline.h" #include "pipeline.h"
#include <GL/glx.h>
#if defined(Q_WS_MAC) #if defined(Q_WS_MAC)
extern void *qt_current_nsopengl_context (); extern void *qt_current_nsopengl_context ();
#endif #endif
QGLRenderer::QGLRenderer(const QString &videoLocation, QGLRenderer::QGLRenderer (const QString & videoLocation, QWidget * parent)
QWidget *parent) :
: QGLWidget(parent), QGLWidget (parent),
videoLoc (videoLocation), videoLoc (videoLocation),
gst_thread (NULL), gst_thread (NULL),
closing (false), closing (false),
@ -60,15 +65,28 @@ QGLRenderer::initializeGL()
GstGLContext *context; GstGLContext *context;
GstGLDisplay *display; GstGLDisplay *display;
#if GST_GL_HAVE_PLATFORM_GLX
display =
(GstGLDisplay *) gst_gl_display_x11_new_with_display (QX11Info::
display ());
#else
display = gst_gl_display_new (); display = gst_gl_display_new ();
#endif
/* FIXME: Allow the choice at runtime */ /* FIXME: Allow the choice at runtime */
#if GST_GL_HAVE_PLATFORM_WGL #if GST_GL_HAVE_PLATFORM_WGL
context = gst_gl_context_new_wrapped (display, (guintptr) wglGetCurrentContext (), GST_GL_PLATFORM_WGL, GST_GL_API_OPENGL); context =
gst_gl_context_new_wrapped (display, (guintptr) wglGetCurrentContext (),
GST_GL_PLATFORM_WGL, GST_GL_API_OPENGL);
#elif GST_GL_HAVE_PLATFORM_CGL #elif GST_GL_HAVE_PLATFORM_CGL
context = gst_gl_context_new_wrapped (display, (guintptr) qt_current_nsopengl_context(), GST_GL_PLATFORM_CGL, GST_GL_API_OPENGL); context =
gst_gl_context_new_wrapped (display,
(guintptr) qt_current_nsopengl_context (), GST_GL_PLATFORM_CGL,
GST_GL_API_OPENGL);
#elif GST_GL_HAVE_PLATFORM_GLX #elif GST_GL_HAVE_PLATFORM_GLX
context = gst_gl_context_new_wrapped (display, (guintptr) glXGetCurrentContext (), GST_GL_PLATFORM_GLX, GST_GL_API_OPENGL); context =
gst_gl_context_new_wrapped (display, (guintptr) glXGetCurrentContext (),
GST_GL_PLATFORM_GLX, GST_GL_API_OPENGL);
#endif #endif
gst_object_unref (display); gst_object_unref (display);
@ -76,7 +94,8 @@ QGLRenderer::initializeGL()
// Otherwise the attempt to share gst-gl context with Qt will fail. // Otherwise the attempt to share gst-gl context with Qt will fail.
this->doneCurrent (); this->doneCurrent ();
this->gst_thread = this->gst_thread =
new GstThread(context, this->videoLoc, SLOT(newFrame()), this); new GstThread (display, context, this->videoLoc,
SLOT (newFrame ()), this);
this->makeCurrent (); this->makeCurrent ();
QObject::connect (this->gst_thread, SIGNAL (finished ()), QObject::connect (this->gst_thread, SIGNAL (finished ()),
@ -124,7 +143,9 @@ QGLRenderer::newFrame()
this->updateGL (); this->updateGL ();
} }
static void flushGstreamerGL(GstGLContext* context,void *data){ static void
flushGstreamerGL (GstGLContext * context, void *data G_GNUC_UNUSED)
{
context->gl_vtable->Flush (); context->gl_vtable->Flush ();
} }
@ -135,8 +156,7 @@ QGLRenderer::paintGL()
static GLfloat yrot = 0; static GLfloat yrot = 0;
static GLfloat zrot = 0; static GLfloat zrot = 0;
if (this->frame) if (this->frame) {
{
guint tex_id; guint tex_id;
GstMemory *mem; GstMemory *mem;
GstVideoInfo v_info; GstVideoInfo v_info;
@ -164,8 +184,7 @@ QGLRenderer::paintGL()
glEnable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, tex_id); glBindTexture (GL_TEXTURE_2D, tex_id);
if(glGetError () != GL_NO_ERROR) if (glGetError () != GL_NO_ERROR) {
{
qDebug ("failed to bind texture that comes from gst-gl"); qDebug ("failed to bind texture that comes from gst-gl");
emit closeRequested (); emit closeRequested ();
return; return;
@ -173,10 +192,8 @@ QGLRenderer::paintGL()
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -191,35 +208,59 @@ QGLRenderer::paintGL()
glBegin (GL_QUADS); glBegin (GL_QUADS);
// Front Face // Front Face
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f (1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glVertex3f (-1.0f, -1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f (0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f (1.0f, -1.0f, 1.0f);
glTexCoord2f (0.0f, 1.0f);
glVertex3f (1.0f, 1.0f, 1.0f);
glTexCoord2f (1.0f, 1.0f);
glVertex3f (-1.0f, 1.0f, 1.0f);
// Back Face // Back Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f (0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f (-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f (0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glVertex3f (-1.0f, 1.0f, -1.0f);
glTexCoord2f (1.0f, 1.0f);
glVertex3f (1.0f, 1.0f, -1.0f);
glTexCoord2f (1.0f, 0.0f);
glVertex3f (1.0f, -1.0f, -1.0f);
// Top Face // Top Face
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f (1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f (-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f (1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glVertex3f (-1.0f, 1.0f, 1.0f);
glTexCoord2f (0.0f, 0.0f);
glVertex3f (1.0f, 1.0f, 1.0f);
glTexCoord2f (0.0f, 1.0f);
glVertex3f (1.0f, 1.0f, -1.0f);
// Bottom Face // Bottom Face
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f (1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glVertex3f (-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f (0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f (1.0f, -1.0f, -1.0f);
glTexCoord2f (0.0f, 1.0f);
glVertex3f (1.0f, -1.0f, 1.0f);
glTexCoord2f (1.0f, 1.0f);
glVertex3f (-1.0f, -1.0f, 1.0f);
// Right face // Right face
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f (0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glVertex3f (1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f (0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glVertex3f (1.0f, 1.0f, -1.0f);
glTexCoord2f (1.0f, 1.0f);
glVertex3f (1.0f, 1.0f, 1.0f);
glTexCoord2f (1.0f, 0.0f);
glVertex3f (1.0f, -1.0f, 1.0f);
// Left Face // Left Face
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f (1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f (-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f (0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f (-1.0f, -1.0f, 1.0f);
glTexCoord2f (0.0f, 1.0f);
glVertex3f (-1.0f, 1.0f, 1.0f);
glTexCoord2f (1.0f, 1.0f);
glVertex3f (-1.0f, 1.0f, -1.0f);
glEnd (); glEnd ();
xrot += 0.3f; xrot += 0.3f;
@ -235,8 +276,7 @@ QGLRenderer::paintGL()
void void
QGLRenderer::closeEvent (QCloseEvent * event) QGLRenderer::closeEvent (QCloseEvent * event)
{ {
if(this->closing == false) if (this->closing == false) {
{
this->closing = true; this->closing = true;
emit closeRequested (); emit closeRequested ();
event->ignore (); event->ignore ();

View file

@ -37,6 +37,7 @@ unix:!mac {
-lgstgl-1.0 \ -lgstgl-1.0 \
-lGLU \ -lGLU \
-lGL -lGL
QT += x11extras
} }
mac { mac {
DEFINES += MACOSX DEFINES += MACOSX