00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "glfboapplet.h"
00022
00023 using namespace GluonPlayer;
00024
00025 #include <QtOpenGL/QGLPixelBuffer>
00026 #include <QtOpenGL/QGLFramebufferObject>
00027 #include <QtGui/QPainter>
00028 #include <QtGui/QImage>
00029
00030 class GLFBOApplet::GLFBOAppletPrivate
00031 {
00032 public:
00033 GLFBOAppletPrivate()
00034 {
00035 init();
00036 }
00037 ~GLFBOAppletPrivate()
00038 {
00039 delete fbo;
00040 delete pbuf;
00041 delete dummy;
00042 }
00043 void init()
00044 {
00045 dummy = new QGLWidget(( QWidget* ) 0 );
00046 dummy->makeCurrent();
00047
00048 if( QGLFramebufferObject::hasOpenGLFramebufferObjects() )
00049 {
00050 fbo = new QGLFramebufferObject( 256, 256, QGLFramebufferObject::CombinedDepthStencil, GL_TEXTURE_2D, GL_RGBA );
00051
00052 if( !fbo->isValid() )
00053 fbo = new QGLFramebufferObject( 256, 256, QGLFramebufferObject::CombinedDepthStencil, GL_TEXTURE_2D, GL_RGB );
00054
00055 pbuf = 0;
00056 }
00057 else
00058 {
00059 qDebug() << "Notice: FBO's not available, falling back to pbuffer's";
00060 fbo = 0;
00061 QGLFormat format = QGLFormat::defaultFormat();
00062
00063
00064
00065 pbuf = new QGLPixelBuffer( 300, 300, format, dummy );
00066 if( pbuf->isValid() )
00067 {
00068 pbuf->makeCurrent();
00069 }
00070 }
00071 width = 300;
00072 height = 300;
00073 }
00074 void updateGlSize( const QSize& size )
00075 {
00076 if( size.width() > width || size.height() > height )
00077 {
00078 if( fbo )
00079 {
00080 GLenum intFormat = fbo->format().internalTextureFormat();
00081 delete fbo;
00082 fbo = new QGLFramebufferObject( size, QGLFramebufferObject::CombinedDepthStencil, GL_TEXTURE_2D, intFormat );
00083 }
00084 else
00085 {
00086 QGLFormat format = pbuf->format();
00087 delete pbuf;
00088 pbuf = new QGLPixelBuffer( size, format, dummy );
00089 }
00090 width = size.width();
00091 height = size.height();
00092 }
00093 }
00094
00095 public:
00096 QGLFramebufferObject* fbo;
00097 QGLPixelBuffer* pbuf;
00098 QGLWidget* dummy;
00099 float width;
00100 float height;
00101 };
00102
00103 GLFBOApplet::GLFBOApplet( QGraphicsItem* parent,
00104 const QString& serviceId,
00105 int appletId )
00106 : Plasma::Applet( parent, serviceId, appletId )
00107 , d( new GLFBOAppletPrivate )
00108 {
00109 if( d->fbo )
00110 {
00111 if( !d->fbo->isValid() )
00112 {
00113 setFailedToLaunch( true, i18n( "This system does not support Gluon's OpenGL widget." ) );
00114 }
00115 }
00116 else
00117 {
00118 if( !d->dummy->isValid() || !QGLPixelBuffer::hasOpenGLPbuffers()
00119 || !d->pbuf->isValid() )
00120 {
00121 setFailedToLaunch( true, i18n( "This system does not support Gluon's OpenGL widget." ) );
00122 }
00123 }
00124 }
00125
00126 GLFBOApplet::GLFBOApplet( QObject* parent, const QVariantList& args )
00127 : Applet( parent, args )
00128 , d( new GLFBOAppletPrivate )
00129 {
00130 if( d->fbo )
00131 {
00132 if( !d->fbo->isValid() )
00133 {
00134 setFailedToLaunch( true, i18n( "This system does not support Gluon's OpenGL widget." ) );
00135 }
00136 }
00137 else
00138 {
00139 if( !d->dummy->isValid() || !QGLPixelBuffer::hasOpenGLPbuffers()
00140 || !d->pbuf->isValid() )
00141 {
00142 setFailedToLaunch( true, i18n( "This system does not support Gluon's OpenGL widget." ) );
00143 }
00144 }
00145 }
00146
00147 GLFBOApplet::~GLFBOApplet()
00148 {
00149 delete d;
00150 }
00151
00152 GLuint GLFBOApplet::bindTexture( const QImage& image, GLenum target )
00153 {
00154
00155 if( !d->dummy->isValid() )
00156 {
00157 return 0;
00158 }
00159 return d->dummy->bindTexture( image, target );
00160 }
00161
00162 void GLFBOApplet::deleteTexture( GLuint textureId )
00163 {
00164
00165 d->dummy->deleteTexture( textureId );
00166 }
00167
00168 void GLFBOApplet::paintGLInterface( QPainter* painter,
00169 const QStyleOptionGraphicsItem* option )
00170 {
00171 Q_UNUSED( painter )
00172 Q_UNUSED( option )
00173 }
00174
00175 static inline QPainterPath headerPath( const QRectF& r, int roundness,
00176 int headerHeight = 10 )
00177 {
00178 QPainterPath path;
00179 int xRnd = roundness;
00180 int yRnd = roundness;
00181 if( r.width() > r.height() )
00182 {
00183 xRnd = int ( roundness * r.height() / r.width() );
00184 }
00185 else
00186 {
00187 yRnd = int ( roundness * r.width() / r.height() );
00188 }
00189
00190 if( xRnd >= 100 )
00191 {
00192 xRnd = 99;
00193 }
00194 if( yRnd >= 100 )
00195 {
00196 yRnd = 99;
00197 }
00198 if( xRnd <= 0 || yRnd <= 0 )
00199 {
00200 path.addRect( r );
00201 return path;
00202 }
00203
00204 QRectF rect = r.normalized();
00205
00206 if( rect.isNull() )
00207 {
00208 return path;
00209 }
00210
00211 qreal x = rect.x();
00212 qreal y = rect.y();
00213 qreal w = rect.width();
00214 qreal h = rect.height();
00215 qreal rxx = w * xRnd / 200;
00216 qreal ryy = h * yRnd / 200;
00217
00218 if( rxx < 0 )
00219 {
00220 rxx = w / 200 * xRnd;
00221 }
00222 if( ryy < 0 )
00223 {
00224 ryy = h / 200 * yRnd;
00225 }
00226 qreal rxx2 = 2 * rxx;
00227 qreal ryy2 = 2 * ryy;
00228
00229 path.arcMoveTo( x, y, rxx2, ryy2, 90 );
00230 path.arcTo( x, y, rxx2, ryy2, 90, 90 );
00231 QPointF pt = path.currentPosition();
00232 path.lineTo( x, pt.y() + headerHeight );
00233 path.lineTo( x + w, pt.y() + headerHeight );
00234 path.lineTo( x + w, pt.y() );
00235 path.arcTo( x + w - rxx2, y, rxx2, ryy2, 0, 90 );
00236 path.closeSubpath();
00237
00238 return path;
00239 }
00240
00241 void GLFBOApplet::paintInterface( QPainter* painter,
00242 const QStyleOptionGraphicsItem* option,
00243 const QRect& contentsRect )
00244 {
00245 Q_UNUSED( contentsRect )
00246 if( d->fbo )
00247 {
00248 d->dummy->makeCurrent();
00249 d->fbo->bind();
00250
00251 glClearColor( 0, 0, 0, 0 );
00252 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00253
00254 QMatrix m = painter->worldMatrix();
00255 QRect deviceRect = m.mapRect( QRect( QPoint( 23, 25 ), boundingRect().size().toSize() ) );
00256 d->updateGlSize( deviceRect.size() );
00257
00258 QPainter p( d->fbo );
00259 paintGLInterface( &p, option );
00260
00261 QImage image = d->fbo->toImage();
00262 painter->drawImage( 0, 0, image );
00263 }
00264 else
00265 {
00266 Q_ASSERT( d->pbuf );
00267 if(( !d->dummy->isValid() || !d->pbuf->isValid() ) )
00268 {
00269 if( !hasFailedToLaunch() )
00270 {
00271 setFailedToLaunch( true, i18n( "Your machine does not support Gluon's OpenGL widget." ) );
00272 }
00273
00274 return;
00275 }
00276 d->pbuf->makeCurrent();
00277
00278
00279 glClearColor( 0, 0, 0, 0 );
00280 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00281
00282 QMatrix m = painter->worldMatrix();
00283 QRect deviceRect = m.mapRect( QRect( QPoint( 23, 25 ), boundingRect().size().toSize() ) );
00284 d->updateGlSize( deviceRect.size() );
00285
00286
00287 QPainter p( d->pbuf );
00288 paintGLInterface( &p, option );
00289
00290
00291 QImage image = d->pbuf->toImage();
00292 painter->drawImage( 0, 0, image );
00293 }
00294 }
00295
00296 void GLFBOApplet::makeCurrent()
00297 {
00298 if( !d->dummy->isValid() )
00299 {
00300 d->dummy->makeCurrent();
00301 }
00302 }
00303
00304 #include "glfboapplet.moc"