Friday, May 26, 2006

Survived Thesis A

Just spent the week rewriting my Thesis A (proposal) report "Optimising L4 on Blackfin 53x: for a high performance L4 microkernel on a processor without virtual memory". 40 pages. That's longer than most people's Thesis B (actual work) report! Maybe I spent too long on it at the expense of other assignments... Did the talk today and here is my killer mascot ("Blackfin"):


It's amazing what one can do in KolourPaint/MSPaint :)

At 4am, I was drawing up the slides for the talk and fired up OpenOffice Impress. I don't normally praise software but having never used a presentation program before, I was really impressed by how intuitive it was, taking only about 10 minutes discover how it worked (even at 4am). But then after drawing up the 15 slides, I went to save:

"Write error" [or a similar message]

After trying to save in different formats and on different disks, I got a message saying "OpenOffice experienced a general failure" and then it disabled most of the menu items... My fault for using a beta version of Fedora Core 4's fault for shipping one?

Having said that, performance aside, OpenOffice Writer has worked great so far to allow me to continue on without LaTeX (figured out how to use the styles - press F11 and right mouse click to change a style).

Friday, May 12, 2006

Strange smell from an old computer

My main and old computer (Pentium II from 1998) is giving off a bad smell, as if rubber/tyres are burning or I'm in a train/bus with new brake lines. It's giving me a headache and I have a bad feeling about its health effects.

No wires are touching the heatsink - I already checked that.

Any ideas on what this is?

Thursday, May 11, 2006

What does a "Cheese and Bacon Pie" mean to you?

Quiche? Or something with lots of cheese and bacon?

It was around midnight in Sydney (I wrote that just so that it sounds more mysterious) that I got one of these "Cheese and Bacon Pies" from 7-11. It tastes mainly like it was made of beef and in fact, a closer look at the ingredients said that the cheese and the bacon forms only 12% of the product (in weight, if I remember correctly). How's that for misleading advertising? It was still a good pie though.

What was that not-so-old adage? Something like "we live in a world where lemonade contains no lemon but detergent does".

Sunday, April 30, 2006

Buffy the Vampire Slayer Audio CDs

Yes, I am a fan of BtVS given than I watched all 144 episodes over 2 months. To cut a long story short, the soundtrack (on 3 CDs released at different points when the series was on TV) finally arrived from Amazon after a few months.

In my opinion, Buffy The Vampire Slayer: The Album (1999 Television Series) [SOUNDTRACK] is really not worth buying except for theme music and "Close Your Eyes", which is played when Buffy murders her boyfriend Angel at the end of Season 2 in order to save the world (so much for "boyfriend"; and yes, Ashlee Simpson can make a song entitled that if she wishes).

Ditto, for Buffy The Vampire Slayer: Radio Sunnydale [SOUNDTRACK] (2003 US Version). A good track is "The Final Fight" - the music for the last episode, when the slayers are somehow kicking all the Ubervamps' butts (a nice plot inconsistency: even though Buffy the veteran slayer had trouble killing a single Ubervamp throughout all of Season 7, in the last episode, other slayers and Giles/Spike/Xander/Dawn had no problems; won't say the same about Anya though...).

The last CD, the infamous Once More, with Feeling (2002) musical soundtrack is pretty good esp. Sarah Michelle Gellar's singing in "Going Through the Motions" and "Walk Through the Fire". A nice addition was not Joss Whedon's wife singing :) but rather "Sacrifice", the track for the Season 5 finale, where Buffy selfishly jumps off the tower to "to save the world" when in reality, she knows she's going to go to heaven instead of her sister (yes, my postmodernist interpretation). Jokes aside, this is probably the best finale in the whole series (it's also the 100th episode by accident).

On the other hand, Season 4 was hopeless and in its final episode, literally nothing happened!

I would really like to see an 8th season, set 10 years after the last, when all the actors are older and can't walk but still have to battle vampires etc. :)

So what's up with KolourPaint in KDE4?

These last couple of weeks I've been trying to find a 1:1 mapping between the Qt3 graphics functions and the Qt4 ones. Later, I'll blog in the detail how to really port QPainter/QPixmap/QImage. The Qt4 porting guide is too scanty on important semantic changes.

In the meantime, KolourPaint in trunk/ has regressed a bit because of the KToolBar/KAction changes:



As you can see, the size hints for the Colour Box and Tool Box are not working and since those 6x6 tool icons are so hard to click, I had to manually add them to the main toolbar. I'll fix this stuff after I get the paint engine porting under control.

And apart from not working, KolourPaint is really slow (and blocks the X server) because of unneeded QPixmap <-> QImage transformations in the deprecated copyBlt() (my local changes have dropped copyBlt()) and calls to QPixmap::mask(). The latter has this rather amusing comment in qt-copy/src/gui/image/qpixmap_x11.cpp:


#ifndef QT_NO_XRENDER
if (data->picture && data->d == 32) {
// #### slow - there must be a better way
mask = QBitmap::fromImage(toImage().createAlphaMask());
} else
#endif


Well, at least it was amusing at 1am... See, QPixmap::mask() in Qt3 returned a pointer to a precomputed mask so it was real fast. In Qt4 however, it does X serverside magic and in the worst case (the above snippet of code for QPixmap's with alpha channels), it does 2 X server roundtrips plus computation. In fact, it takes 450ms for an 800x600 image on a 2.2Ghz processor. Simply unbearable.

But the good news is that most calls to QPixmap::mask() in KolourPaint are either for drawing on the mask (since QPainter3 would happily draw on the QPixmap but not update the mask; for Qt4, I will drop this code shortly) or determining whether the pixmap has a mask. For the latter, this Qt3 code:


if (pixmap.mask ())


should not be ported to:


if (!pixmap.mask ().isNull ())


contrary to a previous blog entry since QPixmap::mask() does expensive computation that we throw away anyway. Do this instead:


if (pixmap.hasAlpha ())


So in a couple of weeks, expect a commit that will make painting work. Also, the next time Trolltech and KDE make such sweeping changes to their APIs, they should feel free to send me a cheque :) I am simply spending far too much time porting 50 thousand lines of code (which feels like a "NOP" job) rather than writing new features or doing real work (uni).

An old joke is that if you don't understand what "deprecated method" means, you should update to Java 1.2 (or maybe it was 1.4?). Now, they can add Qt to that. I now have literally 500 "deprecated" warnings to go through. coolo, mueller and montel have been doing a lot of fixes though - thanks! But on the flip side, I'm duplicating some work (I don't commit often due to internet time limitations) and it means I have to review a lot of patches:


$ wc -l *.diff
36 521415.diff
859 528186.diff
492 530108-533650.diff
1000 535185-535614.diff
0 ALSO_REVIEW_CMAKE.diff
2387 total


Speaking of which, cmake works quite well. In fact, I'm going to remove the remaining Makefile.am's since compat/Makefile.am is already gone. cmake is faster than unsermake, which was faster than automake. cmake supports "make -t". Also, if you want to hack CXXFLAGS long after running "cmake", the file you want is kdegraphics-build/kolourpaint/CMakeFiles/kolourpaint.dir/flags.make.

Now, back to work!

Tuesday, April 11, 2006

Determining if a type is a pointer at compile time

http://doc.trolltech.com/4.1/qlist.html:

"QList is represented as an array of pointers to items. (Exceptionally, if T is a pointer type, a basic type of the size of a pointer, or one of Qt's shared classes, QList stores the item directly in the pointer.)"

So a QList<QRect> is going to be an array of QRect * but QList<QWidget *> will be an array of QWidget * - not QWidget **. But how can we determine whether a type is a pointer at compile time?

Update: This describes the method used in Qt for compilers lacking support for partial template specialisation. If you have partial specialisation, it can be done in a very straightforward way (see blog comments).

Well it seems to be done by abusing our favourite language. QList uses the QTypeInfo class - the interesting bits being:


template <typename T> char QTypeInfoHelper(T*(*)());
void* QTypeInfoHelper(...);

template <typename T>
class QTypeInfo
{
public:
enum {
isPointer = (1 == sizeof(QTypeInfoHelper((T(*)())0))),


int *



Now, consider the case of QTypeInfo<int *>. the last line expands to:

isPointer = (1 == sizeof(QTypeInfoHelper( (int * (*) ()) 0))).

Now I've added some spaces so that it can actually be read. It's saying, pass NULL - casted to a pointer to a function that accepts nothing and returns an int * - to one of the QTypeInfo functions.

But to which 1 of the 2 overloads? Well, the C++ rule for resolving overloaded function calls is to select the function with the most specific matching argument types, assuming no ambiguity. In this case, our function call matches this candidate:

template <typename T> char QTypeInfoHelper(T * (*) ());

because T is int. Now you won't actually find QTypeInfoHelper defined anywhere because all sizeof is interested in is the size of the return value of the function - it doesn't actually execute it. Now, the return type is a char, which is of size 1, therefore isPointer is true.

int



Now we look at a non-pointer type, int. The tricky line expands to:

isPointer = (1 == sizeof(QTypeInfoHelper( (int (*) ()) 0))).

That function pointer argument type accepts nothing and returns an int. It's not going to match the same overload because it's looking for a pointer (the T *):

template <typename T> char QTypeInfoHelper(T * (*) ());

And int is no pointer. Therefore, it can only match the catch-all overload:

void* QTypeInfoHelper(...);

which returns a void* and guess what:

isPointer = (1 == sizeof(void *)).

is false (unless on an 8-bit machine :)). Therefore, int is correctly detected as not a pointer.

Conclusion



QTypeInfo manages to determine whether a type is a pointer without:


  1. actually invoking a function (by merely checking the size of the return type)

  2. ever constructing an element of type T (which might otherwise cause side effects)

Thursday, April 06, 2006

Moving messages in PINE

I'm stuck with using PINE/Mutt at uni - partially because they don't have KMail (or much of KDE for that matter) and mainly because I want to be able to access it over SSH from anywhere. Today my inbox finally got too big to manage so I started splitting it up into multiple folders and combined the scheme with filters.

And guess how you save a message in PINE? Well it's not by pressing 'S' for "Save" (that moves messages between folders). It's 'E' for "Export".

In other news, I had a dream where I swear I saw Terminator 4. Great sequel, plot but as with all good dreams, I forgot by the time I had woken up. Too bad. Would have sold the plot to the Governor of California otherwise.

Sunday, March 05, 2006

Porting to KDE 4

I've just managed to compile KDE 4 so that I can port KolourPaint. A lot of work (thanks mainly to Laurent Montel) has already been done.

I spent yesterday combing through the 15,000 line diff (actually, I did some tricks to reduce my reading down to 5,000 lines) and fixed 2 main kinds of errors:

1. qt3to4 remaining variables like "red" to "Qt::red".

2. "if (!pixmap.mask ())" should not be "if (!pixmap.mask ().isNull ())". It should be "if (pixmap.mask ().isNull ())".

KolourPaint exploited Qt3's painting system to the max. And given the rewrite of the Qt painting system, there's going to have to be a lot more work before KolourPaint compiles, let alone works. With the addition of proper alpha channel support, Qt seems to have done away with the Qt::NotAndROP and friends. Going to be tricky to port.

And I just don't think that breaking source compatibility every few years and saying "now port KDE's several million lines of code" works well. Something to think about for future Qt's & KDE's.

Oh, and this is my first blog post :)