132001f49Smrg/* 232001f49Smrg * Test the GL_NV_texture_rectangle and GL_MESA_ycrcb_texture extensions and GLX_MESA_allocate-memory 332001f49Smrg * 432001f49Smrg * Dave Airlie - Feb 2005 532001f49Smrg */ 632001f49Smrg 732001f49Smrg#include <assert.h> 832001f49Smrg#include <math.h> 932001f49Smrg#include <stdio.h> 1032001f49Smrg#include <stdlib.h> 1132001f49Smrg#include <string.h> 1232001f49Smrg#include <X11/Xlib.h> 1332001f49Smrg#include <X11/keysym.h> 1432001f49Smrg#define GL_GLEXT_PROTOTYPES 1532001f49Smrg#include <GL/glx.h> 1632001f49Smrg 1732001f49Smrg#include "../util/readtex.c" /* I know, this is a hack. */ 1832001f49Smrg 1932001f49Smrg#define TEXTURE_FILE DEMOS_DATA_DIR "girl2.rgb" 2032001f49Smrg 2132001f49Smrgstatic GLfloat Xrot = 0, Yrot = 0, Zrot = 0; 2232001f49Smrgstatic GLint ImgWidth, ImgHeight; 2332001f49Smrgstatic GLushort *ImageYUV = NULL; 2432001f49Smrgstatic void *glx_memory; 2532001f49Smrg 2632001f49Smrgstatic void DrawObject(void) 2732001f49Smrg{ 2832001f49Smrg glBegin(GL_QUADS); 2932001f49Smrg 3032001f49Smrg glTexCoord2f(0, 0); 3132001f49Smrg glVertex2f(-1.0, -1.0); 3232001f49Smrg 3332001f49Smrg glTexCoord2f(ImgWidth, 0); 3432001f49Smrg glVertex2f(1.0, -1.0); 3532001f49Smrg 3632001f49Smrg glTexCoord2f(ImgWidth, ImgHeight); 3732001f49Smrg glVertex2f(1.0, 1.0); 3832001f49Smrg 3932001f49Smrg glTexCoord2f(0, ImgHeight); 4032001f49Smrg glVertex2f(-1.0, 1.0); 4132001f49Smrg 4232001f49Smrg glEnd(); 4332001f49Smrg} 4432001f49Smrg 4532001f49Smrg 4632001f49Smrgstatic void scr_Display( void ) 4732001f49Smrg{ 4832001f49Smrg glClear( GL_COLOR_BUFFER_BIT ); 4932001f49Smrg 5032001f49Smrg glPushMatrix(); 5132001f49Smrg glRotatef(Xrot, 1.0, 0.0, 0.0); 5232001f49Smrg glRotatef(Yrot, 0.0, 1.0, 0.0); 5332001f49Smrg glRotatef(Zrot, 0.0, 0.0, 1.0); 5432001f49Smrg DrawObject(); 5532001f49Smrg glPopMatrix(); 5632001f49Smrg 5732001f49Smrg} 5832001f49Smrg 5932001f49Smrg 6032001f49Smrgstatic void Reshape( int width, int height ) 6132001f49Smrg{ 6232001f49Smrg glViewport( 0, 0, width, height ); 6332001f49Smrg glMatrixMode( GL_PROJECTION ); 6432001f49Smrg glLoadIdentity(); 6532001f49Smrg glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 ); 6632001f49Smrg glMatrixMode( GL_MODELVIEW ); 6732001f49Smrg glLoadIdentity(); 6832001f49Smrg glTranslatef( 0.0, 0.0, -15.0 ); 6932001f49Smrg} 7032001f49Smrg 7132001f49Smrgstatic int queryClient(Display *dpy, int screen) 7232001f49Smrg{ 7332001f49Smrg#ifdef GLX_MESA_allocate_memory 7432001f49Smrg char *extensions; 7532001f49Smrg 7632001f49Smrg extensions = (char *)glXQueryExtensionsString(dpy, screen); 7732001f49Smrg if (!extensions || !strstr(extensions,"GLX_MESA_allocate_memory")) { 7832001f49Smrg return 0; 7932001f49Smrg } 8032001f49Smrg 8132001f49Smrg return 1; 8232001f49Smrg#else 8332001f49Smrg return 0; 8432001f49Smrg#endif 8532001f49Smrg} 8632001f49Smrg 8732001f49Smrgstatic int 8832001f49Smrgquery_extension(char* extName) { 8932001f49Smrg char *p = (char *) glGetString(GL_EXTENSIONS); 9032001f49Smrg char *end = p + strlen(p); 9132001f49Smrg while (p < end) { 9232001f49Smrg int n = strcspn(p, " "); 9332001f49Smrg if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0)) 9432001f49Smrg return GL_TRUE; 9532001f49Smrg p += (n + 1); 9632001f49Smrg } 9732001f49Smrg return GL_FALSE; 9832001f49Smrg} 9932001f49Smrg 10032001f49Smrgstatic void Init( int argc, char *argv[] , Display *dpy, int screen, Window win) 10132001f49Smrg{ 10232001f49Smrg GLuint texObj = 100; 10332001f49Smrg const char *file; 10432001f49Smrg void *glx_memory = NULL; 10532001f49Smrg 10632001f49Smrg if (!query_extension("GL_NV_texture_rectangle")) { 10732001f49Smrg printf("Sorry, GL_NV_texture_rectangle is required\n"); 10832001f49Smrg exit(0); 10932001f49Smrg } 11032001f49Smrg 11132001f49Smrg if (!query_extension("GL_MESA_ycbcr_texture")) { 11232001f49Smrg printf("Sorry, GL_MESA_ycbcr_texture is required\n"); 11332001f49Smrg exit(0); 11432001f49Smrg } 11532001f49Smrg 11632001f49Smrg if (!queryClient(dpy, screen)) { 11732001f49Smrg printf("Sorry, GLX_MESA_allocate_memory is required\n"); 11832001f49Smrg exit(0); 11932001f49Smrg } 12032001f49Smrg 12132001f49Smrg glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1); 12232001f49Smrg glBindTexture(GL_TEXTURE_RECTANGLE_NV, texObj); 12332001f49Smrg#ifdef LINEAR_FILTER 12432001f49Smrg /* linear filtering looks much nicer but is much slower for Mesa */ 12532001f49Smrg glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 12632001f49Smrg glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 12732001f49Smrg#else 12832001f49Smrg glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 12932001f49Smrg glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 13032001f49Smrg#endif 13132001f49Smrg 13232001f49Smrg if (argc > 1) 13332001f49Smrg file = argv[1]; 13432001f49Smrg else 13532001f49Smrg file = TEXTURE_FILE; 13632001f49Smrg 13732001f49Smrg ImageYUV = LoadYUVImage(file, &ImgWidth, &ImgHeight); 13832001f49Smrg if (!ImageYUV) { 13932001f49Smrg printf("Couldn't read %s\n", TEXTURE_FILE); 14032001f49Smrg exit(0); 14132001f49Smrg } 14232001f49Smrg 14332001f49Smrg#ifdef GLX_MESA_allocate_memory 14432001f49Smrg glx_memory = glXAllocateMemoryMESA(dpy, screen, ImgWidth * ImgHeight * 2, 0, 0 ,0); 14532001f49Smrg#endif 14632001f49Smrg if (!glx_memory) 14732001f49Smrg { 14832001f49Smrg fprintf(stderr,"Failed to allocate MESA memory\n"); 14932001f49Smrg exit(-1); 15032001f49Smrg } 15132001f49Smrg 15232001f49Smrg memcpy(glx_memory, ImageYUV, ImgWidth * ImgHeight * 2); 15332001f49Smrg 15432001f49Smrg printf("Image: %dx%d\n", ImgWidth, ImgHeight); 15532001f49Smrg 15632001f49Smrg glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 15732001f49Smrg GL_YCBCR_MESA, ImgWidth, ImgHeight, 0, 15832001f49Smrg GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_APPLE, glx_memory); 15932001f49Smrg 16032001f49Smrg assert(glGetError() == GL_NO_ERROR); 16132001f49Smrg 16232001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 16332001f49Smrg 16432001f49Smrg glEnable(GL_TEXTURE_RECTANGLE_NV); 16532001f49Smrg 16632001f49Smrg glShadeModel(GL_FLAT); 16732001f49Smrg glClearColor(0.3, 0.3, 0.4, 1.0); 16832001f49Smrg 16932001f49Smrg} 17032001f49Smrg 17132001f49Smrg/* 17232001f49Smrg * Create an RGB, double-buffered window. 17332001f49Smrg * Return the window and context handles. 17432001f49Smrg */ 17532001f49Smrgstatic void 17632001f49Smrgmake_window( Display *dpy, const char *name, 17732001f49Smrg int x, int y, int width, int height, 17832001f49Smrg Window *winRet, GLXContext *ctxRet) 17932001f49Smrg{ 18032001f49Smrg int attribs[] = { GLX_RGBA, 18132001f49Smrg GLX_RED_SIZE, 1, 18232001f49Smrg GLX_GREEN_SIZE, 1, 18332001f49Smrg GLX_BLUE_SIZE, 1, 18432001f49Smrg GLX_DOUBLEBUFFER, 18532001f49Smrg GLX_DEPTH_SIZE, 1, 18632001f49Smrg None }; 18732001f49Smrg int scrnum; 18832001f49Smrg XSetWindowAttributes attr; 18932001f49Smrg unsigned long mask; 19032001f49Smrg Window root; 19132001f49Smrg Window win; 19232001f49Smrg GLXContext ctx; 19332001f49Smrg XVisualInfo *visinfo; 19432001f49Smrg 19532001f49Smrg scrnum = DefaultScreen( dpy ); 19632001f49Smrg root = RootWindow( dpy, scrnum ); 19732001f49Smrg 19832001f49Smrg visinfo = glXChooseVisual( dpy, scrnum, attribs ); 19932001f49Smrg if (!visinfo) { 20032001f49Smrg printf("Error: couldn't get an RGB, Double-buffered visual\n"); 20132001f49Smrg exit(1); 20232001f49Smrg } 20332001f49Smrg 20432001f49Smrg /* window attributes */ 20532001f49Smrg attr.background_pixel = 0; 20632001f49Smrg attr.border_pixel = 0; 20732001f49Smrg attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); 20832001f49Smrg attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 20932001f49Smrg attr.override_redirect = 0; 21032001f49Smrg mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; 21132001f49Smrg 21232001f49Smrg win = XCreateWindow( dpy, root, 0, 0, width, height, 21332001f49Smrg 0, visinfo->depth, InputOutput, 21432001f49Smrg visinfo->visual, mask, &attr ); 21532001f49Smrg 21632001f49Smrg /* set hints and properties */ 21732001f49Smrg { 21832001f49Smrg XSizeHints sizehints; 21932001f49Smrg sizehints.x = x; 22032001f49Smrg sizehints.y = y; 22132001f49Smrg sizehints.width = width; 22232001f49Smrg sizehints.height = height; 22332001f49Smrg sizehints.flags = USSize | USPosition; 22432001f49Smrg XSetNormalHints(dpy, win, &sizehints); 22532001f49Smrg XSetStandardProperties(dpy, win, name, name, 22632001f49Smrg None, (char **)NULL, 0, &sizehints); 22732001f49Smrg } 22832001f49Smrg 22932001f49Smrg ctx = glXCreateContext( dpy, visinfo, NULL, True ); 23032001f49Smrg if (!ctx) { 23132001f49Smrg printf("Error: glXCreateContext failed\n"); 23232001f49Smrg exit(1); 23332001f49Smrg } 23432001f49Smrg 23532001f49Smrg XFree(visinfo); 23632001f49Smrg 23732001f49Smrg *winRet = win; 23832001f49Smrg *ctxRet = ctx; 23932001f49Smrg} 24032001f49Smrg 24132001f49Smrg 24232001f49Smrgstatic void 24332001f49Smrgevent_loop(Display *dpy, Window win) 24432001f49Smrg{ 24532001f49Smrg while (1) { 24632001f49Smrg while (XPending(dpy) > 0) { 24732001f49Smrg XEvent event; 24832001f49Smrg XNextEvent(dpy, &event); 24932001f49Smrg switch (event.type) { 25032001f49Smrg case Expose: 25132001f49Smrg /* we'll redraw below */ 25232001f49Smrg break; 25332001f49Smrg case ConfigureNotify: 25432001f49Smrg Reshape(event.xconfigure.width, event.xconfigure.height); 25532001f49Smrg break; 25632001f49Smrg case KeyPress: 25732001f49Smrg { 25832001f49Smrg char buffer[10]; 25932001f49Smrg int r, code; 26032001f49Smrg code = XLookupKeysym(&event.xkey, 0); 26132001f49Smrg r = XLookupString(&event.xkey, buffer, sizeof(buffer), 26232001f49Smrg NULL, NULL); 26332001f49Smrg if (buffer[0] == 27) { 26432001f49Smrg /* escape */ 26532001f49Smrg return; 26632001f49Smrg 26732001f49Smrg } 26832001f49Smrg } 26932001f49Smrg } 27032001f49Smrg } 27132001f49Smrg 27232001f49Smrg } 27332001f49Smrg} 27432001f49Smrg 27532001f49Smrg 27632001f49Smrgint 27732001f49Smrgmain(int argc, char *argv[]) 27832001f49Smrg{ 27932001f49Smrg Display *dpy; 28032001f49Smrg Window win; 28132001f49Smrg GLXContext ctx; 28232001f49Smrg char *dpyName = NULL; 28332001f49Smrg GLboolean printInfo = GL_FALSE; 28432001f49Smrg int i; 28532001f49Smrg 28632001f49Smrg for (i = 1; i < argc; i++) { 28732001f49Smrg if (strcmp(argv[i], "-display") == 0) { 28832001f49Smrg dpyName = argv[i+1]; 28932001f49Smrg i++; 29032001f49Smrg } 29132001f49Smrg else if (strcmp(argv[i], "-info") == 0) { 29232001f49Smrg printInfo = GL_TRUE; 29332001f49Smrg } 29432001f49Smrg else 29532001f49Smrg printf("Warrning: unknown parameter: %s\n", argv[i]); 29632001f49Smrg } 29732001f49Smrg 29832001f49Smrg dpy = XOpenDisplay(dpyName); 29932001f49Smrg if (!dpy) { 30032001f49Smrg printf("Error: couldn't open display %s\n", 30132001f49Smrg XDisplayName(dpyName)); 30232001f49Smrg return -1; 30332001f49Smrg } 30432001f49Smrg 30532001f49Smrg make_window(dpy, "yuvrect_client", 0, 0, 300, 300, &win, &ctx); 30632001f49Smrg XMapWindow(dpy, win); 30732001f49Smrg glXMakeCurrent(dpy, win, ctx); 30832001f49Smrg 30932001f49Smrg if (printInfo) { 31032001f49Smrg printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 31132001f49Smrg printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 31232001f49Smrg printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 31332001f49Smrg printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 31432001f49Smrg } 31532001f49Smrg 31632001f49Smrg Init(argc, argv, dpy, DefaultScreen(dpy), win); 31732001f49Smrg 31832001f49Smrg scr_Display(); 31932001f49Smrg glXSwapBuffers(dpy, win); 32032001f49Smrg event_loop(dpy, win); 32132001f49Smrg 32232001f49Smrg#ifdef GLX_MESA_allocate_memory 32332001f49Smrg glXFreeMemoryMESA(dpy, DefaultScreen(dpy), glx_memory); 32432001f49Smrg#endif 32532001f49Smrg glXDestroyContext(dpy, ctx); 32632001f49Smrg XDestroyWindow(dpy, win); 32732001f49Smrg XCloseDisplay(dpy); 32832001f49Smrg 32932001f49Smrg return 0; 33032001f49Smrg} 331