Using framebuffer to build GUI

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
uri

Re:Using framebuffer to build GUI

Post by uri »

amirsadig wrote: hi
I have readed here that new version of bochs support VBE 3.0.

read this http://osdev.neopages.net/tutorials/bochs/bochs.php
AFAIK, the Bochs VGA BIOS supports only a subset of the VBE3 specification, which does not include the protected mode interface.

But you don't need to trust me on this:

[pre]cd bochs
grep PMID VGABIOS-lgpl-latest[/pre]

If it says: "binary file matches", I was wrong :)

- uri
amirsadig

Re:Using framebuffer to build GUI

Post by amirsadig »

I am trying to init VBE in VMWare, I have copied BIOS Image from 0xC0000 to a buffer of size 32K, and make scaning for siginatur of VBE PMinfo

Code: Select all

PMInfoBlock struc
Signature db 'PMID' ; PM Info Block Signature
EntryPoint dw ? ; Offset of PM entry point within BIOS
PMInitialize dw ? ; Offset of PM initialization entry point
BIOSDataSel dw 0 ; Selector to BIOS data area emulation block
A0000Sel dw A000h ; Selector to access A0000h physical mem
B0000Sel dw B000h ; Selector to access B0000h physical mem
B8000Sel dw B800h ; Selector to access B8000h physical mem
CodeSegSel dw C000h ; Selector to access code segment as data
InProtectMode db 0 ; Set to 1 when in protected mode
Checksum db ? ; Checksum byte for structure
PMInfoBlock ends
is db 'PMID' 4 byte ? because I do not find this signatur
amirsadig

Re:Using framebuffer to build GUI

Post by amirsadig »

@beyond infinity
I think you mean VMware support VBE 3.0 function but without PM Interface. in Official site of VMWare they said nothing about VBE.
amirsadig

Re:Using framebuffer to build GUI

Post by amirsadig »

I have test with GRUB the VBE in VMWare and I got that it support VBE 2.0. with the command vbeprobe.

now I have done in my multiboot header this code

Code: Select all

MULTIBOOT_PAGE_ALIGN   equ 1<<0
MULTIBOOT_MEMORY_INFO   equ 1<<1
MULTIBOOT_VIDEO_INFO   equ 1<<2
;MULTIBOOT_AOUT_KLUDGE   equ 1<<16
MULTIBOOT_HEADER_MAGIC   equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS   equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_VIDEO_INFO
MULTIBOOT_CHECKSUM   equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

Code: Select all

ALIGN 4
mboot:
   dd MULTIBOOT_HEADER_MAGIC
   dd MULTIBOOT_HEADER_FLAGS
   dd MULTIBOOT_CHECKSUM
; aout kludge. These must be PHYSICAL addresses
   dd mboot
   dd _code
   dd _bss
   dd _end
   dd entry
   dd 0
   dd 800
   dd 600
   dd 32
but I receive in bit 11 of the multiboot info a zero. the flags is
2023 (11111100111)
amirsadig

Re:Using framebuffer to build GUI

Post by amirsadig »

I have found a patch for GRUB to set the vidio mode, but after that I can not see any thing :'(. surely because I have not write any things to LFB.
have one a simple example to write something in screen of a font libray, so that I can test VBE.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Using framebuffer to build GUI

Post by Pype.Clicker »

he! now you know why we suggest people to stick with text mode as a start :)

basically, the VBE info structure reported by GRUB *should* include LFB address start. Depending on the mode you set up, bytes at that address will be interpreted differently, but at least writing "0xFFFFFFFF" in a loop should fill the screen with white color and, assuming 32 bits coloring scheme, you can write a font character with

Code: Select all


    char font_a[]={00111100b,
                        011001100b,
                        11000011b,
                        11000011b,
                        11111111b,
                        11000011b,
                        11000011b};
   int RGBA_white = 0xFFFFFFFF;
   show_character(char *font, char *VRAM, int color, int rowlength) {
       int i, j;
       for (i=0;i<CHAR_HEIGHT;i++,VRAM+=rowlength) {
           char *row=VRAM;
           for (j=1<<CHAR_WIDTH;j!=0;j=j>>1) {
              if (font[i]&j) *row=color;
              row++;
           }
        }
    }
should help you displaying characters ...
amirsadig

Re:Using framebuffer to build GUI

Post by amirsadig »

thank you it work now.

I should make all character like "A" or is there an easy one im internet to use it!
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Using framebuffer to build GUI

Post by Pype.Clicker »

the CHAR_HEIGHT and CHAR_WIDTH are used to know what's the character's pixmap size. the 'A' i gave is 8x7, so it should have

Code: Select all

#define CHAR_HEIGHT 7
#define CHAR_WIDTH 8
and the 'rowlength' should be something like 1024, 1200 or whatever your X resolution is...
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Using framebuffer to build GUI

Post by Pype.Clicker »

hey ? why did you drop your code ? it was interresting for other people ...

yes, you can quickly get a set of data for such fonts. there's for instance the 8x14 character set of most text modes in your system ROM. (in the video memory).
A VGA tutorial explaining how you can change those characters shouldn't be too hard to find (though i have no url atm). Just reverse it to copy the ROM font into some buffer you'll use later :)
amirsadig

Re:Using framebuffer to build GUI

Post by amirsadig »

I have dropped it because it was wrong ;D.

here is the new code:

Code: Select all

extern unsigned long mboot_info;

char font_a[]=???{0x00, /* 00000000 */
???0x00, /* 00000000 */
???0x00, /* 00000000 */
???0x00, /* 00000000 */
???0x00, /* 00000000 */
???0x78, /* 01111000 */
???0x0c, /* 00001100 */
???0x7c, /* 01111100 */
???0xcc, /* 11001100 */
???0xcc, /* 11001100 */
???0xcc, /* 11001100 */
???0x76, /* 01110110 */
???0x00, /* 00000000 */
???0x00, /* 00000000 */
???0x00, /* 00000000 */
???0x00};
unsigned long  RGBA_black = 0x00000000;
#define CHAR_HEIGHT    16
#define CHAR_WIDTH     8
unsigned long *framebuffer;
SVGAMODEINFO *vbe_mode_info;

void show_character(char *font, unsigned long *VRAM, unsigned long color, int rowlength);

int vbe_init()
{
    multiboot_info_t *mbi;
    union flags_info flags;
    char *image;
    int len = 32*1024, i, j;
    int done = 0;
    image = (char *) kmalloc(len);
    memcpy(image, biosimage, len);
    kprintf("init VBE ... ");
    mbi = (multiboot_info_t *)mboot_info;
    flags.flags = mbi->flags;
    if(flags.bits.bit11 == 1){
???done = 1;
    ???
???vbe_mode_info = (SVGAMODEINFO *)mbi->vbe_mode_info;
???framebuffer = (unsigned long *)vbe_mode_info->physbaseptr;
???if(framebuffer != NULL)
???{
???    int offset = 0;
???    for(j=0; j < 600; j++){
??????for(i=0; i < 800; i++){
??????    offset = 800*j + i;
??????    framebuffer[offset] = RGBA_black;
??????}
???    }
???    show_character(font_a,framebuffer,0xFFFFFFFF, 800);
???}
    }
    return 0;
}

void show_character(char *font, unsigned long *VRAM, unsigned long color, int rowlength) {
      int i, j;
      for (i=0;i<CHAR_HEIGHT;i++,VRAM+=rowlength) {
          unsigned long *row=VRAM;
          for (j=1<<CHAR_WIDTH;j!=0;j=j>>1) {
              if (font[i]&j) *row=color;
              row++;
          }
      }
}
is LBF realy a physical address, because I check it with bochsdbg, I notice it is in very heigh memory 0xE0000000. or that is the memory of video card but mapped to my physicall address?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Using framebuffer to build GUI

Post by Pype.Clicker »

yes, it is *really* a physical address (that is, an address as you can view it on the address bus). The trick is that you have no memory chip responding for that address while the PCI video card or the PCI-to-AGP bridge of your system will recognize that's an address it owns (with something like bus_seen_address & 0xF0000000 == pci_setup_address) and will map it as internal_vram[bus_seen_address&0x0FFFFFFF] for instance ...
amirsadig

Re:Using framebuffer to build GUI

Post by amirsadig »

oooh,
therefore I don't receive page fault. ah I have not enabled page yet (I mean as using LFB).
that mean I could mapped in my kernel space like normal paging mechanism using that physical address of LFB.
amirsadig

Re:Using framebuffer to build GUI

Post by amirsadig »

If need to use more than graphics console, should I allocate for every console a buffer with the size of LFB? and then when switch between console copy the buffer to LFB.
the best solution is to use small resolution, becaue heigh resolution need more memory (over 1MB). but here I come with problem when I want to write a compelx GUI (window, buttom ...) I need heigh resolution.

I know we can use VM86 or unreal mode to switch between Video Mode. but I have not until now pickup to use VM86.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Using framebuffer to build GUI

Post by Pype.Clicker »

if i were you, i would allocate a 4KB buffer that you use just as text memory and periodically poll if the page has been modified (Dirty bit set). If this is the case, just re-generate the console bitmap on the screen from the text-mode information ...

You can even keep the last version (what's on screen) and compare the new buffer with the previously drawn in order to reduce the amount of operations on VRAMS (only re-drawing characters that have changed), or generate that 'modified' bitmap when putch() to the buffer...
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Using framebuffer to build GUI

Post by Pype.Clicker »

Code: Select all

struct console {
    char width, height;
    int rowstart, currpos;
    char attr;
    short *buffer;

}

/** poor implementation: do not handle lines wider than 
 *  console correctly
 */
putch(struct console *con, char c) {
    if (c=='\n') {
       rowstart+=width;
       currpos=rowstart;
    } else {
        buffer[currpos]=(attr<<8)|c;
        currpos++;
    }
}

long colors[]={
    0x00000000, 0x00004000, 0x00400000, 0x00404000,
    ...
}

/**
 * 
 */
redraw(console*, long *fb) {
  for (int j=0; j<console->height;j++) {
    for (int i=0; i<console->width;i++) {
        if (buffer[j*console->width+i]==0xFFFF) continue;
        clear_character(fb,colors[buffer[...]>>12],i,j);
        draw_character(fb,(colors[buffer[...]>>8)&0x0f, font[buffer[...]&0xff]);
        buffer[...]=0xffff;
    }
  }
}
Post Reply