Double Buffer not working?

Topics: Using Cosmos (Developing your own OS, projects, etc)
Feb 25, 2013 at 7:36 PM
Hi, I'm a Cosmos beginner and I'm creating my own OS. I tried to write a double buffer to draw the mouse cursor, but the screen goes yellow and it doesn't show anything.
I'm using the VGA driver that Civilwarrock posted here
Here is my code:
// Screen.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using Cosmos;
public class Screen
{
    public enum ScreenDriver
    {
        VGA = 0
    }
    public uint[] DoubleBuffer;
    public int ScreenHeight, ScreenWidth;
    public ScreenDriver Driver;
    public void Initialize()
    {
        Driver = 0;
        ScreenHeight = DeltaOS.VGA.ScreenHeight;
        ScreenWidth = DeltaOS.VGA.ScreenWidth;
        for (uint i = 0; i < ScreenHeight * ScreenWidth; i++)
        {
            DoubleBuffer[i] = (uint)VGAColors.FindIndex(0, 0, 0);
        }
    }

    public void SetPixel(uint x, uint y, uint c)
    {
        DeltaOS.VGA.SetPixel(x, y, c);
    }

    public uint GetPixel(uint x, uint y)
    {
        return DeltaOS.VGA.GetPixel(x, y);
    }

    public void VGASetMode(DeltaOS.VGA.ScreenResolution res)
    {
        DeltaOS.VGA.SetMode(res);
    }
    
    public void SetPaletteEntry(int index, Color color)
    {
        DeltaOS.VGA.SetPaletteEntry(index, color);
    }

    public void SetPaletteEntry(int index, byte r, byte g, byte b)
    {
        DeltaOS.VGA.SetPaletteEntry(index, r, g, b);
    }

    public void SetPalette(int index, byte[] palette)
    {
        DeltaOS.VGA.SetPalette(index, palette);
    }

    public void Clear(int color)
    {
        DeltaOS.VGA.Clear(color);
    }

    #region Double Buffer Methods
    public void SetPixelDoubleBuffer(uint x, uint y, uint c)
    {
        DoubleBuffer[y * ScreenWidth + x] = c;
    }

    public uint GetPixelDoubleBuffer(uint x, uint y)
    {
        return DoubleBuffer[y * ScreenWidth + x];
    }  

    public void ClearDoubleBuffer(int color)
    {
        for (uint i = 0; i < ScreenHeight * ScreenWidth; i++)
        {
            DoubleBuffer[i] = (uint)color;
        }
    }

    public void DrawDoubleBuffer()
    {
        for (uint i = 0; i < ScreenHeight; i++)
        {
            for (uint j = 0; j < ScreenWidth; j++)
            {
                DeltaOS.VGA.SetPixel(j, i, DoubleBuffer[i * ScreenWidth + j]);
            }
        }
    }
    #endregion
}

//Snippet from Kernel.cs:
 Mouse1.Initialize();
                DeltaOS.Kernel.Screen.VGASetMode(VGA.ScreenResolution.Res720x480x16);
                DeltaOS.Kernel.Screen.Initialize();
                DeltaOS.Kernel.Screen.ClearDoubleBuffer(VGAColors.FindIndex(0, 255, 255));
                uint x = (uint)(Mouse1.X);
                uint y = (uint)(Mouse1.Y);
                uint mx = 0;
                uint my = 0;
                         

                while (true)
                {
                    mx = (uint)(Mouse1.X);
                    my = (uint)(Mouse1.Y);
                    if (((mx != x) || (my != y)))
                    {
                        if ((Mouse1.Buttons == Mouse1.MouseState.Left))
                        {
                            ;
                        }
                        else
                        {
                            Screen.ClearDoubleBuffer(VGAColors.FindIndex(0, 255, 255));
                            x = mx;
                            y = my;
                            Graphics.DrawMouseImage(mouse_idle, 13, 24, new Vector2(x, y));
                            Screen.DrawDoubleBuffer();
                        }
                    }
                    Screen.ClearDoubleBuffer(VGAColors.FindIndex(0, 255, 255));
                    Graphics.DrawMouseImage(mouse_idle, 13, 24, new Vector2(x, y));
                    Screen.DrawDoubleBuffer();
                }
//DrawMouseImage and GetColorsForMouse methods:
private static byte GetColorsForMouse(byte color)
        {
            switch (color)
            {
                case 0:
                    return 0;
                case 1:
                    return 255;
                case 2:
                    return 0x80;
                default:
                    return 0x80; //(uint)VGAColors.FindIndex(0, 0, 0);
            }
        }
        private static uint k = 0;
        public static void DrawMouseImage(byte[] colors, uint width, uint height, Vector2 start)        {
            k = 0;
            for (uint i = 0; i < height; i++)
            {
                for (uint j = 0; j < width; j++)
                {
                    if (GetColorsForMouse(colors[k]) != 0x80)
                    {
                        Kernel.Screen.SetPixelDoubleBuffer(j + start.x, i + start.y, (uint)VGAColors.FindIndex(GetColorsForMouse(colors[k]),GetColorsForMouse(colors[k]),GetColorsForMouse(colors[k])));
                    }
                    k += 1;
                }
            }
        }
Could someone please tell me what wrong with my code?
Feb 26, 2013 at 5:23 PM
I finally figured out where the bug was. I didn't initialize the DoubleBuffer array. This is the new code:
  public void Initialize()
    {
        Driver = 0;
        ScreenHeight = DeltaOS.VGA.ScreenHeight;
        ScreenWidth = DeltaOS.VGA.ScreenWidth;
       DoubleBuffer = new uint[ScreenHeight * ScreenWidth];
    }
It works, but it's extremely slow, because the OS has to redraw the whole screen continuously.

I've read here that you have to implement a direct copy method from the buffer to the VGA memory, because the loops are too slow to be useful in drawing to the screen.
Does anyone know how to do this in Cosmos?

P.S. Thanks to civilwarrock for the driver! =)