FEZ Touch DrawstringInternal suggestion

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);
            }

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

Nice work Bob!

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

You are okay with this right?

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

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);