[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdegames/kwin4/src
From:       Martin Heni <martin () heni-online ! de>
Date:       2007-10-31 18:56:13
Message-ID: 1193856973.970212.1515.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 731449 by heni:

Another try to handle the performance issues of the reflections
- Split reflection calculation into several steps
- Slow down Qt graphics update on slow computers 


 M  +112 -53   kwin4view.cpp  
 M  +24 -4     kwin4view.h  
 M  +1 -1      pixmapsprite.h  
 M  +2 -1      thememanager.cpp  
 M  +2 -3      thememanager.h  


--- trunk/KDE/kdegames/kwin4/src/kwin4view.cpp #731448:731449
@@ -25,7 +25,6 @@
 #include <math.h>
 
 // Qt includes
-#include <QTimer>
 #include <QColor>
 #include <QEvent>
 #include <QTime>
@@ -46,7 +45,9 @@
 // How many time measurements for average
 #define MEASUREMENT_LIST_SIZE  50
 // How many warnings until reflections are switched off
-#define WARNING_MAX_COUNT      10
+#define WARNING_MAX_COUNT      5
+// How many milliseconds rounding error
+#define MEASUREMENT_ROUNDING_ERROR 5
 
 
 // Constructor for the view
@@ -55,11 +56,15 @@
                      ReflectionGraphicsScene* scene,
                      ThemeManager* theme, 
                      QWidget* parent)
-          : QGraphicsView(scene, parent)
+          : Themeable("theview", theme), QGraphicsView(scene, parent)
 {
   // Store attributes    
-  mScene         = scene;
-  mTheme         = theme;
+  mScene             = scene;
+  mTheme             = theme;
+  mDefaultUpdateTime = updateTime;
+  mSlowDownFactor    = 1.0;
+  mSlowCnt           = 0;
+  mReflectPhase      = 0; 
 
   // We do not need scrolling so switch it off
   setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@@ -81,9 +86,9 @@
   scene->setBackgroundBrush(QColor(0,0,128));
 
 
-  QTimer* timer = new QTimer(this);
-  connect(timer, SIGNAL(timeout()), this, SLOT(updateAndAdvance()));
-  timer->start(updateTime);
+  mTimer = new QTimer(this);
+  connect(mTimer, SIGNAL(timeout()), this, SLOT(updateAndAdvance()));
+  mTimer->start(mDefaultUpdateTime);
 
   // Game status
   mIsRunning = false;
@@ -116,7 +121,6 @@
   mReflectionSprite->hide();
 
   // Debug                      
-  mDisplayUpdateTime = updateTime;
   mFrameSprite = new QGraphicsTextItem(0, scene);
   mFrameSprite->setPos(QPointF(0.0, 0.0));
   mFrameSprite->setZValue(1000.0);
@@ -145,47 +149,118 @@
   if (mReflectionSprite) delete mReflectionSprite;
 }
 
+// Main themeable function. Called for any theme change. 
+void KWin4View::changeTheme()
+{
+  if (global_debug > 0) kDebug() << "CHANGE THEME IN VIEW ... resetting slow \
counter"; +  mDrawTimes.clear();
+  mSlowDownFactor = 1.0;
+  mSlowCnt = 0;
+  mTimer->setInterval(int(mDefaultUpdateTime*mSlowDownFactor)); 
+}
 
+
 // Advance and update canvas/scene
 void KWin4View::updateAndAdvance()
 {
+  // Time measurement (maybe remove static at some point)  
+  static bool first = true;
+  static QTime time;
+  int elapsed = time.elapsed();
+  if (first) {elapsed = 0;first=false;}
+  time.restart();
+
+  // Time display
+  mDrawTimes.append(elapsed);
+  if (mDrawTimes.size() > MEASUREMENT_LIST_SIZE) mDrawTimes.removeFirst();
+  double avg = 0.0;
+  for (int i=0; i<mDrawTimes.size(); i++) avg += mDrawTimes[i];
+  avg /= mDrawTimes.size();
+
+  // Set debug sprite
+  if (global_debug > 0)
+  {
+     mFrameSprite->setPlainText(QString("CurrentUpdate: %1 ms  AverageUpdate%2 ms  \
DefaultUpdate: %3*%4 ms"). +                  \
arg(elapsed).arg(int(avg)).arg(mDefaultUpdateTime).arg(mSlowDownFactor)); +  }
+     
+  
+  // Dynamic update of the graphics advance and update speed
+  if (mDrawTimes.size() == MEASUREMENT_LIST_SIZE && 
+      avg > mDefaultUpdateTime*mSlowDownFactor+MEASUREMENT_ROUNDING_ERROR)
+  {
+    mSlowCnt++;
+    kDebug() << "Warning " << mSlowCnt << " avg=" << avg;
+    mDrawTimes.clear();
+    if (mSlowCnt > WARNING_MAX_COUNT)
+    {
+      mSlowDownFactor = \
double(MEASUREMENT_ROUNDING_ERROR+avg)/double(mDefaultUpdateTime); +      mSlowCnt = \
0; +      mTimer->setInterval(int(mDefaultUpdateTime*mSlowDownFactor)); 
+
+      kDebug() << "SLOW COMPUTER WARNING: Decreasing graphics update speed "
+               << mDefaultUpdateTime*mSlowDownFactor<<"ms. Maybe switch off \
reflections."; +    }
+  }
+
+    
+  // Scene advance  
   scene()->advance();
   // QGV takes care of updating dirty rects, no need to call update or the whole \
scene is dirtied and repainted  // scene()->update();
 
+
+  // ====================================================================================
  // Reflections need to be done in the view otherwise the update's go wrong
   if (mReflectionRect.width() >0 && mReflectionRect.height() > 0)
   {
-    QImage image(mReflectionRect.width(), mReflectionRect.height(), \
                QImage::Format_ARGB32);
-    image.fill(Qt::transparent);
-    QPainter imagePainter(&image);
-    // imagePainter.fillRect(image.rect(),QBrush(Qt::red));
+    // Draw reflection in steps to save processing power
+    if (mReflectPhase == 0)
+    {
+      mReflectImage = QImage(mReflectionRect.width(), mReflectionRect.height(), \
QImage::Format_ARGB32); +      mReflectImage.fill(Qt::transparent);
+      QPainter imagePainter(&mReflectImage);
+      // imagePainter.fillRect(image.rect(),QBrush(Qt::red));
 
-    //Turn on all optimizations
-    imagePainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing \
                | QPainter::SmoothPixmapTransform, false);
-    imagePainter.setClipping(true);
-    imagePainter.setWorldMatrix(QMatrix(1.0,0.0,0.0,-1.0,0.0,image.height()));
-    QRect source = QRect(mReflectionRect.x(),mReflectionRect.y()-image.height(),   \
image.width(), image.height()); +      //Turn on all optimizations
+      imagePainter.setRenderHints(QPainter::Antialiasing |
+                                  QPainter::TextAntialiasing |
+                                  QPainter::SmoothPixmapTransform, false);
+      imagePainter.setClipping(true);
+      imagePainter.setWorldMatrix(QMatrix(1.0,0.0,0.0,-1.0,0.0,mReflectImage.height()));
 +      QRect source = \
QRect(mReflectionRect.x(),mReflectionRect.y()-mReflectImage.height(),  +              \
mReflectImage.width(), mReflectImage.height());  
-    bool vis = mReflectionSprite->isVisible();
-    mReflectionSprite->hide();
-    dynamic_cast<ReflectionGraphicsScene*>(scene())->setBackground(false);
-    scene()->render(&imagePainter, image.rect(), source, Qt::IgnoreAspectRatio);
-    dynamic_cast<ReflectionGraphicsScene*>(scene())->setBackground(true);
-    if (vis) mReflectionSprite->show();
-
-     // Semi transparent
-    imagePainter.setTransform(QTransform());
-    imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
-    imagePainter.drawImage(0,0,mGradientImage);
-    
-     // Set to sprite
-    QPixmap pm = QPixmap::fromImage(image);
-    mReflectionSprite->setPixmap(pm);
-    mReflectionSprite->update();
+      bool vis = mReflectionSprite->isVisible();
+      mReflectionSprite->hide();
+      dynamic_cast<ReflectionGraphicsScene*>(scene())->setBackground(false);
+      scene()->render(&imagePainter, mReflectImage.rect(), source, \
Qt::IgnoreAspectRatio); +      \
dynamic_cast<ReflectionGraphicsScene*>(scene())->setBackground(true); +      if (vis) \
mReflectionSprite->show(); +      mReflectPhase = 1;
+    }
+    // Draw reflection in steps to save processing power
+    else if (mReflectPhase == 1)
+    {
+       // Semi transparent
+      QPainter imagePainter(&mReflectImage);
+      imagePainter.setTransform(QTransform());
+      imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+      imagePainter.drawImage(0,0,mGradientImage);
+      mReflectPhase = 2;
+    }
+    // Draw reflection in steps to save processing power
+    else if (mReflectPhase == 2)
+    {
+       // Set to sprite
+      QPixmap pm = QPixmap::fromImage(mReflectImage);
+      mReflectionSprite->setPixmap(pm);
+      mReflectionSprite->update();
+      mReflectPhase = 0;
+    }
   }
+  // ====================================================================================
  
-  
 }
 
 
@@ -219,27 +294,11 @@
   }
 }
 
-// QGV drawItems function
+
+// QGV drawItems function (for debug time measurements)
 void KWin4View::drawItems(QPainter* painter, int numItems, QGraphicsItem* items[], \
const QStyleOptionGraphicsItem options[])  {
-  static bool first = true;
-  static QTime time;
-  int elapsed = time.elapsed();
-  if (first) {elapsed = 0;first=false;}
-  time.restart();
   QGraphicsView::drawItems(painter, numItems, items, options);
-
-  // Time display
-  mDrawTimes.append(elapsed);
-  if (mDrawTimes.size() > MEASUREMENT_LIST_SIZE) mDrawTimes.removeFirst();
-  double avg = 0.0;
-  for (int i=0; i<mDrawTimes.size(); i++) avg += mDrawTimes[i];
-  avg /= mDrawTimes.size();
-
-
-  if (global_debug > 0)
-     mFrameSprite->setPlainText(QString("Draw: %1 ms  Average %2 ms  Update: %3 \
                ms").arg(elapsed).arg(int(avg)).arg(mDisplayUpdateTime));
-
 }
 
 
--- trunk/KDE/kdegames/kwin4/src/kwin4view.h #731448:731449
@@ -34,7 +34,9 @@
 #include <QLinearGradient>
 #include <QImage>
 #include <QPixmap>
+#include <QTimer>
 
+
 // KDE includes
 #include <kgameio.h>
 
@@ -51,7 +53,7 @@
 /**
  * The view object which shows the graphics for the game.
  */
-class KWin4View : public QGraphicsView
+class KWin4View : public QGraphicsView, public virtual Themeable
 {
   Q_OBJECT
 
@@ -73,6 +75,12 @@
       */
     ~KWin4View();
 
+    /** Main theme manager function. Called when any theme change like
+      * a new theme or a theme size change occurs. This object needs to
+      * resiez and redraw then.
+      */
+    virtual void changeTheme();
+
     /** Initial setup of the game view.
       */
     void initGame(Score *scoreData);
@@ -186,8 +194,9 @@
     // The theme manager 
     ThemeManager* mTheme;
 
-    // Theme Queue
+    // Theme queue
     QList<int> mThemeQueue;
+    // Theme offset queque
     QList<QPoint> mThemeOffset;
     
     // The scene to plot to
@@ -213,13 +222,24 @@
     QGraphicsPixmapItem* mReflectionSprite;
     // Refection size
     QRect mReflectionRect;
+    // Paint image of reflection
+    QImage mReflectImage;
+    // Phase of reflection drawing
+    int mReflectPhase;
 
     // Debug frame rate sprite
     QGraphicsTextItem* mFrameSprite;
-    // Time between updates
-    int mDisplayUpdateTime;
     // Average update times
     QList<int> mDrawTimes;
+    
+    // Update and advance timer
+    QTimer* mTimer;
+    // Default update time [ms]
+    int mDefaultUpdateTime;
+    // Update slow down factor
+    double mSlowDownFactor;
+    // Slow incident counter
+    int mSlowCnt;
 };
 
 #endif // KWIN4_KWIN4VIEW_H
--- trunk/KDE/kdegames/kwin4/src/pixmapsprite.h #731448:731449
@@ -179,7 +179,7 @@
 
     /** Offset status.
      */
-     bool mOffsetStatus;
+    bool mOffsetStatus;
 };
 
 #endif
--- trunk/KDE/kdegames/kwin4/src/thememanager.cpp #731448:731449
@@ -130,7 +130,8 @@
 // Rescale the theme. Call all registed objects so that they can refresh.
 void ThemeManager::rescale(int scale, QPoint offset)
 {
-  if (global_debug > 0) kDebug() << "THEMEMANAGER::Rescaling theme to " << scale;
+  if (global_debug > 0)
+     kDebug() << "THEMEMANAGER::Rescaling theme to " << scale<<" offset to " << \
offset;  
   mThemeFileChanged = false;
 
--- trunk/KDE/kdegames/kwin4/src/thememanager.h #731448:731449
@@ -184,12 +184,11 @@
     void updateTheme(const QString &themefile);
     
     /** Change the scale of the theme and update all registered
-      * theme objects. If the scale did not change no action is
-      * performed!
+      * theme objects.
       * @param scale The new scale (maximum extension)
       * @param offset The new offset of the theme (left upper corner)
       */
-    void rescale(int scale,  QPoint offset);
+    void rescale(int scale, QPoint offset);
 
     /** Retrieve the theme's apsect ratio. This is stored as
       * 'aspect-ratio' key in the 'general' group of the theme.


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic