Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * x11 helper functions -- blit frames to the screen
  3  *
  4  */
  5 
  6 #include "config.h"
  7 
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #include <strings.h>
 11 #include <errno.h>
 12 #include <assert.h>
 13 #include <pthread.h>
 14 #include <sys/ipc.h>
 15 #include <sys/shm.h>
 16 
 17 #include <X11/Xlib.h>
 18 #include <X11/Intrinsic.h>
 19 #include <X11/extensions/XShm.h>
 20 #ifdef HAVE_LIBXV
 21 # include <X11/extensions/Xv.h>
 22 # include <X11/extensions/Xvlib.h>
 23 #endif
 24 
 25 #if HAVE_GL
 26 # include <GL/gl.h>
 27 # include <GL/glx.h>
 28 #endif
 29 
 30 #include "grab-ng.h"
 31 #include "blit.h"
 32 
 33 /* ------------------------------------------------------------------------ */
 34 
 35 extern XtAppContext    app_context;
 36 extern int             debug;
 37 
 38 unsigned int           x11_dpy_fmtid;
 39 
 40 static int             display_bits = 0;
 41 static unsigned int    display_bytes = 0;
 42 static unsigned int    pixmap_bytes = 0;
 43 static bool            x11_byteswap = 0;
 44 static int             no_mitshm = 0;
 45 static int             gl_error = 0;
 46 
 47 #if HAVE_LIBXV
 48 static int             ver, rel, req, ev, err;
 49 static int             formats;
 50 static int             adaptors;
 51 static XvImageFormatValues  *fo;
 52 static XvAdaptorInfo        *ai;
 53 #endif
 54 
 55 static unsigned int    im_adaptor,im_port = UNSET;
 56 static unsigned int    im_formats[VIDEO_FMT_COUNT];
 57 
 58 static struct SEARCHFORMAT {
 59     unsigned int   depth;
 60     int            order;
 61     unsigned long  red;
 62     unsigned long  green;
 63     unsigned long  blue;
 64     unsigned int   format;
 65 } fmt[] = {
 66     { 2, MSBFirst, 0x7c00,     0x03e0,     0x001f,     VIDEO_RGB15_BE },
 67     { 2, MSBFirst, 0xf800,     0x07e0,     0x001f,     VIDEO_RGB16_BE },
 68     { 2, LSBFirst, 0x7c00,     0x03e0,     0x001f,     VIDEO_RGB15_LE },
 69     { 2, LSBFirst, 0xf800,     0x07e0,     0x001f,     VIDEO_RGB16_LE },
 70 
 71     { 3, LSBFirst, 0x00ff0000, 0x0000ff00, 0x000000ff, VIDEO_BGR24    },
 72     { 3, LSBFirst, 0x000000ff, 0x0000ff00, 0x00ff0000, VIDEO_RGB24    },
 73     { 3, MSBFirst, 0x00ff0000, 0x0000ff00, 0x000000ff, VIDEO_RGB24    },
 74     { 3, MSBFirst, 0x000000ff, 0x0000ff00, 0x00ff0000, VIDEO_BGR24    },
 75 
 76     { 4, LSBFirst, 0x00ff0000, 0x0000ff00, 0x000000ff, VIDEO_BGR32    },
 77     { 4, LSBFirst, 0x0000ff00, 0x00ff0000, 0xff000000, VIDEO_RGB32    },
 78     { 4, MSBFirst, 0x00ff0000, 0x0000ff00, 0x000000ff, VIDEO_RGB32    },
 79     { 4, MSBFirst, 0x0000ff00, 0x00ff0000, 0xff000000, VIDEO_BGR32    },
 80 
 81     { 2, -1,       0,          0,          0,          VIDEO_LUT2     },
 82     { 4, -1,       0,          0,          0,          VIDEO_LUT4     },
 83     { 0 /* END OF LIST */ },
 84 };
 85 
 86 static int
 87 catch_no_mitshm(Display * dpy, XErrorEvent * event)
 88 {
 89     no_mitshm++;
 90     return 0;
 91 }
 92 
 93 static int
 94 catch_gl_error(Display * dpy, XErrorEvent * event)
 95 {
 96     fprintf(stderr,"WARNING: Your OpenGL setup is broken.\n");
 97     gl_error++;
 98     return 0;
 99 }
100 
101 /* ------------------------------------------------------------------------ */
102 /* plain X11 stuff                                                          */
103 
104 Visual*
105 x11_find_visual(Display *dpy)
106 {
107     XVisualInfo  *info, template;
108     Visual*      vi = CopyFromParent;
109     int          found,i;
110     char         *class;
111 
112     template.screen = XDefaultScreen(dpy);
113     info = XGetVisualInfo(dpy, VisualScreenMask,&template,&found);
114     for (i = 0; i < found; i++) {
115         switch (info[i].class) {
116         case StaticGray:   class = "StaticGray";  break;
117         case GrayScale:    class = "GrayScale";   break;
118         case StaticColor:  class = "StaticColor"; break;
119         case PseudoColor:  class = "PseudoColor"; break;
120         case TrueColor:    class = "TrueColor";   break;
121         case DirectColor:  class = "DirectColor"; break;
122         default:           class = "UNKNOWN";     break;
123         }
124         if (debug)
125             fprintf(stderr,"visual: id=0x%lx class=%d (%s), depth=%d\n",
126                     info[i].visualid,info[i].class,class,info[i].depth);
127     }
128     for (i = 0; vi == CopyFromParent && i < found; i++)
129         if (info[i].class == TrueColor && info[i].depth >= 15)
130             vi = info[i].visual;
131     for (i = 0; vi == CopyFromParent && i < found; i++)
132         if (info[i].class == StaticGray && info[i].depth == 8)
133             vi = info[i].visual;
134     return vi;
135 }
136 
137 void
138 x11_init_visual(Display *dpy, XVisualInfo *vinfo)
139 {
140     XPixmapFormatValues *pf;
141     int                  i,n;
142     int                  format = 0;
143 
144     if (!XShmQueryExtension(dpy))
145         no_mitshm = 1;
146 
147     display_bits = vinfo->depth;
148     display_bytes = (display_bits+7)/8;
149 
150     pf = XListPixmapFormats(dpy,&n);
151     for (i = 0; i < n; i++)
152         if (pf[i].depth == display_bits)
153             pixmap_bytes = pf[i].bits_per_pixel/8;
154 
155     if (debug) {
156         fprintf(stderr,"x11: color depth: "
157                 "%d bits, %d bytes - pixmap: %d bytes\n",
158                 display_bits,display_bytes,pixmap_bytes);
159         if (vinfo->class == TrueColor || vinfo->class == DirectColor)
160             fprintf(stderr, "x11: color masks: "
161                     "red=0x%08lx green=0x%08lx blue=0x%08lx\n",
162                     vinfo->red_mask, vinfo->green_mask, vinfo->blue_mask);
163         fprintf(stderr,"x11: server byte order: %s\n",
164                 ImageByteOrder(dpy)==LSBFirst ? "little endian":"big endian");
165         fprintf(stderr,"x11: client byte order: %s\n",
166                 BYTE_ORDER==LITTLE_ENDIAN ? "little endian":"big endian");
167     }
168     if (ImageByteOrder(dpy)==LSBFirst && BYTE_ORDER!=LITTLE_ENDIAN)
169         x11_byteswap=1;
170     if (ImageByteOrder(dpy)==MSBFirst && BYTE_ORDER!=BIG_ENDIAN)
171         x11_byteswap=1;
172     if (vinfo->class == TrueColor /* || vinfo->class == DirectColor */) {
173         /* pixmap format */
174         for (i = 0; fmt[i].depth > 0; i++) {
175             if (fmt[i].depth  == pixmap_bytes                               &&
176                 (fmt[i].order == ImageByteOrder(dpy) || fmt[i].order == -1) &&
177                 (fmt[i].red   == vinfo->red_mask     || fmt[i].red   == 0)  &&
178                 (fmt[i].green == vinfo->green_mask   || fmt[i].green == 0)  &&
179                 (fmt[i].blue  == vinfo->blue_mask    || fmt[i].blue  == 0)) {
180                 x11_dpy_fmtid = fmt[i].format;
181                 break;
182             }
183         }
184         if (fmt[i].depth == 0) {
185             fprintf(stderr, "Huh?\n");
186             exit(1);
187         }
188         ng_lut_init(vinfo->red_mask, vinfo->green_mask, vinfo->blue_mask,
189                     x11_dpy_fmtid,x11_byteswap);
190         /* guess physical screen format */
191         if (ImageByteOrder(dpy) == MSBFirst) {
192             switch (pixmap_bytes) {
193             case 2: format = (display_bits==15) ?
194                         VIDEO_RGB15_BE : VIDEO_RGB16_BE; break;
195             case 3: format = VIDEO_RGB24; break;
196             case 4: format = VIDEO_RGB32; break;
197             }
198         } else {
199             switch (pixmap_bytes) {
200             case 2: format = (display_bits==15) ?
201                         VIDEO_RGB15_LE : VIDEO_RGB16_LE; break;
202             case 3: format = VIDEO_BGR24; break;
203             case 4: format = VIDEO_BGR32; break;
204             }
205         }
206     }
207     if (vinfo->class == StaticGray && vinfo->depth == 8) {
208         format = VIDEO_GRAY;
209     }
210     if (0 == format) {
211         if (vinfo->class == PseudoColor && vinfo->depth == 8) {
212             fprintf(stderr,
213 "\n"
214 "8-bit Pseudocolor Visual (256 colors) is *not* supported.\n"
215 "You can startup X11 either with 15 bpp (or more)...\n"
216 "       xinit -- -bpp 16\n"
217 "... or with StaticGray visual:\n"
218 "       xinit -- -cc StaticGray\n"
219             );
220         } else {
221             fprintf(stderr, "Sorry, I can't handle your strange display\n");
222         }
223         exit(1);
224     }
225     x11_dpy_fmtid = format;
226 }
227 
228 XImage*
229 x11_create_ximage(Display *dpy, XVisualInfo *vinfo,
230                   int width, int height, XShmSegmentInfo **shm)
231 {
232     XImage          *ximage = NULL;
233     unsigned char   *ximage_data;
234     XShmSegmentInfo *shminfo = NULL;
235     void            *old_handler;
236     
237     if (no_mitshm)
238         goto no_mitshm;
239 
240     assert(width > 0 && height > 0);
241     
242     old_handler = XSetErrorHandler(catch_no_mitshm);
243     shminfo = malloc(sizeof(XShmSegmentInfo));
244     memset(shminfo, 0, sizeof(XShmSegmentInfo));
245     ximage = XShmCreateImage(dpy,vinfo->visual,vinfo->depth,
246                              ZPixmap, NULL,
247                              shminfo, width, height);
248     if (NULL == ximage)
249         goto shm_error;
250     shminfo->shmid = shmget(IPC_PRIVATE,
251                             ximage->bytes_per_line * ximage->height,
252                             IPC_CREAT | 0777);
253     if (-1 == shminfo->shmid) {
254         perror("shmget [x11]");
255         goto shm_error;
256     }
257     shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
258     if ((void *)-1 == shminfo->shmaddr) {
259         perror("shmat");
260         goto shm_error;
261     }
262     ximage->data = shminfo->shmaddr;
263     shminfo->readOnly = False;
264     
265     XShmAttach(dpy, shminfo);
266     XSync(dpy, False);
267     if (no_mitshm)
268         goto shm_error;
269     shmctl(shminfo->shmid, IPC_RMID, 0);
270     XSetErrorHandler(old_handler);
271     *shm = shminfo;
272     return ximage;
273 
274  shm_error:
275     if (ximage) {
276         XDestroyImage(ximage);
277         ximage = NULL;
278     }
279     if ((void *)-1 != shminfo->shmaddr  &&  NULL != shminfo->shmaddr)
280         shmdt(shminfo->shmaddr);
281     free(shminfo);
282     XSetErrorHandler(old_handler);
283     no_mitshm = 1;
284 
285  no_mitshm:
286     *shm = NULL;
287     if (NULL == (ximage_data = malloc(width * height * pixmap_bytes))) {
288         fprintf(stderr,"out of memory\n");
289         exit(1);
290     }
291     ximage = XCreateImage(dpy, vinfo->visual, vinfo->depth,
292                           ZPixmap, 0, ximage_data,
293                           width, height,
294                           8, 0);
295     memset(ximage->data, 0, ximage->bytes_per_line * ximage->height);
296     return ximage;
297 }
298 
299 void
300 x11_destroy_ximage(Display *dpy, XImage *ximage, XShmSegmentInfo *shm)
301 {
302     if (shm && !no_mitshm) {
303         XShmDetach(dpy, shm);
304         XDestroyImage(ximage);
305         shmdt(shm->shmaddr);
306         free(shm);
307     } else
308         XDestroyImage(ximage);
309 }
310 
311 void x11_blit(Display *dpy, Drawable dr, GC gc, XImage *xi,
312               int a, int b, int c, int d, int w, int h)
313 {
314     if (no_mitshm)
315         XPutImage(dpy,dr,gc,xi,a,b,c,d,w,h);
316     else
317         XShmPutImage(dpy,dr,gc,xi,a,b,c,d,w,h,True);
318 }
319 
320 Pixmap
321 x11_create_pixmap(Display *dpy, XVisualInfo *vinfo, struct ng_video_buf *buf)
322 {
323     Pixmap          pixmap;
324     XImage          *ximage;
325     GC              gc;
326     XShmSegmentInfo *shm;
327     Screen          *scr = DefaultScreenOfDisplay(dpy);
328 
329     pixmap = XCreatePixmap(dpy,RootWindowOfScreen(scr),
330                            buf->fmt.width, buf->fmt.height, vinfo->depth);
331 
332     gc = XCreateGC(dpy, pixmap, 0, NULL);
333 
334     if (NULL == (ximage = x11_create_ximage(dpy, vinfo, buf->fmt.width,
335                                             buf->fmt.height, &shm))) {
336         XFreePixmap(dpy, pixmap);
337         XFreeGC(dpy, gc);
338         return 0;
339     }
340     memcpy(ximage->data,buf->data,buf->size);
341     x11_blit(dpy, pixmap, gc, ximage, 0, 0, 0, 0,
342              buf->fmt.width, buf->fmt.height);
343     x11_destroy_ximage(dpy, ximage, shm);
344     XFreeGC(dpy, gc);
345     return pixmap;
346 }
347 
348 /* ------------------------------------------------------------------------ */
349 /* XVideo extention code                                                    */
350 
351 #ifdef HAVE_LIBXV
352 void xv_image_init(Display *dpy)
353 {
354     int i;
355 
356     if (Success != XvQueryExtension(dpy,&ver,&rel,&req,&ev,&err)) {
357         if (debug)
358             fprintf(stderr,"Xvideo: Server has no Xvideo extention support\n");
359         return;
360     }
361     if (Success != XvQueryAdaptors(dpy,DefaultRootWindow(dpy),&adaptors,&ai)) {
362         fprintf(stderr,"Xvideo: XvQueryAdaptors failed");
363         return;
364     }
365     for (i = 0; i < adaptors; i++) {
366         if ((ai[i].type & XvInputMask) &&
367             (ai[i].type & XvImageMask) &&
368             (im_port == UNSET)) {
369             im_port = ai[i].base_id;
370             im_adaptor = i;
371         }
372     }
373     if (UNSET == im_port)
374         return;
375 
376     fo = XvListImageFormats(dpy, im_port, &formats);
377     for(i = 0; i < formats; i++) {
378         if (debug)
379             fprintf(stderr, "blit: xv: 0x%x (%c%c%c%c) %s",
380                     fo[i].id,
381                     (fo[i].id)       & 0xff,
382                     (fo[i].id >>  8) & 0xff,
383                     (fo[i].id >> 16) & 0xff,
384                     (fo[i].id >> 24) & 0xff,
385                     (fo[i].format == XvPacked) ? "packed" : "planar");
386         if (0x32595559 == fo[i].id) {
387             im_formats[VIDEO_YUYV] = fo[i].id;
388             if (debug)
389                 fprintf(stderr," [ok: %s]",ng_vfmt_to_desc[VIDEO_YUYV]);
390         }
391         if (0x59565955 == fo[i].id) {
392             im_formats[VIDEO_UYVY] = fo[i].id;
393             if (debug)
394                 fprintf(stderr," [ok: %s]",ng_vfmt_to_desc[VIDEO_UYVY]);
395         }
396         if (0x30323449 == fo[i].id) {
397             im_formats[VIDEO_YUV420P] = fo[i].id;
398             if (debug)
399                 fprintf(stderr," [ok: %s]",ng_vfmt_to_desc[VIDEO_YUV420P]);
400         }
401         if (debug)
402             fprintf(stderr,"\n");
403     }
404 }
405 
406 XvImage*
407 xv_create_ximage(Display *dpy, int width, int height, int format,
408                  XShmSegmentInfo **shm)
409 {
410     XvImage         *xvimage = NULL;
411     unsigned char   *ximage_data;
412     XShmSegmentInfo *shminfo = NULL;
413     void            *old_handler;
414     
415     if (no_mitshm)
416         goto no_mitshm;
417     
418     old_handler = XSetErrorHandler(catch_no_mitshm);
419     shminfo = malloc(sizeof(XShmSegmentInfo));
420     memset(shminfo, 0, sizeof(XShmSegmentInfo));
421     xvimage = XvShmCreateImage(dpy, im_port, format, 0,
422                                width, height, shminfo);
423     if (NULL == xvimage)
424         goto shm_error;
425     shminfo->shmid = shmget(IPC_PRIVATE, xvimage->data_size,
426                             IPC_CREAT | 0777);
427     if (-1 == shminfo->shmid) {
428         perror("shmget [xv]");
429         goto shm_error;
430     }
431     shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
432     if ((void *)-1 == shminfo->shmaddr) {
433         perror("shmat");
434         goto shm_error;
435     }
436     xvimage->data = shminfo->shmaddr;
437     shminfo->readOnly = False;
438     
439     XShmAttach(dpy, shminfo);
440     XSync(dpy, False);
441     if (no_mitshm)
442         goto shm_error;
443     shmctl(shminfo->shmid, IPC_RMID, 0);
444     XSetErrorHandler(old_handler);
445     *shm = shminfo;
446     return xvimage;
447 
448 shm_error:
449     if (xvimage) {
450         XFree(xvimage);
451         xvimage = NULL;
452     }
453     if ((void *)-1 != shminfo->shmaddr  &&  NULL != shminfo->shmaddr)
454         shmdt(shminfo->shmaddr);
455     free(shminfo);
456     XSetErrorHandler(old_handler);
457     no_mitshm = 1;
458 
459  no_mitshm:
460     *shm = NULL;
461     if (NULL == (ximage_data = malloc(width * height * 2))) {
462         fprintf(stderr,"out of memory\n");
463         exit(1);
464     }
465     xvimage = XvCreateImage(dpy, im_port, format, ximage_data,
466                             width, height);
467     return xvimage;
468 }
469 
470 void
471 xv_destroy_ximage(Display *dpy, XvImage * xvimage, XShmSegmentInfo *shm)
472 {
473     if (shm && !no_mitshm) {
474         XShmDetach(dpy, shm);
475         XFree(xvimage);
476         shmdt(shm->shmaddr);
477         free(shm);
478     } else
479         XFree(xvimage);
480 }
481 
482 void xv_blit(Display *dpy, Drawable dr, GC gc, XvImage *xi,
483              int a, int b, int c, int d, int x, int y, int w, int h)
484 {
485     if (no_mitshm)
486         XvPutImage(dpy,im_port,dr,gc,xi,a,b,c,d,x,y,w,h);
487     else
488         XvShmPutImage(dpy,im_port,dr,gc,xi,a,b,c,d,x,y,w,h,True);
489 }
490 #endif
491 
492 /* ------------------------------------------------------------------------ */
493 /* OpenGL code                                                              */
494 
495 #if HAVE_GL
496 static int have_gl,max_gl;
497 static int gl_attrib[] = { GLX_RGBA,
498                            GLX_RED_SIZE, 1,
499                            GLX_GREEN_SIZE, 1,
500                            GLX_BLUE_SIZE, 1,
501                            GLX_DOUBLEBUFFER,
502                            None };
503 
504 struct {
505     int  fmt;
506     int  type;
507     char *ext;
508 } gl_formats[VIDEO_FMT_COUNT] = {
509     [ VIDEO_RGB24 ] = {
510         fmt:  GL_RGB,
511         type: GL_UNSIGNED_BYTE,
512     },
513 #ifdef GL_EXT_bgra
514     [ VIDEO_BGR24 ] = {
515         fmt:  GL_BGR_EXT,
516         type: GL_UNSIGNED_BYTE,
517         ext:  "GL_EXT_bgra",
518     },
519     [ VIDEO_BGR32 ] = {
520         fmt:  GL_BGRA_EXT,
521         type: GL_UNSIGNED_BYTE,
522         ext:  "GL_EXT_bgra",
523     },
524 #endif
525 };
526 
527 static int gl_init(Widget widget)
528 {
529     void *old_handler;
530     XVisualInfo *visinfo;
531     GLXContext ctx;
532 
533     if (debug)
534         fprintf(stderr,"blit: gl: init\n");
535     visinfo = glXChooseVisual(XtDisplay(widget),
536                               XScreenNumberOfScreen(XtScreen(widget)),
537                               gl_attrib);
538     if (!visinfo) {
539         if (debug)
540             fprintf(stderr,"blit: gl: can't get visual (rgb,db)\n");
541         return -1;
542     }
543     ctx = glXCreateContext(XtDisplay(widget), visinfo, NULL, True);
544     if (!ctx) {
545         if (debug)
546             fprintf(stderr,"blit: gl: can't create context\n");
547         return -1;
548     }
549 
550     /* there is no point in using OpenGL for image scaling if it
551      * isn't hardware accelerated ... */
552     if (debug)
553         fprintf(stderr, "blit: gl: DRI=%s\n",
554                 glXIsDirect(XtDisplay(widget), ctx) ? "Yes" : "No");
555     if (!glXIsDirect(XtDisplay(widget), ctx))
556         return -1;
557 
558     old_handler = XSetErrorHandler(catch_gl_error);
559     glXMakeCurrent(XtDisplay(widget),XtWindow(widget),ctx);
560     XSync(XtDisplay(widget), False);
561     XSetErrorHandler(old_handler);
562     if (gl_error)
563         return -1;
564     
565     have_gl = 1;
566     glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_gl);
567     if (debug)
568         fprintf(stderr,"blit: gl: texture max size: %d\n",max_gl);
569     return 0;
570 }
571 
572 static int gl_ext(GLubyte *find)
573 {
574     int len = strlen(find);
575     const GLubyte *ext;
576     GLubyte *pos;
577     
578     ext = glGetString(GL_EXTENSIONS);
579     if (NULL == ext)
580         return 0;
581     if (NULL == (pos = strstr(ext,find)))
582         return 0;
583     if (pos != ext && pos[-1] != ' ')
584         return 0;
585     if (pos[len] != ' ' && pos[len] != '\0')
586         return 0;
587     if (debug)
588         fprintf(stderr,"blit: gl: extention %s is available\n",find);
589     return 1;
590 }
591 
592 static int gl_resize(int iw, int ih, int ww, int wh,
593                      GLint *tex, int *tw, int *th, int fmt, int type)
594 {
595     char *dummy;
596     int i;
597     
598     /* check against max size */
599     if (iw > max_gl)
600         return -1;
601     if (ih > max_gl)
602         return -1;
603     
604     /* textures have power-of-two x,y dimensions */
605     for (i = 0; iw >= (1 << i); i++)
606         ;
607     *tw = (1 << i);
608     for (i = 0; ih >= (1 << i); i++)
609         ;
610     *th = (1 << i);
611     if (debug)
612         fprintf(stderr,"blit: gl: frame=%dx%d, texture=%dx%d\n",
613                 iw,ih,*tw,*th);
614 
615     glClearColor (0.0, 0.0, 0.0, 0.0);
616     glShadeModel(GL_FLAT);
617     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
618     
619     glViewport(0, 0, ww, wh);
620     glMatrixMode(GL_PROJECTION);
621     glLoadIdentity();
622     glOrtho(0.0, ww, 0.0, wh, -1, 1);
623     glMatrixMode(GL_MODELVIEW);
624     glLoadIdentity();
625 
626     glGenTextures(1,tex);
627     glBindTexture(GL_TEXTURE_2D,*tex);
628     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
629     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
630     dummy = malloc((*tw)*(*th)*3);
631     memset(dummy,128,(*tw)*(*th)*3);
632     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,*tw,*th,0,
633                  fmt,type,dummy);
634     free(dummy);
635 
636     return 0;
637 }
638 
639 static void gl_cleanup(GLint tex)
640 {
641     /* FIXME: del texture */
642 }
643 
644 static void gl_blit(Widget widget, char *rgbbuf,
645                     int iw, int ih, int ww, int wh,
646                     GLint tex, int tw, int th, int fmt, int type)
647 {
648     float x,y;
649 
650     glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0,iw,ih, fmt,type,rgbbuf);
651     x = (float)iw/tw;
652     y = (float)ih/th;
653 
654     glEnable(GL_TEXTURE_2D);
655     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
656     glBegin(GL_QUADS);
657     glTexCoord2f(0,y);  glVertex3f(0,0,0);
658     glTexCoord2f(0,0);  glVertex3f(0,wh,0);
659     glTexCoord2f(x,0);  glVertex3f(ww,wh,0);
660     glTexCoord2f(x,y);  glVertex3f(ww,0,0);
661     glEnd();
662     glXSwapBuffers(XtDisplay(widget), XtWindow(widget));
663     glDisable(GL_TEXTURE_2D);
664 }
665 #endif
666 
667 /* ------------------------------------------------------------------------ */
668 /* video frame blitter                                                      */
669 
670 enum blit_status {
671     STATUS_UNKNOWN = 0,
672     STATUS_BROKEN  = 1,
673     STATUS_CONVERT = 2,
674     STATUS_XVIDEO  = 3,
675     STATUS_OPENGL  = 4,
676 };
677 
678 struct blit_state {
679     enum blit_status          status;
680     Widget                    widget;
681     Dimension                 win_width, win_height;
682     int                       wx,wy,ww,wh;
683     GC                        gc;
684     XVisualInfo               *vinfo;
685     struct ng_video_fmt       fmt;
686     struct ng_video_buf       buf;
687     struct ng_video_conv      *conv;
688     struct ng_convert_handle  *chandle;
689     XShmSegmentInfo           *shm;
690     XImage                    *ximage;
691 #ifdef HAVE_LIBXV
692     XvImage                   *xvimage;
693 #endif
694 #if HAVE_GL
695     GLint                     tex;
696     int                       tw,th;
697 #endif
698 };
699 
700 struct blit_state*
701 blit_init(Widget widget, XVisualInfo *vinfo, int use_gl)
702 {
703     struct blit_state *st;
704 
705     if (debug)
706         fprintf(stderr,"blit: init\n");
707     BUG_ON(0 == XtWindow(widget), "no blit window");
708     
709     st = malloc(sizeof(*st));
710     memset(st,0,sizeof(*st));
711 
712     st->widget = widget;
713     st->vinfo  = vinfo;
714     st->gc     = XCreateGC(XtDisplay(st->widget),XtWindow(st->widget),0,NULL);
715 #ifdef HAVE_GL
716     if (use_gl)
717         gl_init(st->widget);
718 #endif
719 
720     return st;
721 }
722 
723 void blit_get_formats(struct blit_state *st, int *fmtids, int max)
724 {
725     struct ng_video_conv *conv;
726     int i, n=0;
727 
728     BUG_ON(NULL == st, "blit handle is NULL");
729 
730     /* Xvideo extention */
731 #ifdef HAVE_LIBXV
732     for (i = 0; i < VIDEO_FMT_COUNT; i++) {
733         if (0 != im_formats[i])
734             fmtids[n++] = i;
735         if (n == max)
736             return;
737     }
738 #endif
739 
740 #if HAVE_GL
741     /* OpenGL */
742     if (have_gl) {
743         for (i = 0; i < VIDEO_FMT_COUNT; i++) {
744             if (0 != gl_formats[i].fmt  &&
745                 (NULL == gl_formats[i].ext || gl_ext(gl_formats[i].ext)))
746                 fmtids[n++] = i;
747             if (n == max)
748                 return;
749         }
750     }
751 #endif
752 
753     /* plain X11 */
754     fmtids[n++] = x11_dpy_fmtid;
755     if (n == max)
756         return;
757     for (i = 0;;) {
758         conv = ng_conv_find_to(x11_dpy_fmtid, &i);
759         if (NULL == conv)
760             break;
761         fmtids[n++] = conv->fmtid_in;
762         if (n == max)
763             return;
764     }
765     for (; n < max; n++)
766         fmtids[n] = 0;
767 }
768 
769 void blit_resize(struct blit_state *st, Dimension width, Dimension height)
770 {
771     if (debug)
772         fprintf(stderr,"blit: resize %dx%d\n",width,height);
773     st->win_width  = width;
774     st->win_height = height;
775 
776     st->wx = 0;
777     st->wy = 0;
778     st->ww = st->win_width;
779     st->wh = st->win_height;
780     ng_ratio_fixup(&st->ww, &st->wh, &st->wx, &st->wy);
781 
782     blit_fini_frame(st);
783 }
784 
785 void blit_init_frame(struct blit_state *st, struct ng_video_fmt *fmt)
786 {
787     struct ng_video_conv *conv;
788     int i;
789 
790     /* Xvideo extention */
791 #ifdef HAVE_LIBXV
792     if (0 != im_formats[fmt->fmtid]) {
793         st->xvimage = xv_create_ximage(XtDisplay(st->widget),
794                                        fmt->width, fmt->height,
795                                        im_formats[fmt->fmtid],
796                                        &st->shm);
797         st->buf.fmt = *fmt;
798         st->status  = STATUS_XVIDEO;
799         if (debug)
800             fprintf(stderr,"blit: %dx%d/[%s] => Xvideo\n",
801                     fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid]);
802         return;
803     }
804 #endif
805 
806 #if HAVE_GL
807     /* OpenGL */
808     if (have_gl  &&  0 != gl_formats[fmt->fmtid].fmt  &&
809         (NULL == gl_formats[fmt->fmtid].ext ||
810          gl_ext(gl_formats[fmt->fmtid].ext)) &&
811         0 == gl_resize(fmt->width,fmt->height,
812                        st->win_width,st->win_height,
813                        &st->tex,&st->tw,&st->th,
814                        gl_formats[fmt->fmtid].fmt,
815                        gl_formats[fmt->fmtid].type)) {
816         st->buf.fmt = *fmt;
817         st->status  = STATUS_OPENGL;
818         if (debug)
819             fprintf(stderr,"blit: %dx%d/[%s] => OpenGL\n",
820                     fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid]);
821         return;
822     }
823 #endif
824 
825     /* plain X11 */
826     st->ximage = x11_create_ximage(XtDisplay(st->widget), st->vinfo,
827                                    fmt->width, fmt->height,
828                                    &st->shm);
829     st->buf.data = st->ximage->data;
830     if (x11_dpy_fmtid == fmt->fmtid) {
831         st->buf.fmt = *fmt;
832         st->status  = STATUS_CONVERT;
833         if (debug)
834             fprintf(stderr,"blit: %dx%d/[%s] => X11 direct\n",
835                     fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid]);
836         return;
837     }
838     for (i = 0;;) {
839         conv = ng_conv_find_to(x11_dpy_fmtid, &i);
840         if (NULL == conv) {
841             st->status = STATUS_BROKEN;
842             if (debug)
843                 fprintf(stderr,"blit: %dx%d/[%s] => can't display\n",
844                         fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid]);
845             return;
846         }
847         if (debug)
848             fprintf(stderr,"blit test: %s\n",ng_vfmt_to_desc[conv->fmtid_in]);
849         if (conv->fmtid_in != fmt->fmtid)
850             continue;
851         break;
852     }
853     st->buf.fmt = *fmt;
854     st->status  = STATUS_CONVERT;
855     st->conv    = conv;
856     st->buf.fmt.fmtid  = x11_dpy_fmtid;
857     st->buf.fmt.bytesperline = 0;
858     st->chandle = ng_convert_alloc(st->conv,fmt,&st->buf.fmt);
859     ng_convert_init(st->chandle);
860     if (debug)
861         fprintf(stderr,"blit: %dx%d/[%s] => X11 via [%s]\n",
862                 fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid],
863                 ng_vfmt_to_desc[st->buf.fmt.fmtid]);
864     return;
865 }
866 
867 void blit_fini_frame(struct blit_state *st)
868 {
869     switch (st->status) {
870     case STATUS_CONVERT:
871         if (st->chandle) {
872             ng_convert_fini(st->chandle);
873             st->chandle = NULL;
874         }
875         if (st->ximage) {
876             x11_destroy_ximage(XtDisplay(st->widget),st->ximage,st->shm);
877             st->ximage = NULL;
878         }
879         break;
880         
881 #if HAVE_LIBXV
882     case STATUS_XVIDEO:
883         if (st->xvimage) {
884             xv_destroy_ximage(XtDisplay(st->widget),st->xvimage,st->shm);
885             st->xvimage = NULL;
886         }
887         XvStopVideo(XtDisplay(st->widget), im_port, XtWindow(st->widget));
888         break;
889 #endif
890 
891 #if HAVE_GL     
892     case STATUS_OPENGL:
893         gl_cleanup(st->tex);
894         break;
895 #endif
896         
897     case STATUS_UNKNOWN:
898     case STATUS_BROKEN:
899         break;
900     }
901     memset(&st->fmt,0,sizeof(st->fmt));
902     memset(&st->buf,0,sizeof(st->buf));
903     st->status = STATUS_UNKNOWN;
904 }
905 
906 void blit_fini(struct blit_state *st)
907 {
908     free(st);
909 }
910 
911 void blit_putframe(struct blit_state *st, struct ng_video_buf *buf)
912 {
913     if (st->fmt.fmtid  != buf->fmt.fmtid &&
914         st->fmt.width  != buf->fmt.width &&
915         st->fmt.height != buf->fmt.height) {
916         blit_fini_frame(st);
917         blit_init_frame(st,&buf->fmt);
918         st->fmt = buf->fmt;
919     }
920 
921     if (debug > 1)
922         fprintf(stderr,"blit: putframe\n");
923     switch (st->status) {
924     case STATUS_CONVERT:
925         if (NULL == st->chandle) {
926             memcpy(st->ximage->data,buf->data,buf->size);
927             ng_release_video_buf(buf);
928         } else {
929             buf = ng_convert_frame(st->chandle,&st->buf,buf);
930         }
931         x11_blit(XtDisplay(st->widget), XtWindow(st->widget),
932                  st->gc,st->ximage,0,0,
933                  (st->win_width  - st->buf.fmt.width)  >> 1,
934                  (st->win_height - st->buf.fmt.height) >> 1,
935                  st->buf.fmt.width, st->buf.fmt.height);
936         break;
937         
938 #ifdef HAVE_LIBXV
939     case STATUS_XVIDEO:
940         memcpy(st->xvimage->data,buf->data,buf->size);
941         ng_release_video_buf(buf);
942         xv_blit(XtDisplay(st->widget), XtWindow(st->widget),
943                 st->gc, st->xvimage,
944                 0, 0,  st->buf.fmt.width, st->buf.fmt.height,
945                 st->wx, st->wy, st->ww, st->wh);
946         break;
947 #endif
948         
949 #if HAVE_GL
950     case STATUS_OPENGL:
951         gl_blit(st->widget,buf->data,
952                 st->buf.fmt.width, st->buf.fmt.height,
953                 st->win_width, st->win_height,
954                 st->tex, st->tw, st->th,
955                 gl_formats[buf->fmt.fmtid].fmt,
956                 gl_formats[buf->fmt.fmtid].type);
957         ng_release_video_buf(buf);
958         break;
959 #endif
960         
961     case STATUS_UNKNOWN:
962     case STATUS_BROKEN:
963         if (debug > 1)
964             fprintf(stderr,"blit: putframe: oops: status = %d\n",st->status);
965         ng_release_video_buf(buf);
966         break;
967     }
968 }
969 
  This page was automatically generated by the LXR engine.