PDA

View Full Version : QT App performance is too slow on OSX



joshhhab
27th May 2011, 22:37
Hello! First of all - i'm not programmer, just tester. I test an app that use grabWindow function to capture screen and get average color.
We have compiled our program for Win/Linux/Mac and for Win/Linux app performance is much much higher about 40-90fps but on Mac with same settings it drops to 6-8fps and not much.

App use few zones to capture via iteration. Zones count 1-8.


This code is capable to grab and transform captured screen.




namespace GrabQt
{

QRgb getColor(const QWidget * grabme)
{
DEBUG_HIGH_LEVEL << Q_FUNC_INFO;

int x = grabme->x();
int y = grabme->y();
int width = grabme->width();
int height = grabme->height();

DEBUG_HIGH_LEVEL << "x y w h:" << x << y << width << height;

QPixmap pix = QPixmap::grabWindow(QApplication::desktop()->winId(), x, y, width, height);
QPixmap scaledPix = pix.scaled(1,1, Qt::IgnoreAspectRatio, Qt::FastTransformation);
QImage im = scaledPix.toImage();
QRgb result = im.pixel(0,0);

DEBUG_HIGH_LEVEL << "QRgb result =" << hex << result;

return result;
}

};



This code call grab and transform iteration for each zones.




void GrabManager::updateLedsColorsIfChanged()
{
DEBUG_HIGH_LEVEL << Q_FUNC_INFO;

// Temporary switch off updating colors
// if one of LED widgets resizing or moving
if(isResizeOrMoving){
timerGrab->start(50); // check in 50 ms
return;
}

bool needToUpdate = false;

int avgR = 0, avgG = 0, avgB = 0;
int countGrabEnabled = 0;

clearColorsNew();


//#define PRINT_TIME_SPENT_ON_GRAB
#ifdef PRINT_TIME_SPENT_ON_GRAB
QTime t; t.start();
#endif

// Capture screen what contains first LED widgets
if(isGrabWinAPI){
GrabWinAPI::captureScreen();
}

for(int ledIndex=0; ledIndex<LEDS_COUNT; ledIndex++){
if(ledWidgets[ledIndex]->isGrabEnabled()){
QRgb rgb;
if(isGrabWinAPI){
rgb = GrabWinAPI::getColor( ledWidgets[ledIndex] );
} else {
rgb = GrabQt::getColor( ledWidgets[ledIndex] );
}

if( avgColorsOnAllLeds ){
avgR += qRed(rgb);
avgG += qGreen(rgb);
avgB += qBlue(rgb);
countGrabEnabled++;
}else{
colorsNew[ledIndex].rgb = rgb;
}
}else{
colorsNew[ledIndex].rgb = 0; // off led
}
}

#ifdef PRINT_TIME_SPENT_ON_GRAB
qDebug() << "Time spent on grab:" << t.elapsed() << "ms";
#endif

if( avgColorsOnAllLeds ){
if( countGrabEnabled != 0 ){
avgR /= countGrabEnabled;
avgG /= countGrabEnabled;
avgB /= countGrabEnabled;
}
// Set one AVG color to all LEDs
for(int ledIndex = 0; ledIndex < LEDS_COUNT; ledIndex++){
if(ledWidgets[ledIndex]->isGrabEnabled()){
colorsNew[ledIndex].rgb = qRgb(avgR, avgG, avgB);
}
}
}

#if 0
// 0 <= color <= ambilight_color_depth




I think on Mac OS X this part of upper code is slowing down all capture. Iteration of grabWindow slowing down all process.




for(int ledIndex=0; ledIndex<LEDS_COUNT; ledIndex++){
if(ledWidgets[ledIndex]->isGrabEnabled()){
QRgb rgb;
if(isGrabWinAPI){
rgb = GrabWinAPI::getColor( ledWidgets[ledIndex] );
} else {
rgb = GrabQt::getColor( ledWidgets[ledIndex] );
}

if( avgColorsOnAllLeds ){
avgR += qRed(rgb);
avgG += qGreen(rgb);
avgB += qBlue(rgb);
countGrabEnabled++;
}else{
colorsNew[ledIndex].rgb = rgb;
}
}else{
colorsNew[ledIndex].rgb = 0; // off led
}
}




Does anyone know the reason why grabbing screen on OSX is too slow instead of Win/Linux. And how we can fix it? Maybe via grabbing screen in OSX from OGL framebuffer, cause OSX output all to OGL surface? Or maybe use one screen capture for all zones and do an iteration of cut/resize parts from one catured screen? Or maybe something else?

Thank you!

ps. sorry for bad language.
project home is http://code.google.com/p/lightpack/

stampede
28th May 2011, 09:30
I'm not a OSX user, so I don't know the answer, but what I know is that the getColor method could be done better.
I understand that it's purpose is to grab the (0,0) pixel color from widget, so I don't see why you need to grab the whole desktop ? Can't you use the QWidget::winId()? And if all you need is this one pixel, pass a QRectF(0,0,1,1) to QPixmap::grabWindow, no need to scale anything, so your method will look like:


QRgb getColor(const QWidget * grabme)
{
DEBUG_HIGH_LEVEL << Q_FUNC_INFO;

QPixmap pix = QPixmap::grabWindow(grabme->winId(),0,0,1,1);
QImage im = pix.toImage();
QRgb result = im.pixel(0,0);

DEBUG_HIGH_LEVEL << "QRgb result =" << hex << result;

return result;
}

I think it could be faster.