善用 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
留言
張貼留言