OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 2:50 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Double Buffering problems
PostPosted: Fri Feb 24, 2017 4:37 am 
Offline
Member
Member

Joined: Fri Sep 09, 2016 5:52 pm
Posts: 44
Location: Australia
I have been running into some really weird problems when i tried implementing Double Buffering in my graphics driver in my operating system. When i don't use the double buffering my functions work fine. When i do however, if I use malloc to allocate space nothing happens and the screen is black but when i don't it's really weird and it draws my first yellow 200x200 rectangle, but it wont draw anything else and there is an exception (VirtualBox won't tell me much else).
Here is my graphics code:
Code:
namespace graphics{
   vesa_mode_info_t *modeInfo;
   uint32_t vram = 0;

   unsigned char* dblBuffer;
   unsigned char* screen;
   bool initialized = false;

   vesa_mode_info_t * initGfx(){
      if(!initialized){
         modeInfo = EnterGraphicsMode();
         vram = modeInfo->physbase;
         //if(vram == 0)
         //   panic("ERR_GFX_MODE_FAILED", "Error whilst setting graphics mode.",false);

         screen = (unsigned char*)vram;
         //dblBuffer = (unsigned char*)malloc(modeInfo->width*modeInfo->height*modeInfo->bpp/8);

         UpdateScreen();

         initialized = true;
      }

      return modeInfo;
   }

   void putpixel(int x,int y, uint8_t r, uint8_t g, uint8_t b) {
      putpixel(x,y,(r << 16) + (g << 8) + b);
   }

   /* Using Double Buffer
       void putpixel(int x,int y, uint32_t colour) {
      unsigned where = y * modeInfo->pitch + (x * (modeInfo->bpp/8));
      dblBuffer[where] = colour & 255;              // BLUE
      dblBuffer[where + 1] = (colour >> 8) & 255;   // GREEN
      dblBuffer[where + 2] = (colour >> 16) & 255;  // RED
   }

   void fillrect(int x, int y, int w, int h, uint32_t colour) {
      int bpp = modeInfo->bpp;
      int pitch = modeInfo->pitch;
      uint32_t where = 0;
      for(int i=0;i<h;i++){
         for(int j=0;j<w;j++){
            where = (y+i) * pitch + ((x+j) * (bpp/8));
            dblBuffer[where] = colour & 255;             // BLUE
            dblBuffer[where + 1] = (colour >> 8) & 255;  // GREEN
            dblBuffer[where + 2] = (colour >> 16) & 255; // RED
         }
      }
   }*/

        /* Without Double Buffer*/
   void putpixel(int x,int y, uint32_t colour) {
      unsigned where = y * modeInfo->pitch + (x * (modeInfo->bpp/8));
      screen[where] = colour & 255;              // BLUE
      screen[where + 1] = (colour >> 8) & 255;   // GREEN
      screen[where + 2] = (colour >> 16) & 255;  // RED
   }

   void fillrect(int x, int y, int w, int h, uint32_t colour) {
      int bpp = modeInfo->bpp;
      int pitch = modeInfo->pitch;
      uint32_t where = 0;
      for(int i=0;i<h;i++){
         for(int j=0;j<w;j++){
            where = (y+i) * pitch + ((x+j) * (bpp/8));
            screen[where] = colour & 255;             // BLUE
            screen[where + 1] = (colour >> 8) & 255;  // GREEN
            screen[where + 2] = (colour >> 16) & 255; // RED
         }
      }
   }

   void fillrect(int x, int y, int w, int h, unsigned char r, unsigned char g, unsigned char b){
      fillrect(x,y,w,h,(r << 16) + (g << 8) + b);
   }

        // Copy back buffer to video memory
   void UpdateScreen(){
      memcpy(screen,dblBuffer,modeInfo->width*modeInfo->height*(modeInfo->bpp/8));
   }
}


Top
 Profile  
 
 Post subject: Re: Double Buffering problems
PostPosted: Fri Feb 24, 2017 5:37 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
If you don't allocate memory for the buffer you are bound to have problems. So the question you need to answer is why things don't work when you malloc() the buffer; time for a little debugging.


Top
 Profile  
 
 Post subject: Re: Double Buffering problems
PostPosted: Fri Feb 24, 2017 7:47 pm 
Offline
Member
Member

Joined: Fri Sep 09, 2016 5:52 pm
Posts: 44
Location: Australia
iansjack wrote:
If you don't allocate memory for the buffer you are bound to have problems. So the question you need to answer is why things don't work when you malloc() the buffer; time for a little debugging.

Ok thanks i will try to find out the problem with malloc()


Top
 Profile  
 
 Post subject: Re: Double Buffering problems
PostPosted: Sat Mar 11, 2017 1:44 am 
Offline
Member
Member

Joined: Fri Sep 09, 2016 5:52 pm
Posts: 44
Location: Australia
iansjack wrote:
If you don't allocate memory for the buffer you are bound to have problems. So the question you need to answer is why things don't work when you malloc() the buffer; time for a little debugging.
Malloc is working but i am still having problems, i tried drawing a rectangle to fill the screen and it only filled about 50 pixels at the top of the screen.

_________________
My OS:
https://github.com/fido2020/Lemon-OS
https://lemonos.org
https://discord.gg/NAYp6AUYWM


Top
 Profile  
 
 Post subject: Re: Double Buffering problems
PostPosted: Sat Mar 11, 2017 2:43 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

ComputerFido wrote:
iansjack wrote:
If you don't allocate memory for the buffer you are bound to have problems. So the question you need to answer is why things don't work when you malloc() the buffer; time for a little debugging.
Malloc is working but i am still having problems, i tried drawing a rectangle to fill the screen and it only filled about 50 pixels at the top of the screen.


Try to figure out if it's a problem with the code that draws stuff in the double buffer, and/or if it's a problem with the code that copies the double buffer to display memory.

Looking at your old (and likely no longer relevant) code; I'd be tempted to expect multiple problems (e.g. that "fillrect()" is buggy and that "UpdateScreen()" is buggy too), but it's hard to say without seeing any of the new/relevant code.


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Double Buffering problems
PostPosted: Sat Mar 11, 2017 5:14 am 
Offline
Member
Member

Joined: Fri Sep 09, 2016 5:52 pm
Posts: 44
Location: Australia
Brendan wrote:
Hi,

ComputerFido wrote:
iansjack wrote:
If you don't allocate memory for the buffer you are bound to have problems. So the question you need to answer is why things don't work when you malloc() the buffer; time for a little debugging.
Malloc is working but i am still having problems, i tried drawing a rectangle to fill the screen and it only filled about 50 pixels at the top of the screen.


Try to figure out if it's a problem with the code that draws stuff in the double buffer, and/or if it's a problem with the code that copies the double buffer to display memory.

Looking at your old (and likely no longer relevant) code; I'd be tempted to expect multiple problems (e.g. that "fillrect()" is buggy and that "UpdateScreen()" is buggy too), but it's hard to say without seeing any of the new/relevant code.


Cheers,

Brendan


I have not changed my fillrect code (as it worked without the doublebuffer and i got the same problem when i used memset) i also tried using a loop instead of memcpy and i still got the same problem.

_________________
My OS:
https://github.com/fido2020/Lemon-OS
https://lemonos.org
https://discord.gg/NAYp6AUYWM


Top
 Profile  
 
 Post subject: Re: Double Buffering problems
PostPosted: Sun Mar 12, 2017 12:39 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

ComputerFido wrote:
Looking at your old (and likely no longer relevant) code; I'd be tempted to expect multiple problems (e.g. that "fillrect()" is buggy and that "UpdateScreen()" is buggy too), but it's hard to say without seeing any of the new/relevant code.


I have not changed my fillrect code (as it worked without the doublebuffer and i got the same problem when i used memset) i also tried using a loop instead of memcpy and i still got the same problem.[/quote]

The first problem is your handling of "pitch".

Think of the video card's display memory as rows, where each row consists of pixel data followed by none or more unused bytes (for padding). For example, for "800*600 with 32-bpp" each row might be 800*4 bytes (3200 bytes) of pixel data followed by 896 bytes of padding, that adds up to a total of 4096 bytes per row (and so "modeInfo->pitch" would be 4096).

Of course your double buffer has no padding.

Your "UpdateScreen()" assumes that there is no padding for the double buffer (correct) and that there's no padding for display memory (incorrect). This can cause pixels in the double buffer to be written to unused padding and be invisible.

Your "fillrect()" code assumes that there is padding when it draws into the double buffer (that has no padding). This is a potential "index out of range" bug where data in memory after the buffer get trashed. For example, for "800*600 with 32-bpp" with "modeInfo->pitch" is 4096, you allocate 800*600*4 bytes (or 1920000 bytes), and for the bottom left pixel you would write to "where = 799*4096+599*4 = 3275100" , which is 1355100 bytes past the end of the memory you allocated.


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Double Buffering problems
PostPosted: Fri Mar 17, 2017 5:56 pm 
Offline
Member
Member

Joined: Fri Sep 09, 2016 5:52 pm
Posts: 44
Location: Australia
Brendan wrote:
The first problem is your handling of "pitch".

Think of the video card's display memory as rows, where each row consists of pixel data followed by none or more unused bytes (for padding). For example, for "800*600 with 32-bpp" each row might be 800*4 bytes (3200 bytes) of pixel data followed by 896 bytes of padding, that adds up to a total of 4096 bytes per row (and so "modeInfo->pitch" would be 4096).

Of course your double buffer has no padding.

Your "UpdateScreen()" assumes that there is no padding for the double buffer (correct) and that there's no padding for display memory (incorrect). This can cause pixels in the double buffer to be written to unused padding and be invisible.


Okay i have tried many different things to try and fix UpdateScreen() this being among them.
Code:
void UpdateScreen(){
      for(int i=0;i<modeInfo->height;i++){
         for(int j=0;j<modeInfo->width;j++)
            screen[i*modeInfo->width*modeInfo->pitch+j] = dblBuffer[i*modeInfo->width+j];
      }
   }

But it still isn't working and i have no idea why. It's probably just something obvious i am missing but i am not sure. It would be really helpful if you could point me in right direction with the really annoying equation to copy the buffer :?

_________________
My OS:
https://github.com/fido2020/Lemon-OS
https://lemonos.org
https://discord.gg/NAYp6AUYWM


Top
 Profile  
 
 Post subject: Re: Double Buffering problems
PostPosted: Fri Mar 17, 2017 6:19 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

ComputerFido wrote:
Okay i have tried many different things to try and fix UpdateScreen() this being among them.
Code:
void UpdateScreen(){
      for(int i=0;i<modeInfo->height;i++){
         for(int j=0;j<modeInfo->width;j++)
            screen[i*modeInfo->width*modeInfo->pitch+j] = dblBuffer[i*modeInfo->width+j];
      }
   }

But it still isn't working and i have no idea why. It's probably just something obvious i am missing but i am not sure. It would be really helpful if you could point me in right direction with the really annoying equation to copy the buffer :?


That's not right either. The "modeInfo->pitch" is the number of bytes in a horizontal line and should not be multiplied by the horizontal resolution ("modeInfo->width").

It also won't work "as is" for arrays in C - you'd have to use something like "modeInfo->pitch/sizeof(screen[0])" instead. A better alternative is something like:


Code:
void UpdateScreen(){
      unsigned int visibleBytesPerLine = modeInfo->width * modeInfo->bpp / 8;
      uint8_t *dest = screen;
      uint8_t *src = dblBuffer;

      for(int y = 0; y < modeInfo->height; y++) {
         memcpy(dest, src, visibleBytesPerLine);
         dest += modeInfo->pitch;
         src += visibleBytesPerLine;
      }
   }


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot], Majestic-12 [Bot] and 58 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group