善用 DRI 加速貼圖
近日以來,筆者都在著手處理 Linux 下圖形運算的議題,不久前也曾發表一篇『善用 XShm 加速貼圖』以探討 X 架構之下的貼圖機制,舊文最後也提出範例,使用共享記憶體(Shared Memory)的方式,達到效能的改善。不過,透過減少資料複製,雖然能有效提升貼圖的效率,但都還只是停留在彌補 X 架構先天上的缺陷,令人不禁去想,是否有更直接的解決方案?尋思,現今硬體能力不可同日而語,幾乎每台電腦都具備著基本能力的影像晶片,若運用 DRI 直接對硬體貼圖應該是種可行的手段。
欲在 X 上透過 DRI 繪圖,最簡單的方法是使用 GLX Extension,藉由建立 OpenGL Window 開啟直接和硬體溝通的管道。我們可以修改與舊文相同的程式碼,並改用 OpenGL 來達成相同的效果:
編譯 GLX 程式:
欲在 X 上透過 DRI 繪圖,最簡單的方法是使用 GLX Extension,藉由建立 OpenGL Window 開啟直接和硬體溝通的管道。我們可以修改與舊文相同的程式碼,並改用 OpenGL 來達成相同的效果:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <X11/Xlib.h> #include <GL/gl.h> #include <GL/glx.h> #include <GL/glu.h> int main(void) { Window win; Display display = XOpenDisplay(getenv("DISPLAY")); unsigned char *buffer; GLint glxattr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 32, GLX_DOUBLEBUFFER, None }; /* Initialize GLX */ xvinfo = glXChooseVisual(display, 0, glxattr); if (xvinfo == NULL) exit(1); /* Initial Window */ win = XCreateSimpleWindow(display, RootWindow(display, DefaultScreen(display)), 0, 0, 100, 100, 0, BlackPixel(display, DefaultScreen(display)), BlackPixel(display, DefaultScreen(display))); XMapWindow(display, win); /* Create context */ glcontext = glXCreateContext(display, vinfo, NULL, GL_TRUE); if (glcontext == NULL) exit(0); glXMakeCurrent(display, win, glcontext); glEnable(GL_DEPTH_TEST); XSync(display, False); /* Allocate image memory for 100x100x32bits */ buffer = (unsigned char *)malloc(sizeof(char) * 100 * 100 * 4); /* Create texture from framebuffer */ glEnable(GL_TEXTURE_2D); glGenTextures(1, &texture_id); glBindTexture(GL_TEXTURE_2D, texture_id); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 100, 100, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)buffer); /* Loop */ while(1) { glViewport(0, 0, 100, 100); glClearColor(0., 0., 0., 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1., 1., -1., 1., -1., 1.); glColor3f(1.0, 1.0, 1.0); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, 0.0); glEnd(); glXSwapBuffers(display, win); usleep(1000); }; /* Release */ glXMakeCurrent(display, None, NULL); glXDestroyContext(display, glcontext); XCloseDisplay(display); }
編譯 GLX 程式:
gcc -o glximage glximage.c -lX11 -lGL -lGLU
留言
張貼留言