Page 1 of 1
vbe SetPixel problem
Posted: Tue Dec 12, 2006 2:12 am
by AndrewAPrice
Can people check to see what's wrong with the following code?
Code: Select all
unsigned int * screenBase; /* beginning of the VBE lfb */
unsigned int width; /* horizontal resolution of the screen */
unsigned int bpp; /* 1 byte for 8-bit, 2 for 16-bit, 3 for 24-bit, 4 for 32-bit */
void setpixel(unsigned int x, unsigned int y, byte_t red, byte_t green, byte_t blue)
{
byte_t *address = screenBase + (width * y + x) * bpp;
*address = blue; /* these would only work for 24-bit */
address++;
*address = green;
address++;
*address = red;
}
If I run it in a for loop, say
Code: Select all
int i;
for(i = 0; i < 800; i++)
{
setpixel(i, 0, 0xFF, 0xFF, 0x00);
}
only every third pixel is coloured yellow. If I remove the "* bpp" in setpixel so the function reads as:
Code: Select all
byte_t *address = screenBase + (width * y + x) * bpp;
every byte ends up being set to blue value resulting in a white line.
Posted: Tue Dec 12, 2006 4:04 am
by AndrewAPrice
If fixed my problem by removing "* bpp" and selecting a 32bpp VESA mode. However, how would I adapt the above function to work in 8bpp, 15bpp, 16bpp, and 24bbp VESA modes?
Posted: Tue Dec 12, 2006 4:17 am
by AJ
Hi,
I haven't looked thoroughly at the code as I haven't done VESA before, but how are you running this?
I know that VPC2004 has problems with some 24 bit colour modes (I have had problems with some linux distro's before) - in fact some software I have run in the past seemed to stretch the screen and only colour every n'th pixel - sounds very similar to your problems.
Of course, if you are having this problem on a 'real' PC, this doesn't help
Hope this helps,
Adam
Posted: Tue Dec 12, 2006 4:49 am
by Ready4Dis
Try this:
Code: Select all
void PlotPixel(int x, int y, unsigned char red, unsigned char green, unsigned char blue)
{
unsigned char *addr = base + (Width*bpp*y) + (x*bpp);
*addr++ = red;
*addr++ = green;
*addr = blue;
}
Also, make sure all your variables have the values in them that you think are there! Now, most video cards actually reverse the red and blue values, so this may screw up, just a heads up! You would need to check the bit masks to see. You can adapt this to 32-bit code easily... depends on where the spare 8-bits is, just increment addr where required. 15/16 bit is a bit harder, but not much... first you must check if you are indeed in 15-bit (R5G5B5) mode, or 16-bit (R5G6B5) mode. Then you would run a function similar to this (again, red and blue may be backwards).
Code: Select all
void PlotPixel16(int x, int y, unsigned char red, unsigned char green, unsigned char blue)
{
unsigned short *addr = base + (Width*bpp*y) + (x*bpp);
*addr = (blue>>3); //Shift right 3 to remove bottom 3 bits 8->5 bits!
*addr<<=6; //Move right 6 bits to make room for green
*addr+=(green>>2); //This removes 2 bits, 8->6
*addr<<=5; //Move this left 5 more bits for red
*addr+=(red>>3); //Again, remove bottom 3 bits
}
15 bits per pixel is almost the same, just change the <<=6 to <<=5, and the green>>2 into green>>3. Hope this helps.
Posted: Tue Dec 12, 2006 4:54 am
by Combuster
Also, the order in which Red Green and Blue appear depends on the implementation.
IIRC you can ask VBE for the exact bitmasks where which color component should go, but you'd still end up with different blocks for each bpp value, due to the byte count of each pixel.
As for why 24 bits dont work - i have no clue. Its especially strange that effectively writing all zeroes result in a white line
Posted: Tue Dec 12, 2006 10:42 am
by Ready4Dis
One more thing, before you enter graphics mode, you should print out all your variables, width, height, bpp, and screen_base just to make sure they all contain the values you are expecting, there is no reason why removing the multiplication by bpp should fix the problem, your code looks pretty correct as far as I can see, so it might be elsewhere.
Posted: Tue Dec 12, 2006 11:29 am
by ces_mohab
i have recently finished some vbe work here are some snippets:
load bmp of width 160 and height 128 true color at top right screen shifted by 20 from top and right notice 180 and 148.
This works for 24/32 bit color depth.
Code: Select all
load = baseptr + (width*148)*depth ;
for ( i=128 ; i>0 ; i-- )
{
int loadtemp = load ;
for(j=0 ; j<160 ; j++ )
{
for(k=0 ; k<3 ; k++)
load[j*depth + (width-180)*depth + k] = *bmp++ ;
}
load = loadtemp - width*depth ;
}
while this prints a character.
font size 8*16.
Code: Select all
void putcha( int ch , int x , int y )
{
unsigned char* tov = vptr + (y*16*width + x*8)*depth ;
int i , j, index = ch*16 ;
for( i=0 ; i<16 ; i++ )
{
unsigned char* temp = tov ;
int mask = 0x00000080 ;
for( j=0 ; j<8 ; j++ )
{
if( (font1[index+i]&mask) == mask )
{
*tov = attrib ;
*(tov+1) = attrib>>8 ;
*(tov+2) = attrib>>16 ;
}
tov+=depth ;
mask >>= 1 ;
}
tov = temp + width*depth ;
}
}
this needs optimization but at least works.