1/* 2 * Test the GL_NV_texture_rectangle and GL_MESA_ycrcb_texture extensions and GLX_MESA_allocate-memory 3 * 4 * Dave Airlie - Feb 2005 5 */ 6 7#include <assert.h> 8#include <math.h> 9#include <stdio.h> 10#include <stdlib.h> 11#include <string.h> 12#include <X11/Xlib.h> 13#include <X11/keysym.h> 14#define GL_GLEXT_PROTOTYPES 15#include <GL/glx.h> 16 17#include "../util/readtex.c" /* I know, this is a hack. */ 18 19#define TEXTURE_FILE DEMOS_DATA_DIR "girl2.rgb" 20 21static GLfloat Xrot = 0, Yrot = 0, Zrot = 0; 22static GLint ImgWidth, ImgHeight; 23static GLushort *ImageYUV = NULL; 24static void *glx_memory; 25 26static void DrawObject(void) 27{ 28 glBegin(GL_QUADS); 29 30 glTexCoord2f(0, 0); 31 glVertex2f(-1.0, -1.0); 32 33 glTexCoord2f(ImgWidth, 0); 34 glVertex2f(1.0, -1.0); 35 36 glTexCoord2f(ImgWidth, ImgHeight); 37 glVertex2f(1.0, 1.0); 38 39 glTexCoord2f(0, ImgHeight); 40 glVertex2f(-1.0, 1.0); 41 42 glEnd(); 43} 44 45 46static void scr_Display( void ) 47{ 48 glClear( GL_COLOR_BUFFER_BIT ); 49 50 glPushMatrix(); 51 glRotatef(Xrot, 1.0, 0.0, 0.0); 52 glRotatef(Yrot, 0.0, 1.0, 0.0); 53 glRotatef(Zrot, 0.0, 0.0, 1.0); 54 DrawObject(); 55 glPopMatrix(); 56 57} 58 59 60static void Reshape( int width, int height ) 61{ 62 glViewport( 0, 0, width, height ); 63 glMatrixMode( GL_PROJECTION ); 64 glLoadIdentity(); 65 glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 ); 66 glMatrixMode( GL_MODELVIEW ); 67 glLoadIdentity(); 68 glTranslatef( 0.0, 0.0, -15.0 ); 69} 70 71static int queryClient(Display *dpy, int screen) 72{ 73#ifdef GLX_MESA_allocate_memory 74 char *extensions; 75 76 extensions = (char *)glXQueryExtensionsString(dpy, screen); 77 if (!extensions || !strstr(extensions,"GLX_MESA_allocate_memory")) { 78 return 0; 79 } 80 81 return 1; 82#else 83 return 0; 84#endif 85} 86 87static int 88query_extension(char* extName) { 89 char *p = (char *) glGetString(GL_EXTENSIONS); 90 char *end = p + strlen(p); 91 while (p < end) { 92 int n = strcspn(p, " "); 93 if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0)) 94 return GL_TRUE; 95 p += (n + 1); 96 } 97 return GL_FALSE; 98} 99 100static void Init( int argc, char *argv[] , Display *dpy, int screen, Window win) 101{ 102 GLuint texObj = 100; 103 const char *file; 104 void *glx_memory = NULL; 105 106 if (!query_extension("GL_NV_texture_rectangle")) { 107 printf("Sorry, GL_NV_texture_rectangle is required\n"); 108 exit(0); 109 } 110 111 if (!query_extension("GL_MESA_ycbcr_texture")) { 112 printf("Sorry, GL_MESA_ycbcr_texture is required\n"); 113 exit(0); 114 } 115 116 if (!queryClient(dpy, screen)) { 117 printf("Sorry, GLX_MESA_allocate_memory is required\n"); 118 exit(0); 119 } 120 121 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1); 122 glBindTexture(GL_TEXTURE_RECTANGLE_NV, texObj); 123#ifdef LINEAR_FILTER 124 /* linear filtering looks much nicer but is much slower for Mesa */ 125 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 126 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 127#else 128 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 129 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 130#endif 131 132 if (argc > 1) 133 file = argv[1]; 134 else 135 file = TEXTURE_FILE; 136 137 ImageYUV = LoadYUVImage(file, &ImgWidth, &ImgHeight); 138 if (!ImageYUV) { 139 printf("Couldn't read %s\n", TEXTURE_FILE); 140 exit(0); 141 } 142 143#ifdef GLX_MESA_allocate_memory 144 glx_memory = glXAllocateMemoryMESA(dpy, screen, ImgWidth * ImgHeight * 2, 0, 0 ,0); 145#endif 146 if (!glx_memory) 147 { 148 fprintf(stderr,"Failed to allocate MESA memory\n"); 149 exit(-1); 150 } 151 152 memcpy(glx_memory, ImageYUV, ImgWidth * ImgHeight * 2); 153 154 printf("Image: %dx%d\n", ImgWidth, ImgHeight); 155 156 glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 157 GL_YCBCR_MESA, ImgWidth, ImgHeight, 0, 158 GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_APPLE, glx_memory); 159 160 assert(glGetError() == GL_NO_ERROR); 161 162 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 163 164 glEnable(GL_TEXTURE_RECTANGLE_NV); 165 166 glShadeModel(GL_FLAT); 167 glClearColor(0.3, 0.3, 0.4, 1.0); 168 169} 170 171/* 172 * Create an RGB, double-buffered window. 173 * Return the window and context handles. 174 */ 175static void 176make_window( Display *dpy, const char *name, 177 int x, int y, int width, int height, 178 Window *winRet, GLXContext *ctxRet) 179{ 180 int attribs[] = { GLX_RGBA, 181 GLX_RED_SIZE, 1, 182 GLX_GREEN_SIZE, 1, 183 GLX_BLUE_SIZE, 1, 184 GLX_DOUBLEBUFFER, 185 GLX_DEPTH_SIZE, 1, 186 None }; 187 int scrnum; 188 XSetWindowAttributes attr; 189 unsigned long mask; 190 Window root; 191 Window win; 192 GLXContext ctx; 193 XVisualInfo *visinfo; 194 195 scrnum = DefaultScreen( dpy ); 196 root = RootWindow( dpy, scrnum ); 197 198 visinfo = glXChooseVisual( dpy, scrnum, attribs ); 199 if (!visinfo) { 200 printf("Error: couldn't get an RGB, Double-buffered visual\n"); 201 exit(1); 202 } 203 204 /* window attributes */ 205 attr.background_pixel = 0; 206 attr.border_pixel = 0; 207 attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); 208 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 209 attr.override_redirect = 0; 210 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; 211 212 win = XCreateWindow( dpy, root, 0, 0, width, height, 213 0, visinfo->depth, InputOutput, 214 visinfo->visual, mask, &attr ); 215 216 /* set hints and properties */ 217 { 218 XSizeHints sizehints; 219 sizehints.x = x; 220 sizehints.y = y; 221 sizehints.width = width; 222 sizehints.height = height; 223 sizehints.flags = USSize | USPosition; 224 XSetNormalHints(dpy, win, &sizehints); 225 XSetStandardProperties(dpy, win, name, name, 226 None, (char **)NULL, 0, &sizehints); 227 } 228 229 ctx = glXCreateContext( dpy, visinfo, NULL, True ); 230 if (!ctx) { 231 printf("Error: glXCreateContext failed\n"); 232 exit(1); 233 } 234 235 XFree(visinfo); 236 237 *winRet = win; 238 *ctxRet = ctx; 239} 240 241 242static void 243event_loop(Display *dpy, Window win) 244{ 245 while (1) { 246 while (XPending(dpy) > 0) { 247 XEvent event; 248 XNextEvent(dpy, &event); 249 switch (event.type) { 250 case Expose: 251 /* we'll redraw below */ 252 break; 253 case ConfigureNotify: 254 Reshape(event.xconfigure.width, event.xconfigure.height); 255 break; 256 case KeyPress: 257 { 258 char buffer[10]; 259 int r, code; 260 code = XLookupKeysym(&event.xkey, 0); 261 r = XLookupString(&event.xkey, buffer, sizeof(buffer), 262 NULL, NULL); 263 if (buffer[0] == 27) { 264 /* escape */ 265 return; 266 267 } 268 } 269 } 270 } 271 272 } 273} 274 275 276int 277main(int argc, char *argv[]) 278{ 279 Display *dpy; 280 Window win; 281 GLXContext ctx; 282 char *dpyName = NULL; 283 GLboolean printInfo = GL_FALSE; 284 int i; 285 286 for (i = 1; i < argc; i++) { 287 if (strcmp(argv[i], "-display") == 0) { 288 dpyName = argv[i+1]; 289 i++; 290 } 291 else if (strcmp(argv[i], "-info") == 0) { 292 printInfo = GL_TRUE; 293 } 294 else 295 printf("Warrning: unknown parameter: %s\n", argv[i]); 296 } 297 298 dpy = XOpenDisplay(dpyName); 299 if (!dpy) { 300 printf("Error: couldn't open display %s\n", 301 XDisplayName(dpyName)); 302 return -1; 303 } 304 305 make_window(dpy, "yuvrect_client", 0, 0, 300, 300, &win, &ctx); 306 XMapWindow(dpy, win); 307 glXMakeCurrent(dpy, win, ctx); 308 309 if (printInfo) { 310 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 311 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 312 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 313 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 314 } 315 316 Init(argc, argv, dpy, DefaultScreen(dpy), win); 317 318 scr_Display(); 319 glXSwapBuffers(dpy, win); 320 event_loop(dpy, win); 321 322#ifdef GLX_MESA_allocate_memory 323 glXFreeMemoryMESA(dpy, DefaultScreen(dpy), glx_memory); 324#endif 325 glXDestroyContext(dpy, ctx); 326 XDestroyWindow(dpy, win); 327 XCloseDisplay(dpy); 328 329 return 0; 330} 331