<< home >>
Nesúvislé fragmenty z objavovania OS Linux
<<- ->>


  • SVGALIB

MOŽNOSTI GRAFIKY V OS LINUX

Operačný systém Linux vznikol bez grafického používateľského rozhrania. Keďže Linux sa rozšíril najmä na PC kompatibilných počítačoch, kde hardvérová rôznorodosť dosiahla až neúnosnú hranicu, preniesla sa táto rôznorodosť aj do možností prístupu aplikácií ku grafickému hardvéru. V operačnom systéme Linux sa vyskytuje niekoľko rôznych prístupov ku grafickému HW. Žiakom navyknutým zrejme na komerčné prostredie M$ DOS a Windowsov  asi vyhovuje priamy prístup k HW (ostatne, určite už majú riadne ošahanú bedničku na mieste gombíka reset) a preto uvádzam grafickú knižnicu SVGALIB ako prvú, nie však jedinú. Takže ešte prv než príde k slovu SVGALIB, uvediem stručný prehľad možností prístupu ku grafickému hardvéru.

X-Window systém

Grafický systém pracujúci v prostredí klient-server, kde program je klient a server obhospodaruje platformovo závislú časť. Komunikácia prebieha cez sockety, čo umožňuje transparentnú prácu cez sieť, ale znižuje výkon lokálnych aplikácií. Tento problém sa začal riešiť pomocou DRI (Direct Rendering Infrastructure). Toto riešenie presmeruje časť komunikácie z lokálnych aplikácií priamo na lokálny hardvér a obíde sa sieťová vrstva čo by malo výrazne urýchliť beh graficky náročných aplikácií a znížiť zaťaženie hlavného procesora.

X-Window system + GLX

X-Window systém rozšírený o podporu OpenGL. Donedávna bolo OpenGL pod Linuxom a X-Window k dispozícii len pomocou softvérovej vizualizácie a tiež úplne chýbala podpora protokolu GLX.

SVGAlib

Hlavným motívom je umožniť prácu s SVGA kompatibilnými kartami jednoduchšou cestou, ako v systéme X-Window. Písanie aplikácií pre SVGAlib je veľmi jednoduché a podobá sa programovaniu grafiky pomocou knižnice BGI vo vývojových prostrediach firmy Borland pre operačný systém M$ DOS, čo spolu s vysokým výkonom je silným motivačným faktorom pre programátorov hier, alebo iných grafických systémov pracujúcich v reálnom čase, ktorým väčšinou nevyhovuje programovanie pod zložitými systémami okien, ktoré výrazne spomaľujú beh ich aplikácií a spotrebúvajú značnú časť systémových prostriedkov, ktoré potom nemôžu byť využité aplikáciou. Avšak použitie SVGAlib prináša značné bezpečnostné riziko, ako opíšem ďalej.

Grafická konzola jadra

Grafická konzola jadra (FB Console - Frame Buffer console) sa prevažne používa ako textová konzola s vysokým rozlíšením. Prostredníctvom súboru zariadenia tejto konzoly a volania mmap (systémové volanie, ktoré namapuje časť súboru do operačnej pamäte a v prípade, že ide o súbor zariadenia, ako v tomto prípade, o toto premapovanie sa stará príslušný ovládač v jadre a ten premapuje túto namapovanú pamäť na obrazovú pamäť zobrazovacieho adapteura) sa dá veľmi jednoducho namapovať jej obrazová pamäť, ale nie je možné počas behu meniť jeho bitovú hĺbku a okrem rýchlejšieho kreslenia bitmapových fontov nepodporuje, ani žiadnu akceleráciu. Grafická konzola jadra môže byť použitý aj v prípade, že pre danú grafickú kartu nie je podpora v XFree, ale je podporovaná v jadre (XFree je schopné pracovať cez grafickú konzolu jadra).

Glide (3Dfx)

Firma 3DFx prišla na trh s rozširujúcimi 3D kartami Voodoo a Voodoo2, ktoré sa zapájajú za výstup z grafickej karty. Tieto rozširujúce karty pracujú len v celoobrazovkovom režime a sú úplne nezávislé na grafickej karte. S týmito kartami sa pracuje cez knižnicu Glide (jednoduchá a zároveň veľmi rýchla knižnica navrhnutá špeciálne pre potreby programovania hier), ktorá je dostupná pre Linux, DOS, Windows a Macintosh. Tieto karty majú spolu s knižnicou Glide veľmi dobrý výkon čo prispelo k rozšíreniu medzi hráčskou komunitou. Bohužiaľ ku knižnici glide neboli až donedávna prístupné zdrojové kódy, čo znemožňovalo vytvorenie tejto knižnice pre grafické karty iných výrobcov. Donedávna bola jediná HW 3D podpora pre Linux riešená cez Glide, kde Mesa (open-source implementácia API, ktoré je veľmi podobné OpenGL) prekladala volania OpenGL do Glide. Neskôr sa objavila táto knižnica aj pre karty Voodoo3, ktoré už predstavovali plnohodnotnú grafickú kartu. S nastupujúcimi OpenGL ovládačmi ustupuje Glide trocha do úzadia.

Možnosti prístupu k hardvéru

Linux je operačný systém UNIXového typu a ako taký nepovoľuje priamy prístup aplikácií k hardvérovému vybaveniu. Štandardne sa o prístup k hardvérovému vybaveniu stará jadro systému a aplikácie nemajú oprávnenie priameho prístupu k hardvéru. Knižnica SVGAlib je navrhnutá tak, že program ku svojmu behu potrebuje mať rootovské práva, alebo aspoň SUID atribút, čo je potenciálna bezpečnostná diera a aj je to zároveň aj jeden z dôvodov prečo sa knižnica SVGAlib veľmi nerozšírila. Nastavenie SUID atribútu programu zabezpečí, že daný program sa bude spúšťať s právami vlastníka súboru programu, čo je v tomto prípade root. Tento prístup je veľmi nepopulárny, lebo predstavuje bezpečnostné riziko. Z iných možností prístupu k hardvéru možno spomenúť Kernel module, DRI interface a súbor zariadenia grafickej konzoly jadra.

Knižnica SVGAlib

Zdrojové kódy knižnice SVGAlib možno získať z adresy http://www.svgalib.org/, čo je domovská stránka projektu Linux SuperVGA Graphics Library. V marci 2003 tu bola dostupná verzia 1.4.3. Stiahnutý asi 820kB paklík (svgalib-1.4.3.tar.gz.tar) skopírujeme niekde do domovského adresára a z aktuálneho adresára rozbalíme.

$ tar xzf svgalib-1.4.3.tar.gz.tar

Stačí napísať len tar xzf s a stlačiť tabulátor. Ak v danom adresári nemáme iný súbor začínajúci na písmeno s, bash shell doplní jeho meno. Tabulátor je dobrá tlačica v konzole.V aktuálnom adresári vznikne roztarovaný podadresár svgalib-1.4.3. Vhupneme do neho.

$ cd svgalib-1.4.3

Prečítame si súbor 0-README napríklad našim obľúbeným textovým editorom vi.

$ vi 0-README

Textový editor vi ukončíme v príkazovom režime zapísaním dvojbodky a malého q. Do príkazového režimu sa dostaneme stlačením tlačice Esc a ak by sme čosi v texte boli bývali nechtiac pomenili, treba ešte za malé q dať výkričník.

:q!

Podobne si prečítame súbor 0-INSTALL.

$ vi 0-INSTALL

:q!

Inštalácia SVGAlib

Bežný user toto inštalovať nemôže. Teda zmeníme identitu na roota.

$ su -

Zadáme heslo a presunieme sa do adresára svgalib-1.4.3. Hojne používame tabulátor. Rootovská identita sa dá nastaviť aj su bez pomlčky (vtedy root zotrvá v aktuálnom adresári), ale nevykonajú sa inicializačné skripty roota a inštalácia SVGAlib skončí chybou (make: ldconfig: Command not found make: ***[installsharedlib] Error 127). A inštalujeme.

# cd /home/.../svgalib-1.4.3

# make install

Poznámka: Ak by už v našom systéme bola nejaká staršia verzia SVGAlib, musíme ju najprv odstrániť make uninstall a až potom inštalovať make install. Ďalej je tu možnosť nainštalovať demo programy. Ja som to urobil a o chvíľu som už stískal gombík reset. Už to nerobím, neinštalujem demo programy. SVGAlib umožní každému userovi priamy prístup k HW. Ak mi vytuhne monitor pri vlastných programoch, viem asi kde je chyba. Ak by mi ale vytuhol pri demo programe, neviem ani to.

Počas inštalácie sa v adresári svgalib-1.4.3 vytvoria nejaké súbory (zdieľané knižnice) patriace rootovi, takže ak chceme po inštalácii "upratať",  použijeme make clean a následne (stále ako root) môžeme odstrániť celý adresár svgalib-1.4.3 z domovského adresára a tiež stiahnutý paklík.

# make clean

# cd ..

# rm -rf svgalib-1.4.3

# rm -f svgalib-1.4.3.tar.gz.tar

Ihneď po inštalácii a vymazaní zdrojákov opustíme identitu roota (i keď sa k nej budeme vracať až príliš, príliš často).

# exit

Použitie SVGAlib

Do každého súboru, ktorý používa volania funkcií SVGAlib treba includovať vga.h. Ak používame aj "high-level" knižnicu, treba includovať aj vgagl.h.

Pri linkovaní treba volať kompilátor s parametrom -lvga, prípadne -lvgagl (ten musí byť ešte pred -lvga).

Príklad_1.c

/*
 * Priklad_1 pre vyuzitie
 * kniznice SVGAlib
*/

#include <stdlib.h>
#include <vga.h>

int main(void)
{
   register int i, j, f=0;

   vga_init();
   vga_setmode(G320x200x256);

   for (j=10; j<=150; j+=10) {
     vga_setcolor(f++);
     for (i=10; i<=310; i+=10)
       vga_drawpixel(i, j);
   }

   sleep(5);
   vga_setmode(TEXT);

   return EXIT_SUCCESS;
}



$ gcc -o Priklad_1 Priklad_1.c -lvga

Príklad_2.c

/*
 * Priklad_2 pre vyuzitie
 * kniznice SVGAlib
 * high-level
*/

#include <stdlib.h>
#include <vga.h>
#include <vgagl.h>

GraphicsContext *physicalscreen;
GraphicsContext *virtualscreen;

int main(void)
{
   int i, j, c, g, y;
   int *font;

   vga_init();
   vga_setmode(G320x200x256);
   gl_setcontextvga(G320x200x256);
   physicalscreen=gl_allocatecontext();
   gl_getcontext(physicalscreen);
   gl_setcontextvgavirtual(G320x200x256);
   virtualscreen=gl_allocatecontext();
   gl_getcontext(virtualscreen);

   gl_setcontext(virtualscreen);
   y=0;
   c=0;
   gl_setpalettecolor(c, 0, 0, 0);
   c++;
   for (i=0; i<64; i++) {
     g=63-i;
     gl_setpalettecolor(c, 0, g, 0);
     for (j=0; j<3; j++) {
       gl_hline(0, y, 319, c);
       y++;
     }
     c++;
   }

   gl_copyscreen(physicalscreen);

   vga_getch();
   gl_clearscreen(0);
   vga_setmode(TEXT);

   return EXIT_SUCCESS;
}


$ gcc -o Priklad_2 Priklad_2.c -lvgagl -lvga

Zdrojový súbor môže napísať akýkoľvek user. A to je asi tak všetko, čo môže. (Pravdou je, že si ho môže aj skompilovať, ale nič mu to nebude platné, lebo pri použití SVGAlib program potrebuje priamy prístup k HW (ako v M$ DOS) a keďže predpokladám, že takýto user nemá rootovské práva, OS Linuux ho pekne informuje o situácii: svgalib: Cannot get I/O permissions. Treba preto zabezpečiť, aby proces vytvorený spusteným programom mal rootovské práva. A tu opäť pripomeniem bezpečnostné riziko spojené s SETUID bitom, prípadne s bežnou prácou v systéme pod identitou root.

Asi najvhodnejším postupom bude, ak user (napr. tatinko) napíše zdrojový text, root ho skompiluje a takto vzniknutému spustiteľnému súboru nastaví s bit.

$ vi Priklad_1.c

i

... píšeme zdroják ...

Esc

:wq

$ su

# gcc -o Priklad_1 Priklad_1.c -lvga

# chmod s+u Priklad_1

# exit

Následne bežný user spustí aplikáciu.

$ ./Priklad_1

V konzole to môže vyzerať asi nejako takto (sodou okolností sa aj stroj volá tatinko, asi to bude tatinkov stroj):

gcc

Výpis adresára môže vyzerať asi nejako takto:

$ ls --color -al

ls

Manuálové stránky SVGAlib

Tak sem budeme chodiť často. Z konzoly man svgalib alebo man vgagl. Podrobný opis jednotlivých funkcií je tiež v manuálových stránkach, napr. man vga_setmode. Z X-Windows je možno zobraziť manuálové stránky klávesovou skratkou Alt-F2 a do chlievika príkaz zadáme # (hash) a meno príkazu, napr. #vga_setmode.

Pre úvodné oboznámenie sa s jednotlivými funkciami nasleduje výpis jednotlivých funkcií (tiež z manuálových stránok). Manuálové stránky sú dobré! A to nielen pre knižnicu SVGAlib.

   Initialization

       vga_init(3)
          - initialize svgalib library.
       vga_disabledriverreport(3)
          - makes svgalib not emit any startup messages.
       vga_claimvideomemory(3)
          - declare the amount of video memory used.
       vga_safety_fork(3)
          - start a parallel process to restore the console
            at a crash.
       vga_setchipset(3)
          - force chipset.
       vga_setchipsetandfeatures(3)
          - force chipset and optional parameters.

   Inquire hardware configuration

       vga_getmousetype(3)
          - returns the mouse type configured.
       vga_getcurrentchipset(3)
          - returns the current SVGA chipset.
       vga_getmonitortype(3)
          - returns the monitor type configured.

   Setting video modes

       vga_setmode(3)
          - sets a video mode.
       vga_setdisplaystart(3)
          - set the display start address.
       vga_setlogicalwidth(3)
          - set the logical scanline width.
       vga_setlinearaddressing(3)
          - switch to linear addressing mode.
       vga_setmodeX(3)
          - try to set Mode X-like memory organization .
       vga_ext_set(3)
          - set and query several extended features.
       vga_screenoff(3), vga_screenon(3)
          - turn generation of the video signal on or off.

   Get video mode information

       vga_getxdim(3), vga_getydim(3), vga_getcolors(3)
          - return the current screen resolution.
       vga_white(3)
          - return the color white in the current screen res-
            olution.
       vga_getcurrentmode(3)
          - returns the current video mode.
       vga_hasmode(3)
          - returns if a video mode is supported.
       vga_getmodeinfo(3)
          - returns pointer to mode information structure for
            a mode.
       vga_getdefaultmode(3)
          - returns the default graphics mode number.
       vga_lastmodenumber(3)
          - returns the last video mode number.
       vga_getmodename(3)
          - return a name for the given video mode.
       vga_getmodenumber(3)
          - return a number for the given video mode.

   Drawing primitives

       vga_clear(3)
          - clear the screen.
       vga_setcolor(3)
          - set the current color.
       vga_setrgbcolor(3)
          - set the current color.
       vga_setegacolor(3)
          - set the current color.
       vga_drawpixel(3)
          - draw a pixel on the screen.
       vga_drawscanline(3)
          - draw a horizontal line of pixels.
       vga_drawscansegment(3)
          - draw a horizontal line of pixels.
       vga_drawline(3)
          - draw a line on the screen.
       vga_getpixel(3)
          - get a pixels value from the screen.
       vga_getscansegment(3)
          - get a list of consecutive pixel values.
       vga_waitretrace(3)
          - wait for vertical retrace.

   Basic (non raw) keyboard I/O

       vga_getch(3)
          - wait for a key.
       vga_getkey(3)
          - read a character from the keyboard without  wait-
          ing.
       vga_waitevent(3)
          - wait for various I/O events.

   Direct VGA memory access

       vga_setpage(3)
          - set the 64K SVGA page number.
       vga_setreadpage(3)
          - set the 64K SVGA page number.
       vga_setwritepage(3)
          - set the 64K SVGA page number.
       vga_getgraphmem(3)
          - returns the address of the VGA memory.
       vga_copytoplanar256(3)
          - copy linear pixmap into Mode X video memory.
       vga_copytoplanar16(3)
          - copy  linear pixmap into VGA 16 color mode video
            memory.
       vga_copytoplane(3)
          - copy linear pixmap to some planes of VGA 16 color
            mode video memory.

   Manage color lookup tables

       vga_setpalette(3)
          - set a color in the color lookup table.
       vga_getpalette(3)
          - get a color in the color lookup table.
       vga_setpalvec(3)
          - sets colors in the color lookup table.
       vga_getpalvec(3)
          - gets colors from the color lookup table.

   Mouse handling

       vga_setmousesupport(3)
          - enable mouse support.
       mouse_init(3), mouse_init_return_fd(3)
          - specifically initialize a mouse.
       mouse_close(3)
          - explicitly close a mouse.
       mouse_update(3)
          - updates the mouse state.
       mouse_waitforupdate(3)
          - wait for an mouse update.
       mouse_setscale(3)
          - sets a mouse scale factor.
       mouse_setwrap(3)
          - set what happens at the mouse boundaries.
       mouse_setxrange(3), mouse_setyrange(3)
          - define the boundaries for the mouse cursor.
       mouse_getx(3), mouse_gety(3), mouse_getbutton(3)
          - query the mouse state.
       mouse_setposition(3)
          - set the current mouse position.
       mouse_getposition_6d(3), mouse_setposition_6d(3),
       mouse_setrange_6d(3)
          - provide an interface to 3d mice.
       mouse_seteventhandler(3), mouse_setdefaulteventhandler(3)
          - set a mouse event handler.

   Raw keyboard handling

       keyboard_init(3), keyboard_init_return_fd(3)
          - initialize the keyboard to raw mode.
       keyboard_close(3)
          - return the keyboard to normal operation from raw
            mode.
       keyboard_update(3), keyboard_waitforupdate(3)
          - process raw keyboard events.
       keyboard_translatekeys(3)
          - modify scancode mappings in raw keyboard mode.
       keyboard_keypressed(3)
          - check if a key is pressed when in raw keyboard
            mode.
       keyboard_getstate(3)
          - get  a pointer to a buffer holding the state of
            all keys in raw keyboard mode.
       keyboard_clearstate(3)
          - reset the state of all keys when in raw keyboard
            mode.
       keyboard_seteventhandler(3), keyboard_setdefaulteven-
       thandler(3)
          - define an event handler for keyboard events in
            raw mode.

   Joystick handling

       joystick_init(3)
          - initialize and calibrate joysticks.
       joystick_close(3)
          - close a joystick device.
       joystick_update(3)
          - query and process joystick state changes.
       joystick_sethandler(3), joystick_setdefaulthandler(3)
          - define own joystick even handler.
       joystick_getnumaxes(3), joystick_getnumbuttons(3)
          - query the capabilities of a joystick.
       joystick_getaxis(3), joystick_getbutton(3)
          - query the state of a joystick.
       joystick_button1|2|3|4(3), joystick_getb1|2|3|4(3),
       joystick_x|y|z(3), joystick_getx|y|z(3)
          - convenience macros to query the joystick position.

   Accelerator interface (new style)

       vga_accel(3)
          - calls the graphics accelerator.

   Accelerator interface (old style)

       vga_bitblt(3)
          - copy pixmap on screen using an accelerator.
       vga_fillblt(3)
          - fill rectangular area in video memory with a sin-
            gle color.
       vga_hlinelistblt(3)
          - draw horizontal scan lines.
       vga_imageblt(3)
          - copy  a rectangular pixmap from system memory to
            video memory.
       vga_blitwait(3)
          - wait for any accelerator operation to finish.

   Controlling VC switches

       vga_lockvc(3)
          - disables virtual console switching for safety.
       vga_unlockvc(3)
          - re-enables virtual console switching.
       vga_oktowrite(3)
          - indicates whether the program has  direct  access
            to the SVGA.
       vga_runinbackground(3)
          - enable running of the program while there is no
            VGA access.
       vga_runinbackground_version(3)
          - returns the version  of the  current  background
            support.

   Debugging aids

       vga_dumpregs(3)
          - dump the contents of the SVGA registers.
       vga_gettextfont(3), vga_puttextfont(3)
          - get/set the font used in text mode.
       vga_gettextmoderegs(3), vga_settextmoderegs(3)
          - get/set the vga state used in text mode.
       vga_flip(3)
          - toggle between text and graphics mode.
       vga_setflipchar(3)
          - set the character causing a vga_flip().
<<- ->>