Main Site Documentation

FEZ Touch DrawstringInternal suggestion


#1

Guys, I have done a little work on the DrawStrinInternal code and was able to speed it up about 43%. I know just doubling the speed isn’t that dramatic, but if you had a lot of text it would be somewhat significant. I did two things: I get the foreground and background colors just once outside the loop and avoid array indexing for them and I unrolled the inner loop and used predefined masks to avoid shift operations. Feel free to remove my comment header and use it anyway you like. This uses just a little more memory for the code.

        // This is an attempt to optimize the Drawstring routine to make it faster.
            // Bob Puckett 04/29/11
            //
            // Strategies:
            //  1) Get the foreground and background color bytes once rather than index in loop
            //  2) Use predifined masks instead of bit shifting
            //  
            // Results:
            //  Baseline for 10 iterations of test = 6.4976964 seconds
            //  After Strategy 1: 5.6268638 seconds (~15% improvement)
            //  After Strategy 2: 3.95153253 seconds (~30% improvement)
            //  After Strategy 2.1: 3.7664644 seconds (Total improvement about 43%)

            private void DrawString_Internal(int x, int y, string val)
            {
                lcdCS.Write(false);

                byte ch;

                // Strategy 3: get the foreground and background color bytes before any loops 
                byte bc0 = buffer[2];
                byte bc1 = buffer[3];
                byte fc0 = buffer[0];
                byte fc1 = buffer[1];

                // first four bytes are used for color
                int bufferIndex = 4;

                SetDrawingWindow(x, y, FONT_WIDTH * val.Length, FONT_HEIGHT);            

                for (int j = 0; j < 12; j++)
                {
                    for (int currentChar = 0; currentChar < val.Length; currentChar++)
                    {
                        ch = font[((val[currentChar] - 32) * 12) + j];

                        // Strategy 2: Use defined masks

                        if ((ch & 0x80) != 0) { buffer[bufferIndex] = fc0; buffer[bufferIndex + 1] = fc1; }
                        else { buffer[bufferIndex] = bc0; buffer[bufferIndex + 1] = bc1; }

                        if ((ch & 0x40) != 0) { buffer[bufferIndex+2] = fc0; buffer[bufferIndex + 3] = fc1; }
                        else { buffer[bufferIndex+2] = bc0; buffer[bufferIndex + 3] = bc1; }

                        if ((ch & 0x20) != 0) { buffer[bufferIndex+4] = fc0; buffer[bufferIndex + 5] = fc1; }
                        else { buffer[bufferIndex+4] = bc0; buffer[bufferIndex + 5] = bc1; }

                        if ((ch & 0x10) != 0) { buffer[bufferIndex+6] = fc0; buffer[bufferIndex + 7] = fc1; }
                        else { buffer[bufferIndex+6] = bc0; buffer[bufferIndex + 7] = bc1; }

                        if ((ch & 0x8) != 0) { buffer[bufferIndex+8] = fc0; buffer[bufferIndex + 9] = fc1; }
                        else { buffer[bufferIndex+8] = bc0; buffer[bufferIndex + 9] = bc1; }

                        if ((ch & 0x04) != 0) { buffer[bufferIndex+10] = fc0; buffer[bufferIndex + 11] = fc1; }
                        else { buffer[bufferIndex+10] = bc0; buffer[bufferIndex + 11] = bc1; }

                        if ((ch & 0x02) != 0) { buffer[bufferIndex+12] = fc0; buffer[bufferIndex + 13] = fc1; }
                        else { buffer[bufferIndex+12] = bc0; buffer[bufferIndex + 13] = bc1; }

                        if ((ch & 0x01) != 0) { buffer[bufferIndex+14] = fc0; buffer[bufferIndex + 15] = fc1; }
                        else { buffer[bufferIndex+14] = bc0; buffer[bufferIndex + 15] = bc1; }
                        bufferIndex += 16;
                    }
                }

                SetRegister(REGISTER_WRITE_GRAM);
                pp.Write(buffer, 4, bufferIndex - 4);

                lcdCS.Write(true);
            }


#2

How do I add code tags? - Oh, never mind!


#3

Nice work Bob!


#4

Nice one. I will see if the guys want to take it and drop it in official drivers.

You are okay with this right?


#5

Oh yeah, you don’t need to credit me or anything either. Use it for what ever you can.


#6

Removed over width check; replaced by trimming string (I’ll do the same for < 0 check too at some point)

Note: My variable names are different; this is coming out of Spiral and it changes the standard firmware a bit so watch the names if you plug it in :wink:


            if (X < 0 || Y < 0 || (Y + FONT_HEIGHT) > ScreenHeight)
                throw new ArgumentException();

            int MaxLen = (int)System.Math.Floor((double)(ScreenWidth - X) / 8);
            if (Text.Length > MaxLen)
                Text = Text.Substring(0, MaxLen);