HTML

Az élet kódjai

Csináld maga. Senki nem csinálja meg helyetted.

Friss topikok

  • sdani: @Travis.CG: Nohát, nem is tudtam, hogy ilyen van... bár ahogy elnézem ezek a komponensek fizetősek... (2018.11.01. 10:14) Rossz beidegződések a bionformatikában
  • Csenge Tarnói: Ez érdekes. Most csinálok egy meta-analízist, életemben először, úgyhogy az én tudásom is felszíne... (2018.10.01. 21:39) Ez már nekem sok
  • robertherczeg: Nekem a kedvenc az volt, hogy: "Inkább eleve Mann-Whitney és/vagy Wilcoxon tesztet használjunk, m... (2018.09.04. 07:47) Ezért utálom a Wilcoxon-tesztet
  • Travis.CG: ÉÉÉÉÉs megjelent! (2018.08.24. 23:31) Nehéz szülés 2
  • Szedlák Ádám: Hogy én mennyire köszönöm ezt a posztot, arra nincs szó. A kódoljon mindenki / legyen mindenki olc... (2018.06.25. 03:37) Legyen mindenki programozó

GLX és OpenGL 4.1

2011.01.23. 21:47 Travis.CG

Ahogy egyre fejlettebb és fejlettebb lesz kedvenc 3D API-m, úgy kell egyre újabb és újabb keretrendszert készíteni a demóimnak, hogy lépést tartsak a fejlődéssel.

GNU/Linux alatt az OpenGL és az ablak kezelő rendszer kapcsolatáról a GLX gondoskodik. Ez tekinthető a legalacsonyabb rétegnek. A népszerű, kereszt platformos könyvtárak, mint amilyen az SDL vagy a GLUT, mind erre építenek. Mivel én szeretem, ha minél kevesebb réteg van köztem és az általam programozott eszköz között, ezért nem volt kérdés számomra, hogy meg kell ismernem a GLX használatát.

Az első demó, ami erre épült, a csúfos kudarcomnak tekinthető Aeronautism volt. Itt csak OpenGL 2.0 támogatás volt. Az internetet végigöngészve csak 3.0 és 3.1 keretrendszerre találtam példákat. Vagy feleslegesen elbonyolított, vagy hibáktól hemzsegő verziót találtam, de végül sikerült készítenem egy elég türhető rendszert. Röviden bemutatom:

#define GL_GLEXT_PROTOTYPES
#define GLX_GLXEXT_PROTOTYPES
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <stdlib.h>
#include <stdio.h>

#define WIDTH 1024
#define HEIGHT 768

Display *display;
Window   window;
XEvent   event;
KeySym   ks;
GLXContext context;

int main(){
   int conf[] = {GLX_DOUBLEBUFFER, True,
                 GLX_DEPTH_SIZE, 12,
                 GLX_RED_SIZE,    4,
                 GLX_BLUE_SIZE,   4,
                 GLX_GREEN_SIZE,  4,
                 GLX_ALPHA_SIZE,  4,
                 None};

   int gl4attr[] = {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, /* OpenGL major version number */
                    GLX_CONTEXT_MINOR_VERSION_ARB, 1, /* OpenGL minor version number */
                    GLX_CONTEXT_FLAGS_ARB,
                    GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
                    None};
   GLXFBConfig *fbc;
   int fbcount;
   XSetWindowAttributes swa;
   XVisualInfo *visual;

   int isrunning = 1;

   display = XOpenDisplay(NULL);
   fbc = glXChooseFBConfig(display, DefaultScreen(display), conf, &fbcount);
   visual = glXGetVisualFromFBConfig(display, fbc[0]);
   swa.background_pixel = 0;
   swa.border_pixel     = 0;
   swa.colormap         = XCreateColormap(display, RootWindow(display, visual->screen), visual->visual, AllocNone);
   swa.event_mask       = StructureNotifyMask | ExposureMask | KeyPressMask;
   window = XCreateWindow(display, RootWindow(display, visual->screen), 0, 0, WIDTH, HEIGHT, 0, visual->depth, InputOutput, visual->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);
   context = glXCreateContextAttribsARB(display, fbc[0], NULL, True, gl4attr);
   XMapWindow(display, window);
   glXMakeCurrent(display, window, context);
   free(fbc);
   XFree(visual);

   /* Other OpenGL related initialization stuff here */

   while(isrunning){
      while(XPending(display) > 0){
         XNextEvent(display, &event);
         if(event.type == Expose) break;
         if(event.type == KeyPress){
            ks = XLookupKeysym((XKeyEvent*)&event, 0);
            if(ks == XK_Escape) isrunning = 0;
         }
      }

      /* OpenGL drawing stuff here */

      glXSwapBuffers(display, window);
   }

   /* Free resources */
   glXMakeCurrent(display, 0, 0);
   glXDestroyContext(display, context);
   XDestroyWindow(display, window);
   XCloseDisplay(display);
   return(0);
}

A legújabb OpenGL támogatás kiegészítésként érhető el a GLX rendszerben, ezért a GL_GLEXT_PROTOTYPES és GLX_GLXEXT_PROTOTYPES segítségével definiáljuk, hogy mi használni kívánjuk ezeket a kiegészítéseket. A létre hozni kívánt jellemzőket egészeket tartalmazó tömbként kell átadni, ezek láthatóak a conf és gl4attr változóknál. A tömb végét mindkét esetben egy None jelzi.

Az első komoly műveletet az XOpenDisplay végzi. Kapcsolódik az alapértelmezett X kiszolgálóhoz. Minden további műveletben az itt visszakapott mutatóval dolgozunk. A kapcsolat végén az XCloseDisplay szabadítja fel a lefoglalt erőforrást.

A következő lépésnél két lehetőségünk van, hogy megkapjuk az XVisualInfo-t. Az első, régebbi és ezért szélesebb körben elterjedt módszer, egy GLXPixelmap-en keresztül valósítja meg a kapcsolatot a grafikus kártyával. A függvény a glXChooseVisual. Sokat nem akarok róla írni. Hátránya, hogy a grafikus kártya képét még egyszer leképezi a fizikai memóriában.

Amit itt használunk, az a pixel buffer módszer, ahol közvetlenül érjük el a gpu-t. Hátránya, hogy csak újabb meghajtóprogramokkal érhető el, de mivel a demók többsége modern eszközökön fut, ez nem probléma. A glXChooseFBConfig segítségével kiválasztjuk a megfelelő puffert, ami egyezik az igényeinkkel. Ezeket a conf változóban soroltuk fel. Ha nincs ilyen puffer, a függvény visszatérési értéke NULL.

Általában több puffer is megfelelhet az igényeinknek. Választásunkat a glXGetVisualFromFBConfig függvénnyel jelöljük. Mi most egyszerűen csak az elsőt választjuk, de aki akarja ezen kód alapján kiválaszthatja magának a legjobb XVisualInfot.

XCreateWindow-al elkészítjük az ablakunkat, ahol majd ki akarjuk rajzolni a demót. Ami érdekes számunkra, a GLXContext struktúra. a glXCreateContextAttribsARB kiegészítés segítségével fogjuk elkészíteni OpenGL-es közegünket. Igényeinket a gl4attr tömbbel adjuk át. Amennyiben grafikus kártyánk nem támogatja a megadott OpenGL verziószámot, NULL-t kapunk vissza.

A rendszer minden darabja megvan, már csak össze kell kötni őket. Az XMapWindow elhelyezi az ablakunkat, a glXMakeCurrent pedig összeköti a közeget és az ablakot. Mostantól birtokba vehetjük az OpenGL-t. A példaprogram tartalmaz egy viszonylag primitív billentyű leütés figyelést és a kettős puffereléshez elengedhetetlen lapcserét (glXSwapBuffers).

Amennyiben a felhasználó kilép, a program felszabadítja a lefoglalt erőforrásokat. Már csak egy dologgal vagyok adós, a fordítással:

gcc -lX11 -lGL test.c -o test

Megjegyzés: A program jelenlegi formájában egyetlen visszatérési értéket sem vizsgál, ezért ha hibával tér vissza egy függvény, akkor a program tovább megy és olyan függvénynél áll le, ami látszólag jó. Probléma esetén csökkentsük az OpenGL verziószámot vagy a színeknek fenntartott méretet. Az is előfordulhat, hogy a Mesa az automatikus frissítés során felülírja az NVidia meghajtót, amitől egyetlen GLX alapú program sem fog menni.

Szólj hozzá!

Címkék: programozás demoscene opengl

A bejegyzés trackback címe:

https://cybernetic.blog.hu/api/trackback/id/tr502608474

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.