aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2010-04-01 11:24:41 +0200
committerGerd Hoffmann <kraxel@redhat.com>2010-04-01 11:24:41 +0200
commitf7fa2c3713398385948f6af44a1508dcb47e747e (patch)
treefe41849d8588eae33b04d9bd2f90245f83ccd20f
parentd58cbc3c5392e7bacd75c61bfbf9e2bcd2850ae9 (diff)
v3.93
-rw-r--r--contrib/xawtv-bayer.diff377
-rw-r--r--libng/contrib-plugins/linear-blend.c18
-rw-r--r--x11/blit.c33
-rw-r--r--x11/blit.c.orig949
-rw-r--r--x11/blit.c.rej37
-rw-r--r--xawtv.spec2
6 files changed, 1399 insertions, 17 deletions
diff --git a/contrib/xawtv-bayer.diff b/contrib/xawtv-bayer.diff
new file mode 100644
index 0000000..be67eb9
--- /dev/null
+++ b/contrib/xawtv-bayer.diff
@@ -0,0 +1,377 @@
+Ok..This is the patch for xawtv-3.92..
+
+diff -uprN xawtv-3.92/libng/color_bayer2rgb.c xawtv-3.92-devel/libng/color_bayer2rgb.c
+--- xawtv-3.92/libng/color_bayer2rgb.c 1970-01-01 01:00:00.000000000 +0100
++++ xawtv-3.92-devel/libng/color_bayer2rgb.c 2004-05-31 10:37:11.000000000 +0200
+@@ -0,0 +1,257 @@
++/*
++ * colorspace conversion functions
++ * -- bayer to rgb colorspace conversions
++ *
++ * (c) 2004 Luca Risolia <luca.risolia@studio.unibo.it>
++ * Heavily based on color_yuv2rgb.c by Gerd Knorr <kraxel@bytesex.org>
++ * sbggr8_to_rgb24 written by Christopher Cramer
++ */
++
++#define NG_PRIVATE
++#include "config.h"
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <pthread.h>
++#include <sys/time.h>
++#include <sys/types.h>
++
++#include "grab-ng.h"
++
++#define RED 0
++#define GREEN 1
++#define BLUE 2
++
++#define avg2(x,y) ((((int)(x)) + ((int)(y))) / 2)
++#define avg3(x,y,z) ((((int)(x)) + ((int)(y)) + ((int)(z))) / 3)
++#define avg4(w,x,y,z) ((((int)(w)) + ((int)(x)) + ((int)(y)) + ((int)(z))) / 4)
++
++/* ------------------------------------------------------------------- */
++/* bayer bgbg...grgr...to rgb24 */
++
++/*
++ bgbgbg
++ grgrgr
++ bgbgbg
++ grgrgr
++*/
++
++static void
++sbggr8_to_rgb24(void *h, struct ng_video_buf *out, struct ng_video_buf *in)
++{
++ unsigned char *restrict s, *restrict d;
++ unsigned long x, y, i, j;
++
++ d = out->data;
++ s = in->data;
++ x = in->fmt.width;
++ y = in->fmt.height;
++
++ /* upper left corner */
++ d[0 + RED] = s[x + 1];
++ d[0 + BLUE] = s[0];
++ d[0 + GREEN] = ((int)s[1] + (int)s[x]) / 2;
++
++ /* top line (minus corners) */
++ i = 1;
++ while (i < x - 2) {
++ d[i * 3 + RED] = s[x + i];
++ d[i * 3 + GREEN] = s[i];
++ d[i * 3 + BLUE] = avg2(s[i - 1], s[i + 1]);
++
++ i++;
++
++ d[i * 3 + RED] = avg2(s[x + i - 1], s[x + i + 1]);
++ d[i * 3 + GREEN] = avg3(s[i - 1], s[i + 1], s[x + 1]);
++ d[i * 3 + BLUE] = s[i];
++
++ i++;
++ }
++
++ /* upper right corner */
++ d[i * 3 + RED] = s[x + i];
++ d[i * 3 + GREEN] = s[i];
++ d[i * 3 + BLUE] = s[i - 1];
++
++ /* middle lines */
++ j = 1;
++ while (j < y - 2) {
++ d[j * x * 3 + RED] = s[j * x + 1];
++ d[j * x * 3 + GREEN] = s[j * x];
++ d[j * x * 3 + BLUE] = avg2(s[(j - 1) * x], s[(j + 1) * x]);
++
++ i = 1;
++ while (i < x - 2) {
++ d[(j * x + i) * 3 + RED] = s[j * x + i];
++ d[(j * x + i) * 3 + GREEN] = avg4(s[(j - 1) * x + i],
++ s[j * x + i - 1],
++ s[j * x + i + 1],
++ s[(j + 1) * x + i]);
++ d[(j * x + i) * 3 + BLUE] = avg4(s[(j - 1) * x + i - 1],
++ s[(j - 1) * x + i + 1],
++ s[(j + 1) * x + i - 1],
++ s[(j + 1) * x + i + 1]);
++
++ i++;
++
++ d[(j * x + i) * 3 + RED] = avg2(s[j * x + i - 1],
++ s[j * x + i + 1]);
++ d[(j * x + i) * 3 + GREEN] = s[j * x + i];
++ d[(j * x + i) * 3 + BLUE] = avg2(s[(j - 1) * x + i],
++ s[(j + 1) * x + i]);
++
++ i++;
++ }
++
++ d[(j * x + i) * 3 + RED] = s[j * x + i];
++ d[(j * x + i) * 3 + BLUE] = avg2(s[(j - 1) * x + i - 1],
++ s[(j + 1) * x + i - 1]);
++ d[(j * x + i) * 3 + GREEN] = avg2(s[(j - 1) * x + i],
++ s[(j + 1) * x + i]);
++
++ j++;
++
++ d[(j * x + i) * 3 + RED] = avg2(s[(j - 1) * x + i + 1],
++ s[(j + 1) * x + i + 1]);
++ d[(j * x + i) * 3 + BLUE] = s[j * x + i];
++ d[(j * x + i) * 3 + GREEN] = avg3(s[(j - 1) * x + i],
++ s[j * x + i + 1],
++ s[(j + 1) * x + i]);
++
++ i = 1;
++ while (i < x - 2) {
++ d[(j * x + i) * 3 + RED] = avg2(s[(j - 1) * x + i],
++ s[(j + 1) * x + i]);
++ d[(j * x + i) * 3 + GREEN] = s[j * x + i];
++ d[(j * x + i) * 3 + BLUE] = avg2(s[j * x + i - 1],
++ s[j * x + i + 1]);
++
++ i++;
++
++ d[(j * x + i) * 3 + RED] = avg4(s[(j - 1) * x + i - 1],
++ s[(j - 1) * x + i + 1],
++ s[(j + 1) * x + i - 1],
++ s[(j + 1) * x + i + 1]);
++ d[(j * x + i) * 3 + GREEN] = avg4(s[(j - 1) * x + i],
++ s[j * x + i - 1],
++ s[j * x + i + 1],
++ s[(j + 1) * x + i]);
++ d[(j * x + i) * 3 + BLUE] = s[j * x + i];
++
++ i++;
++ }
++
++ j++;
++ }
++
++ /* lower left corner */
++ d[(j * x) * 3 + RED] = s[j * x + 1];
++ d[(j * x) * 3 + GREEN] = s[j * x];
++ d[(j * x) * 3 + BLUE] = s[(j - 1) * x];
++
++ /* bottom line */
++ i = 1;
++ while (i < x - 2) {
++ d[(j * x + i) * 3 + RED] = s[j * x + i];
++ d[(j * x + i) * 3 + GREEN] = avg2(s[j * x + i - 1], s[j * x + i + 1]);
++ d[(j * x + i) * 3 + BLUE] = avg2(s[(j - 1) * x + i - 1],
++ s[(j - 1) * x + i + 1]);
++
++ i++;
++
++ d[(j * x + i) * 3 + RED] = avg2(s[j * x + i - 1], s[j * x + i + 1]);
++ d[(j * x + i) * 3 + GREEN] = s[j * x + i];
++ d[(j * x + i) * 3 + BLUE] = s[(j - 1) * x + i];
++
++ i++;
++ }
++
++ /* lower right corner */
++ d[(j * x + i) * 3 + RED] = s[j * x + i];
++ d[(j * x + i) * 3 + GREEN] = avg2(s[(j - 1) * x + i], s[j * x + i - 1]);
++ d[(j * x + i) * 3 + BLUE] = s[(j - 1) * x + i - 1];
++}
++
++/* ------------------------------------------------------------------- */
++/* bayer bgbg...grgr...to rgb16 */
++
++static void
++sbggr8_to_rgb16(void *p, struct ng_video_buf *out, struct ng_video_buf *in)
++{
++ unsigned char *restrict s1, *restrict s2, *restrict d;
++ unsigned long i, j, x, y, w, h;
++ unsigned char r, g1, g2, b, g;
++
++ w = in->fmt.width;
++ h = in->fmt.height;
++ d = out->data;
++ s1 = in->data;
++ s2 = s1 + w;
++ i = 0;
++ j = w;
++
++ for (y = 0; y < h; y += 2, i += w * 2, j += w * 2) {
++ for (x = 0; x < w; x += 2) {
++
++ b = d[i + x] ;
++ g1 = d[i + 1 + x];
++ g2 = d[j + x];
++ r = d[j + 1 + x];
++ g = (g1 >> 1) + (g2 >> 1);
++
++ *s1 = ( ((r & 0xF8) >> 3) |
++ ((g1 & 0xFC) << 3) |
++ ((b & 0xF8) << 8) );
++
++ s1 += 2;
++
++ *s1 = ( ((r & 0xF8) >> 3) |
++ ((g & 0xFC) << 3) |
++ ((b & 0xF8) << 8) );
++
++ s1 += 2;
++
++ *s2 = ( ((r & 0xF8) >> 3) |
++ ((g & 0xFC) << 3) |
++ ((b & 0xF8) << 8) );
++
++ s2 += 2;
++
++ *s2 = ( ((r & 0xF8) >> 3) |
++ ((g2 & 0xFC) << 3) |
++ ((b & 0xF8) << 8) );
++
++ s2 += 2;
++ }
++ }
++}
++
++/* ------------------------------------------------------------------- */
++
++static struct ng_video_conv conv_list[] = {
++ {
++ init: ng_conv_nop_init,
++ fini: ng_conv_nop_fini,
++ frame: sbggr8_to_rgb24,
++ fmtid_in: VIDEO_SBGGR8,
++ fmtid_out: VIDEO_RGB24,
++ },
++ {
++ init: ng_conv_nop_init,
++ fini: ng_conv_nop_fini,
++ frame: sbggr8_to_rgb16,
++ fmtid_in: VIDEO_SBGGR8,
++ fmtid_out: VIDEO_RGB16_LE,
++ }
++
++};
++static const int nconv = sizeof(conv_list)/sizeof(struct ng_video_conv);
++
++/* ------------------------------------------------------------------- */
++
++void ng_color_bayer2rgb_init(void)
++{
++ /* register stuff */
++ ng_conv_register(NG_PLUGIN_MAGIC,"built-in",conv_list,nconv);
++}
+diff -uprN xawtv-3.92/libng/grab-ng.c xawtv-3.92-devel/libng/grab-ng.c
+--- xawtv-3.92/libng/grab-ng.c 2003-03-28 13:19:28.000000000 +0100
++++ xawtv-3.92-devel/libng/grab-ng.c 2004-05-30 23:59:15.000000000 +0200
+@@ -42,6 +42,7 @@ const unsigned int ng_vfmt_to_depth[] =
+ 0, /* unused */
+ 8, /* RGB8 */
+ 8, /* GRAY8 */
++ 8, /* SBGGR8 */
+ 16, /* RGB15 LE */
+ 16, /* RGB16 LE */
+ 16, /* RGB15 BE */
+@@ -64,6 +65,7 @@ const char* ng_vfmt_to_desc[] = {
+ "none",
+ "8 bit PseudoColor (dithering)",
+ "8 bit StaticGray",
++ "8 bit Sequential Bayer BGGR",
+ "15 bit TrueColor (LE)",
+ "16 bit TrueColor (LE)",
+ "15 bit TrueColor (BE)",
+@@ -865,6 +867,7 @@ ng_init(void)
+ ng_device_init();
+ ng_color_packed_init();
+ ng_color_yuv2rgb_init();
++ ng_color_bayer2rgb_init();
+ ng_writefile_init();
+
+ count += ng_plugins(LIBDIR);
+diff -uprN xawtv-3.92/libng/grab-ng.h xawtv-3.92-devel/libng/grab-ng.h
+--- xawtv-3.92/libng/grab-ng.h 2003-02-14 15:14:07.000000000 +0100
++++ xawtv-3.92-devel/libng/grab-ng.h 2004-05-30 21:44:23.000000000 +0200
+@@ -41,23 +41,24 @@ extern char ng_v4l_conf[256];
+ #define VIDEO_NONE 0
+ #define VIDEO_RGB08 1 /* bt848 dithered */
+ #define VIDEO_GRAY 2
+-#define VIDEO_RGB15_LE 3 /* 15 bpp little endian */
+-#define VIDEO_RGB16_LE 4 /* 16 bpp little endian */
+-#define VIDEO_RGB15_BE 5 /* 15 bpp big endian */
+-#define VIDEO_RGB16_BE 6 /* 16 bpp big endian */
+-#define VIDEO_BGR24 7 /* bgrbgrbgrbgr (LE) */
+-#define VIDEO_BGR32 8 /* bgr-bgr-bgr- (LE) */
+-#define VIDEO_RGB24 9 /* rgbrgbrgbrgb (BE) */
+-#define VIDEO_RGB32 10 /* -rgb-rgb-rgb (BE) */
+-#define VIDEO_LUT2 11 /* lookup-table 2 byte depth */
+-#define VIDEO_LUT4 12 /* lookup-table 4 byte depth */
+-#define VIDEO_YUYV 13 /* 4:2:2 */
+-#define VIDEO_YUV422P 14 /* YUV 4:2:2 (planar) */
+-#define VIDEO_YUV420P 15 /* YUV 4:2:0 (planar) */
+-#define VIDEO_MJPEG 16 /* MJPEG (AVI) */
+-#define VIDEO_JPEG 17 /* JPEG (JFIF) */
+-#define VIDEO_UYVY 18 /* 4:2:2 */
+-#define VIDEO_FMT_COUNT 19
++#define VIDEO_SBGGR8 3 /* 8 bpp lines: bgbgbgbg...grgrgrgr... */
++#define VIDEO_RGB15_LE 4 /* 15 bpp little endian */
++#define VIDEO_RGB16_LE 5 /* 16 bpp little endian */
++#define VIDEO_RGB15_BE 6 /* 15 bpp big endian */
++#define VIDEO_RGB16_BE 7 /* 16 bpp big endian */
++#define VIDEO_BGR24 8 /* bgrbgrbgrbgr (LE) */
++#define VIDEO_BGR32 9 /* bgr-bgr-bgr- (LE) */
++#define VIDEO_RGB24 10 /* rgbrgbrgbrgb (BE) */
++#define VIDEO_RGB32 11 /* -rgb-rgb-rgb (BE) */
++#define VIDEO_LUT2 12 /* lookup-table 2 byte depth */
++#define VIDEO_LUT4 13 /* lookup-table 4 byte depth */
++#define VIDEO_YUYV 14 /* 4:2:2 */
++#define VIDEO_YUV422P 15 /* YUV 4:2:2 (planar) */
++#define VIDEO_YUV420P 16 /* YUV 4:2:0 (planar) */
++#define VIDEO_MJPEG 17 /* MJPEG (AVI) */
++#define VIDEO_JPEG 18 /* JPEG (JFIF) */
++#define VIDEO_UYVY 19 /* 4:2:2 */
++#define VIDEO_FMT_COUNT 20
+
+ #define AUDIO_NONE 0
+ #define AUDIO_U8_MONO 1
+@@ -478,6 +479,7 @@ void ng_rgb24_to_lut4(unsigned char *des
+ /* init functions */
+ void ng_color_packed_init(void);
+ void ng_color_yuv2rgb_init(void);
++void ng_color_bayer2rgb_init(void);
+ void ng_writefile_init(void);
+
+ /* for yuv2rgb using lookup tables (color_lut.c, color_yuv2rgb.c) */
+diff -uprN xawtv-3.92/libng/plugins/drv0-v4l2.c xawtv-3.92-devel/libng/plugins/drv0-v4l2.c
+--- xawtv-3.92/libng/plugins/drv0-v4l2.c 2003-04-09 20:15:07.000000000 +0200
++++ xawtv-3.92-devel/libng/plugins/drv0-v4l2.c 2004-05-30 18:35:20.000000000 +0200
+@@ -134,6 +134,7 @@ struct ng_vid_driver v4l2_driver = {
+ static __u32 xawtv_pixelformat[VIDEO_FMT_COUNT] = {
+ [ VIDEO_RGB08 ] = V4L2_PIX_FMT_HI240,
+ [ VIDEO_GRAY ] = V4L2_PIX_FMT_GREY,
++ [ VIDEO_SBGGR8] = V4L2_PIX_FMT_SBGGR8,
+ [ VIDEO_RGB15_LE ] = V4L2_PIX_FMT_RGB555,
+ [ VIDEO_RGB16_LE ] = V4L2_PIX_FMT_RGB565,
+ [ VIDEO_RGB15_BE ] = V4L2_PIX_FMT_RGB555X,
+diff -uprN xawtv-3.92/libng/Subdir.mk xawtv-3.92-devel/libng/Subdir.mk
+--- xawtv-3.92/libng/Subdir.mk 2003-02-14 15:14:07.000000000 +0100
++++ xawtv-3.92-devel/libng/Subdir.mk 2004-05-30 20:23:41.000000000 +0200
+@@ -6,6 +6,7 @@ OBJS-libng := \
+ libng/color_packed.o \
+ libng/color_lut.o \
+ libng/color_yuv2rgb.o \
++ libng/color_bayer2rgb.o \
+ libng/convert.o
+
+ libng/libng.a: $(OBJS-libng)
+diff -uprN xawtv-3.92/libng/videodev2.h xawtv-3.92-devel/libng/videodev2.h
+--- xawtv-3.92/libng/videodev2.h 2003-02-14 15:14:07.000000000 +0100
++++ xawtv-3.92-devel/libng/videodev2.h 2004-05-30 22:18:01.000000000 +0200
+@@ -177,6 +177,7 @@ struct v4l2_pix_format
+ #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */
+ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */
+ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */
++#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG..GRGR.. */
+ #define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */
+ #define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */
+ #define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */
+
diff --git a/libng/contrib-plugins/linear-blend.c b/libng/contrib-plugins/linear-blend.c
index 7b5ee36..2c18540 100644
--- a/libng/contrib-plugins/linear-blend.c
+++ b/libng/contrib-plugins/linear-blend.c
@@ -42,7 +42,7 @@ static inline void linearBlend(unsigned char *src, int stride)
#ifdef MMX
asm volatile(
"leal (%0, %1), %%eax \n\t"
- "leal (%%eax, %1, 4), %%ebx \n\t"
+ "leal (%%eax, %1, 4), %%edx \n\t"
"movq (%0), %%mm0 \n\t" // L0
"movq (%%eax, %1), %%mm1 \n\t" // L2
@@ -58,29 +58,29 @@ static inline void linearBlend(unsigned char *src, int stride)
PAVGB(%%mm2, %%mm1) // L2+L4
PAVGB(%%mm0, %%mm1) // 2L3 + L2 + L4
"movq %%mm1, (%%eax, %1) \n\t"
- "movq (%%ebx), %%mm1 \n\t" // L5
+ "movq (%%edx), %%mm1 \n\t" // L5
PAVGB(%%mm1, %%mm0) // L3+L5
PAVGB(%%mm2, %%mm0) // 2L4 + L3 + L5
"movq %%mm0, (%%eax, %1, 2) \n\t"
- "movq (%%ebx, %1), %%mm0 \n\t" // L6
+ "movq (%%edx, %1), %%mm0 \n\t" // L6
PAVGB(%%mm0, %%mm2) // L4+L6
PAVGB(%%mm1, %%mm2) // 2L5 + L4 + L6
"movq %%mm2, (%0, %1, 4) \n\t"
- "movq (%%ebx, %1, 2), %%mm2 \n\t" // L7
+ "movq (%%edx, %1, 2), %%mm2 \n\t" // L7
PAVGB(%%mm2, %%mm1) // L5+L7
PAVGB(%%mm0, %%mm1) // 2L6 + L5 + L7
- "movq %%mm1, (%%ebx) \n\t"
+ "movq %%mm1, (%%edx) \n\t"
"movq (%0, %1, 8), %%mm1 \n\t" // L8
PAVGB(%%mm1, %%mm0) // L6+L8
PAVGB(%%mm2, %%mm0) // 2L7 + L6 + L8
- "movq %%mm0, (%%ebx, %1) \n\t"
- "movq (%%ebx, %1, 4), %%mm0 \n\t" // L9
+ "movq %%mm0, (%%edx, %1) \n\t"
+ "movq (%%edx, %1, 4), %%mm0 \n\t" // L9
PAVGB(%%mm0, %%mm2) // L7+L9
PAVGB(%%mm1, %%mm2) // 2L8 + L7 + L9
- "movq %%mm2, (%%ebx, %1, 2) \n\t"
+ "movq %%mm2, (%%edx, %1, 2) \n\t"
: : "r" (src), "r" (stride)
- : "%eax", "%ebx"
+ : "%eax", "%edx"
);
emms();
#else
diff --git a/x11/blit.c b/x11/blit.c
index 56434f7..6368613 100644
--- a/x11/blit.c
+++ b/x11/blit.c
@@ -42,6 +42,7 @@ static unsigned int display_bytes = 0;
static unsigned int pixmap_bytes = 0;
static bool x11_byteswap = 0;
static int no_mitshm = 0;
+static int gl_error = 0;
#if HAVE_LIBXV
static int ver, rel, req, ev, err;
@@ -89,6 +90,14 @@ catch_no_mitshm(Display * dpy, XErrorEvent * event)
return 0;
}
+static int
+catch_gl_error(Display * dpy, XErrorEvent * event)
+{
+ fprintf(stderr,"WARNING: Your OpenGL setup is broken.\n");
+ gl_error++;
+ return 0;
+}
+
/* ------------------------------------------------------------------------ */
/* plain X11 stuff */
@@ -365,11 +374,9 @@ void xv_image_init(Display *dpy)
return;
fo = XvListImageFormats(dpy, im_port, &formats);
- if (debug)
- fprintf(stderr," image format list for port %d\n",im_port);
for(i = 0; i < formats; i++) {
if (debug)
- fprintf(stderr, " 0x%x (%c%c%c%c) %s",
+ fprintf(stderr, "blit: xv: 0x%x (%c%c%c%c) %s",
fo[i].id,
(fo[i].id) & 0xff,
(fo[i].id >> 8) & 0xff,
@@ -519,6 +526,7 @@ struct {
static int gl_init(Widget widget)
{
+ void *old_handler;
XVisualInfo *visinfo;
GLXContext ctx;
@@ -533,15 +541,26 @@ static int gl_init(Widget widget)
return -1;
}
ctx = glXCreateContext(XtDisplay(widget), visinfo, NULL, True);
- glXMakeCurrent(XtDisplay(widget),XtWindow(widget),ctx);
- if (debug)
- fprintf(stderr, "blit: gl: DRI=%s\n",
- glXIsDirect(XtDisplay(widget), ctx) ? "Yes" : "No");
+ if (!ctx) {
+ if (debug)
+ fprintf(stderr,"blit: gl: can't create context\n");
+ return -1;
+ }
/* there is no point in using OpenGL for image scaling if it
* isn't hardware accelerated ... */
+ if (debug)
+ fprintf(stderr, "blit: gl: DRI=%s\n",
+ glXIsDirect(XtDisplay(widget), ctx) ? "Yes" : "No");
if (!glXIsDirect(XtDisplay(widget), ctx))
return -1;
+
+ old_handler = XSetErrorHandler(catch_gl_error);
+ glXMakeCurrent(XtDisplay(widget),XtWindow(widget),ctx);
+ XSync(XtDisplay(widget), False);
+ XSetErrorHandler(old_handler);
+ if (gl_error)
+ return -1;
have_gl = 1;
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_gl);
diff --git a/x11/blit.c.orig b/x11/blit.c.orig
new file mode 100644
index 0000000..56434f7
--- /dev/null
+++ b/x11/blit.c.orig
@@ -0,0 +1,949 @@
+/*
+ * x11 helper functions -- blit frames to the screen
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <errno.h>
+#include <assert.h>
+#include <pthread.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/extensions/XShm.h>
+#ifdef HAVE_LIBXV
+# include <X11/extensions/Xv.h>
+# include <X11/extensions/Xvlib.h>
+#endif
+
+#if HAVE_GL
+# include <GL/gl.h>
+# include <GL/glx.h>
+#endif
+
+#include "grab-ng.h"
+#include "blit.h"
+
+/* ------------------------------------------------------------------------ */
+
+extern XtAppContext app_context;
+extern int debug;
+
+unsigned int x11_dpy_fmtid;
+
+static int display_bits = 0;
+static unsigned int display_bytes = 0;
+static unsigned int pixmap_bytes = 0;
+static bool x11_byteswap = 0;
+static int no_mitshm = 0;
+
+#if HAVE_LIBXV
+static int ver, rel, req, ev, err;
+static int formats;
+static int adaptors;
+static XvImageFormatValues *fo;
+static XvAdaptorInfo *ai;
+#endif
+
+static unsigned int im_adaptor,im_port = UNSET;
+static unsigned int im_formats[VIDEO_FMT_COUNT];
+
+static struct SEARCHFORMAT {
+ unsigned int depth;
+ int order;
+ unsigned long red;
+ unsigned long green;
+ unsigned long blue;
+ unsigned int format;
+} fmt[] = {
+ { 2, MSBFirst, 0x7c00, 0x03e0, 0x001f, VIDEO_RGB15_BE },
+ { 2, MSBFirst, 0xf800, 0x07e0, 0x001f, VIDEO_RGB16_BE },
+ { 2, LSBFirst, 0x7c00, 0x03e0, 0x001f, VIDEO_RGB15_LE },
+ { 2, LSBFirst, 0xf800, 0x07e0, 0x001f, VIDEO_RGB16_LE },
+
+ { 3, LSBFirst, 0x00ff0000, 0x0000ff00, 0x000000ff, VIDEO_BGR24 },
+ { 3, LSBFirst, 0x000000ff, 0x0000ff00, 0x00ff0000, VIDEO_RGB24 },
+ { 3, MSBFirst, 0x00ff0000, 0x0000ff00, 0x000000ff, VIDEO_RGB24 },
+ { 3, MSBFirst, 0x000000ff, 0x0000ff00, 0x00ff0000, VIDEO_BGR24 },
+
+ { 4, LSBFirst, 0x00ff0000, 0x0000ff00, 0x000000ff, VIDEO_BGR32 },
+ { 4, LSBFirst, 0x0000ff00, 0x00ff0000, 0xff000000, VIDEO_RGB32 },
+ { 4, MSBFirst, 0x00ff0000, 0x0000ff00, 0x000000ff, VIDEO_RGB32 },
+ { 4, MSBFirst, 0x0000ff00, 0x00ff0000, 0xff000000, VIDEO_BGR32 },
+
+ { 2, -1, 0, 0, 0, VIDEO_LUT2 },
+ { 4, -1, 0, 0, 0, VIDEO_LUT4 },
+ { 0 /* END OF LIST */ },
+};
+
+static int
+catch_no_mitshm(Display * dpy, XErrorEvent * event)
+{
+ no_mitshm++;
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+/* plain X11 stuff */
+
+Visual*
+x11_find_visual(Display *dpy)
+{
+ XVisualInfo *info, template;
+ Visual* vi = CopyFromParent;
+ int found,i;
+ char *class;
+
+ template.screen = XDefaultScreen(dpy);
+ info = XGetVisualInfo(dpy, VisualScreenMask,&template,&found);
+ for (i = 0; i < found; i++) {
+ switch (info[i].class) {
+ case StaticGray: class = "StaticGray"; break;
+ case GrayScale: class = "GrayScale"; break;
+ case StaticColor: class = "StaticColor"; break;
+ case PseudoColor: class = "PseudoColor"; break;
+ case TrueColor: class = "TrueColor"; break;
+ case DirectColor: class = "DirectColor"; break;
+ default: class = "UNKNOWN"; break;
+ }
+ if (debug)
+ fprintf(stderr,"visual: id=0x%lx class=%d (%s), depth=%d\n",
+ info[i].visualid,info[i].class,class,info[i].depth);
+ }
+ for (i = 0; vi == CopyFromParent && i < found; i++)
+ if (info[i].class == TrueColor && info[i].depth >= 15)
+ vi = info[i].visual;
+ for (i = 0; vi == CopyFromParent && i < found; i++)
+ if (info[i].class == StaticGray && info[i].depth == 8)
+ vi = info[i].visual;
+ return vi;
+}
+
+void
+x11_init_visual(Display *dpy, XVisualInfo *vinfo)
+{
+ XPixmapFormatValues *pf;
+ int i,n;
+ int format = 0;
+
+ if (!XShmQueryExtension(dpy))
+ no_mitshm = 1;
+
+ display_bits = vinfo->depth;
+ display_bytes = (display_bits+7)/8;
+
+ pf = XListPixmapFormats(dpy,&n);
+ for (i = 0; i < n; i++)
+ if (pf[i].depth == display_bits)
+ pixmap_bytes = pf[i].bits_per_pixel/8;
+
+ if (debug) {
+ fprintf(stderr,"x11: color depth: "
+ "%d bits, %d bytes - pixmap: %d bytes\n",
+ display_bits,display_bytes,pixmap_bytes);
+ if (vinfo->class == TrueColor || vinfo->class == DirectColor)
+ fprintf(stderr, "x11: color masks: "
+ "red=0x%08lx green=0x%08lx blue=0x%08lx\n",
+ vinfo->red_mask, vinfo->green_mask, vinfo->blue_mask);
+ fprintf(stderr,"x11: server byte order: %s\n",
+ ImageByteOrder(dpy)==LSBFirst ? "little endian":"big endian");
+ fprintf(stderr,"x11: client byte order: %s\n",
+ BYTE_ORDER==LITTLE_ENDIAN ? "little endian":"big endian");
+ }
+ if (ImageByteOrder(dpy)==LSBFirst && BYTE_ORDER!=LITTLE_ENDIAN)
+ x11_byteswap=1;
+ if (ImageByteOrder(dpy)==MSBFirst && BYTE_ORDER!=BIG_ENDIAN)
+ x11_byteswap=1;
+ if (vinfo->class == TrueColor /* || vinfo->class == DirectColor */) {
+ /* pixmap format */
+ for (i = 0; fmt[i].depth > 0; i++) {
+ if (fmt[i].depth == pixmap_bytes &&
+ (fmt[i].order == ImageByteOrder(dpy) || fmt[i].order == -1) &&
+ (fmt[i].red == vinfo->red_mask || fmt[i].red == 0) &&
+ (fmt[i].green == vinfo->green_mask || fmt[i].green == 0) &&
+ (fmt[i].blue == vinfo->blue_mask || fmt[i].blue == 0)) {
+ x11_dpy_fmtid = fmt[i].format;
+ break;
+ }
+ }
+ if (fmt[i].depth == 0) {
+ fprintf(stderr, "Huh?\n");
+ exit(1);
+ }
+ ng_lut_init(vinfo->red_mask, vinfo->green_mask, vinfo->blue_mask,
+ x11_dpy_fmtid,x11_byteswap);
+ /* guess physical screen format */
+ if (ImageByteOrder(dpy) == MSBFirst) {
+ switch (pixmap_bytes) {
+ case 2: format = (display_bits==15) ?
+ VIDEO_RGB15_BE : VIDEO_RGB16_BE; break;
+ case 3: format = VIDEO_RGB24; break;
+ case 4: format = VIDEO_RGB32; break;
+ }
+ } else {
+ switch (pixmap_bytes) {
+ case 2: format = (display_bits==15) ?
+ VIDEO_RGB15_LE : VIDEO_RGB16_LE; break;
+ case 3: format = VIDEO_BGR24; break;
+ case 4: format = VIDEO_BGR32; break;
+ }
+ }
+ }
+ if (vinfo->class == StaticGray && vinfo->depth == 8) {
+ format = VIDEO_GRAY;
+ }
+ if (0 == format) {
+ if (vinfo->class == PseudoColor && vinfo->depth == 8) {
+ fprintf(stderr,
+"\n"
+"8-bit Pseudocolor Visual (256 colors) is *not* supported.\n"
+"You can startup X11 either with 15 bpp (or more)...\n"
+" xinit -- -bpp 16\n"
+"... or with StaticGray visual:\n"
+" xinit -- -cc StaticGray\n"
+ );
+ } else {
+ fprintf(stderr, "Sorry, I can't handle your strange display\n");
+ }
+ exit(1);
+ }
+ x11_dpy_fmtid = format;
+}
+
+XImage*
+x11_create_ximage(Display *dpy, XVisualInfo *vinfo,
+ int width, int height, XShmSegmentInfo **shm)
+{
+ XImage *ximage = NULL;
+ unsigned char *ximage_data;
+ XShmSegmentInfo *shminfo = NULL;
+ void *old_handler;
+
+ if (no_mitshm)
+ goto no_mitshm;
+
+ assert(width > 0 && height > 0);
+
+ old_handler = XSetErrorHandler(catch_no_mitshm);
+ shminfo = malloc(sizeof(XShmSegmentInfo));
+ memset(shminfo, 0, sizeof(XShmSegmentInfo));
+ ximage = XShmCreateImage(dpy,vinfo->visual,vinfo->depth,
+ ZPixmap, NULL,
+ shminfo, width, height);
+ if (NULL == ximage)
+ goto shm_error;
+ shminfo->shmid = shmget(IPC_PRIVATE,
+ ximage->bytes_per_line * ximage->height,
+ IPC_CREAT | 0777);
+ if (-1 == shminfo->shmid) {
+ perror("shmget [x11]");
+ goto shm_error;
+ }
+ shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
+ if ((void *)-1 == shminfo->shmaddr) {
+ perror("shmat");
+ goto shm_error;
+ }
+ ximage->data = shminfo->shmaddr;
+ shminfo->readOnly = False;
+
+ XShmAttach(dpy, shminfo);
+ XSync(dpy, False);
+ if (no_mitshm)
+ goto shm_error;
+ shmctl(shminfo->shmid, IPC_RMID, 0);
+ XSetErrorHandler(old_handler);
+ *shm = shminfo;
+ return ximage;
+
+ shm_error:
+ if (ximage) {
+ XDestroyImage(ximage);
+ ximage = NULL;
+ }
+ if ((void *)-1 != shminfo->shmaddr && NULL != shminfo->shmaddr)
+ shmdt(shminfo->shmaddr);
+ free(shminfo);
+ XSetErrorHandler(old_handler);
+ no_mitshm = 1;
+
+ no_mitshm:
+ *shm = NULL;
+ if (NULL == (ximage_data = malloc(width * height * pixmap_bytes))) {
+ fprintf(stderr,"out of memory\n");
+ exit(1);
+ }
+ ximage = XCreateImage(dpy, vinfo->visual, vinfo->depth,
+ ZPixmap, 0, ximage_data,
+ width, height,
+ 8, 0);
+ memset(ximage->data, 0, ximage->bytes_per_line * ximage->height);
+ return ximage;
+}
+
+void
+x11_destroy_ximage(Display *dpy, XImage *ximage, XShmSegmentInfo *shm)
+{
+ if (shm && !no_mitshm) {
+ XShmDetach(dpy, shm);
+ XDestroyImage(ximage);
+ shmdt(shm->shmaddr);
+ free(shm);
+ } else
+ XDestroyImage(ximage);
+}
+
+void x11_blit(Display *dpy, Drawable dr, GC gc, XImage *xi,
+ int a, int b, int c, int d, int w, int h)
+{
+ if (no_mitshm)
+ XPutImage(dpy,dr,gc,xi,a,b,c,d,w,h);
+ else
+ XShmPutImage(dpy,dr,gc,xi,a,b,c,d,w,h,True);
+}
+
+Pixmap
+x11_create_pixmap(Display *dpy, XVisualInfo *vinfo, struct ng_video_buf *buf)
+{
+ Pixmap pixmap;
+ XImage *ximage;
+ GC gc;
+ XShmSegmentInfo *shm;
+ Screen *scr = DefaultScreenOfDisplay(dpy);
+
+ pixmap = XCreatePixmap(dpy,RootWindowOfScreen(scr),
+ buf->fmt.width, buf->fmt.height, vinfo->depth);
+
+ gc = XCreateGC(dpy, pixmap, 0, NULL);
+
+ if (NULL == (ximage = x11_create_ximage(dpy, vinfo, buf->fmt.width,
+ buf->fmt.height, &shm))) {
+ XFreePixmap(dpy, pixmap);
+ XFreeGC(dpy, gc);
+ return 0;
+ }
+ memcpy(ximage->data,buf->data,buf->size);
+ x11_blit(dpy, pixmap, gc, ximage, 0, 0, 0, 0,
+ buf->fmt.width, buf->fmt.height);
+ x11_destroy_ximage(dpy, ximage, shm);
+ XFreeGC(dpy, gc);
+ return pixmap;
+}
+
+/* ------------------------------------------------------------------------ */
+/* XVideo extention code */
+
+#ifdef HAVE_LIBXV
+void xv_image_init(Display *dpy)
+{
+ int i;
+
+ if (Success != XvQueryExtension(dpy,&ver,&rel,&req,&ev,&err)) {
+ if (debug)
+ fprintf(stderr,"Xvideo: Server has no Xvideo extention support\n");
+ return;
+ }
+ if (Success != XvQueryAdaptors(dpy,DefaultRootWindow(dpy),&adaptors,&ai)) {
+ fprintf(stderr,"Xvideo: XvQueryAdaptors failed");
+ return;
+ }
+ for (i = 0; i < adaptors; i++) {
+ if ((ai[i].type & XvInputMask) &&
+ (ai[i].type & XvImageMask) &&
+ (im_port == UNSET)) {
+ im_port = ai[i].base_id;
+ im_adaptor = i;
+ }
+ }
+ if (UNSET == im_port)
+ return;
+
+ fo = XvListImageFormats(dpy, im_port, &formats);
+ if (debug)
+ fprintf(stderr," image format list for port %d\n",im_port);
+ for(i = 0; i < formats; i++) {
+ if (debug)
+ fprintf(stderr, " 0x%x (%c%c%c%c) %s",
+ fo[i].id,
+ (fo[i].id) & 0xff,
+ (fo[i].id >> 8) & 0xff,
+ (fo[i].id >> 16) & 0xff,
+ (fo[i].id >> 24) & 0xff,
+ (fo[i].format == XvPacked) ? "packed" : "planar");
+ if (0x32595559 == fo[i].id) {
+ im_formats[VIDEO_YUYV] = fo[i].id;
+ if (debug)
+ fprintf(stderr," [ok: %s]",ng_vfmt_to_desc[VIDEO_YUYV]);
+ }
+ if (0x59565955 == fo[i].id) {
+ im_formats[VIDEO_UYVY] = fo[i].id;
+ if (debug)
+ fprintf(stderr," [ok: %s]",ng_vfmt_to_desc[VIDEO_UYVY]);
+ }
+ if (0x30323449 == fo[i].id) {
+ im_formats[VIDEO_YUV420P] = fo[i].id;
+ if (debug)
+ fprintf(stderr," [ok: %s]",ng_vfmt_to_desc[VIDEO_YUV420P]);
+ }
+ if (debug)
+ fprintf(stderr,"\n");
+ }
+}
+
+XvImage*
+xv_create_ximage(Display *dpy, int width, int height, int format,
+ XShmSegmentInfo **shm)
+{
+ XvImage *xvimage = NULL;
+ unsigned char *ximage_data;
+ XShmSegmentInfo *shminfo = NULL;
+ void *old_handler;
+
+ if (no_mitshm)
+ goto no_mitshm;
+
+ old_handler = XSetErrorHandler(catch_no_mitshm);
+ shminfo = malloc(sizeof(XShmSegmentInfo));
+ memset(shminfo, 0, sizeof(XShmSegmentInfo));
+ xvimage = XvShmCreateImage(dpy, im_port, format, 0,
+ width, height, shminfo);
+ if (NULL == xvimage)
+ goto shm_error;
+ shminfo->shmid = shmget(IPC_PRIVATE, xvimage->data_size,
+ IPC_CREAT | 0777);
+ if (-1 == shminfo->shmid) {
+ perror("shmget [xv]");
+ goto shm_error;
+ }
+ shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
+ if ((void *)-1 == shminfo->shmaddr) {
+ perror("shmat");
+ goto shm_error;
+ }
+ xvimage->data = shminfo->shmaddr;
+ shminfo->readOnly = False;
+
+ XShmAttach(dpy, shminfo);
+ XSync(dpy, False);
+ if (no_mitshm)
+ goto shm_error;
+ shmctl(shminfo->shmid, IPC_RMID, 0);
+ XSetErrorHandler(old_handler);
+ *shm = shminfo;
+ return xvimage;
+
+shm_error:
+ if (xvimage) {
+ XFree(xvimage);
+ xvimage = NULL;
+ }
+ if ((void *)-1 != shminfo->shmaddr && NULL != shminfo->shmaddr)
+ shmdt(shminfo->shmaddr);
+ free(shminfo);
+ XSetErrorHandler(old_handler);
+ no_mitshm = 1;
+
+ no_mitshm:
+ *shm = NULL;
+ if (NULL == (ximage_data = malloc(width * height * 2))) {
+ fprintf(stderr,"out of memory\n");
+ exit(1);
+ }
+ xvimage = XvCreateImage(dpy, im_port, format, ximage_data,
+ width, height);
+ return xvimage;
+}
+
+void
+xv_destroy_ximage(Display *dpy, XvImage * xvimage, XShmSegmentInfo *shm)
+{
+ if (shm && !no_mitshm) {
+ XShmDetach(dpy, shm);
+ XFree(xvimage);
+ shmdt(shm->shmaddr);
+ free(shm);
+ } else
+ XFree(xvimage);
+}
+
+void xv_blit(Display *dpy, Drawable dr, GC gc, XvImage *xi,
+ int a, int b, int c, int d, int x, int y, int w, int h)
+{
+ if (no_mitshm)
+ XvPutImage(dpy,im_port,dr,gc,xi,a,b,c,d,x,y,w,h);
+ else
+ XvShmPutImage(dpy,im_port,dr,gc,xi,a,b,c,d,x,y,w,h,True);
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+/* OpenGL code */
+
+#if HAVE_GL
+static int have_gl,max_gl;
+static int gl_attrib[] = { GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None };
+
+struct {
+ int fmt;
+ int type;
+ char *ext;
+} gl_formats[VIDEO_FMT_COUNT] = {
+ [ VIDEO_RGB24 ] = {
+ fmt: GL_RGB,
+ type: GL_UNSIGNED_BYTE,
+ },
+#ifdef GL_EXT_bgra
+ [ VIDEO_BGR24 ] = {
+ fmt: GL_BGR_EXT,
+ type: GL_UNSIGNED_BYTE,
+ ext: "GL_EXT_bgra",
+ },
+ [ VIDEO_BGR32 ] = {
+ fmt: GL_BGRA_EXT,
+ type: GL_UNSIGNED_BYTE,
+ ext: "GL_EXT_bgra",
+ },
+#endif
+};
+
+static int gl_init(Widget widget)
+{
+ XVisualInfo *visinfo;
+ GLXContext ctx;
+
+ if (debug)
+ fprintf(stderr,"blit: gl: init\n");
+ visinfo = glXChooseVisual(XtDisplay(widget),
+ XScreenNumberOfScreen(XtScreen(widget)),
+ gl_attrib);
+ if (!visinfo) {
+ if (debug)
+ fprintf(stderr,"blit: gl: can't get visual (rgb,db)\n");
+ return -1;
+ }
+ ctx = glXCreateContext(XtDisplay(widget), visinfo, NULL, True);
+ glXMakeCurrent(XtDisplay(widget),XtWindow(widget),ctx);
+ if (debug)
+ fprintf(stderr, "blit: gl: DRI=%s\n",
+ glXIsDirect(XtDisplay(widget), ctx) ? "Yes" : "No");
+
+ /* there is no point in using OpenGL for image scaling if it
+ * isn't hardware accelerated ... */
+ if (!glXIsDirect(XtDisplay(widget), ctx))
+ return -1;
+
+ have_gl = 1;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_gl);
+ if (debug)
+ fprintf(stderr,"blit: gl: texture max size: %d\n",max_gl);
+ return 0;
+}
+
+static int gl_ext(GLubyte *find)
+{
+ int len = strlen(find);
+ const GLubyte *ext;
+ GLubyte *pos;
+
+ ext = glGetString(GL_EXTENSIONS);
+ if (NULL == ext)
+ return 0;
+ if (NULL == (pos = strstr(ext,find)))
+ return 0;
+ if (pos != ext && pos[-1] != ' ')
+ return 0;
+ if (pos[len] != ' ' && pos[len] != '\0')
+ return 0;
+ if (debug)
+ fprintf(stderr,"blit: gl: extention %s is available\n",find);
+ return 1;
+}
+
+static int gl_resize(int iw, int ih, int ww, int wh,
+ GLint *tex, int *tw, int *th, int fmt, int type)
+{
+ char *dummy;
+ int i;
+
+ /* check against max size */
+ if (iw > max_gl)
+ return -1;
+ if (ih > max_gl)
+ return -1;
+
+ /* textures have power-of-two x,y dimensions */
+ for (i = 0; iw >= (1 << i); i++)
+ ;
+ *tw = (1 << i);
+ for (i = 0; ih >= (1 << i); i++)
+ ;
+ *th = (1 << i);
+ if (debug)
+ fprintf(stderr,"blit: gl: frame=%dx%d, texture=%dx%d\n",
+ iw,ih,*tw,*th);
+
+ glClearColor (0.0, 0.0, 0.0, 0.0);
+ glShadeModel(GL_FLAT);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glViewport(0, 0, ww, wh);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, ww, 0.0, wh, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glGenTextures(1,tex);
+ glBindTexture(GL_TEXTURE_2D,*tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ dummy = malloc((*tw)*(*th)*3);
+ memset(dummy,128,(*tw)*(*th)*3);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,*tw,*th,0,
+ fmt,type,dummy);
+ free(dummy);
+
+ return 0;
+}
+
+static void gl_cleanup(GLint tex)
+{
+ /* FIXME: del texture */
+}
+
+static void gl_blit(Widget widget, char *rgbbuf,
+ int iw, int ih, int ww, int wh,
+ GLint tex, int tw, int th, int fmt, int type)
+{
+ float x,y;
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0,iw,ih, fmt,type,rgbbuf);
+ x = (float)iw/tw;
+ y = (float)ih/th;
+
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,y); glVertex3f(0,0,0);
+ glTexCoord2f(0,0); glVertex3f(0,wh,0);
+ glTexCoord2f(x,0); glVertex3f(ww,wh,0);
+ glTexCoord2f(x,y); glVertex3f(ww,0,0);
+ glEnd();
+ glXSwapBuffers(XtDisplay(widget), XtWindow(widget));
+ glDisable(GL_TEXTURE_2D);
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+/* video frame blitter */
+
+enum blit_status {
+ STATUS_UNKNOWN = 0,
+ STATUS_BROKEN = 1,
+ STATUS_CONVERT = 2,
+ STATUS_XVIDEO = 3,
+ STATUS_OPENGL = 4,
+};
+
+struct blit_state {
+ enum blit_status status;
+ Widget widget;
+ Dimension win_width, win_height;
+ int wx,wy,ww,wh;
+ GC gc;
+ XVisualInfo *vinfo;
+ struct ng_video_fmt fmt;
+ struct ng_video_buf buf;
+ struct ng_video_conv *conv;
+ struct ng_convert_handle *chandle;
+ XShmSegmentInfo *shm;
+ XImage *ximage;
+#ifdef HAVE_LIBXV
+ XvImage *xvimage;
+#endif
+#if HAVE_GL
+ GLint tex;
+ int tw,th;
+#endif
+};
+
+struct blit_state*
+blit_init(Widget widget, XVisualInfo *vinfo, int use_gl)
+{
+ struct blit_state *st;
+
+ if (debug)
+ fprintf(stderr,"blit: init\n");
+ BUG_ON(0 == XtWindow(widget), "no blit window");
+
+ st = malloc(sizeof(*st));
+ memset(st,0,sizeof(*st));
+
+ st->widget = widget;
+ st->vinfo = vinfo;
+ st->gc = XCreateGC(XtDisplay(st->widget),XtWindow(st->widget),0,NULL);
+#ifdef HAVE_GL
+ if (use_gl)
+ gl_init(st->widget);
+#endif
+
+ return st;
+}
+
+void blit_get_formats(struct blit_state *st, int *fmtids, int max)
+{
+ struct ng_video_conv *conv;
+ int i, n=0;
+
+ BUG_ON(NULL == st, "blit handle is NULL");
+
+ /* Xvideo extention */
+#ifdef HAVE_LIBXV
+ for (i = 0; i < VIDEO_FMT_COUNT; i++) {
+ if (0 != im_formats[i])
+ fmtids[n++] = i;
+ if (n == max)
+ return;
+ }
+#endif
+
+#if HAVE_GL
+ /* OpenGL */
+ if (have_gl) {
+ for (i = 0; i < VIDEO_FMT_COUNT; i++) {
+ if (0 != gl_formats[i].fmt &&
+ (NULL == gl_formats[i].ext || gl_ext(gl_formats[i].ext)))
+ fmtids[n++] = i;
+ if (n == max)
+ return;
+ }
+ }
+#endif
+
+ /* plain X11 */
+ fmtids[n++] = x11_dpy_fmtid;
+ if (n == max)
+ return;
+ for (i = 0;;) {
+ conv = ng_conv_find_to(x11_dpy_fmtid, &i);
+ if (NULL == conv)
+ break;
+ fmtids[n++] = conv->fmtid_in;
+ if (n == max)
+ return;
+ }
+ for (; n < max; n++)
+ fmtids[n] = 0;
+}
+
+void blit_resize(struct blit_state *st, Dimension width, Dimension height)
+{
+ if (debug)
+ fprintf(stderr,"blit: resize %dx%d\n",width,height);
+ st->win_width = width;
+ st->win_height = height;
+
+ st->wx = 0;
+ st->wy = 0;
+ st->ww = st->win_width;
+ st->wh = st->win_height;
+ ng_ratio_fixup(&st->ww, &st->wh, &st->wx, &st->wy);
+
+ blit_fini_frame(st);
+}
+
+void blit_init_frame(struct blit_state *st, struct ng_video_fmt *fmt)
+{
+ struct ng_video_conv *conv;
+ int i;
+
+ /* Xvideo extention */
+#ifdef HAVE_LIBXV
+ if (0 != im_formats[fmt->fmtid]) {
+ st->xvimage = xv_create_ximage(XtDisplay(st->widget),
+ fmt->width, fmt->height,
+ im_formats[fmt->fmtid],
+ &st->shm);
+ st->buf.fmt = *fmt;
+ st->status = STATUS_XVIDEO;
+ if (debug)
+ fprintf(stderr,"blit: %dx%d/[%s] => Xvideo\n",
+ fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid]);
+ return;
+ }
+#endif
+
+#if HAVE_GL
+ /* OpenGL */
+ if (have_gl && 0 != gl_formats[fmt->fmtid].fmt &&
+ (NULL == gl_formats[fmt->fmtid].ext ||
+ gl_ext(gl_formats[fmt->fmtid].ext)) &&
+ 0 == gl_resize(fmt->width,fmt->height,
+ st->win_width,st->win_height,
+ &st->tex,&st->tw,&st->th,
+ gl_formats[fmt->fmtid].fmt,
+ gl_formats[fmt->fmtid].type)) {
+ st->buf.fmt = *fmt;
+ st->status = STATUS_OPENGL;
+ if (debug)
+ fprintf(stderr,"blit: %dx%d/[%s] => OpenGL\n",
+ fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid]);
+ return;
+ }
+#endif
+
+ /* plain X11 */
+ st->ximage = x11_create_ximage(XtDisplay(st->widget), st->vinfo,
+ fmt->width, fmt->height,
+ &st->shm);
+ st->buf.data = st->ximage->data;
+ if (x11_dpy_fmtid == fmt->fmtid) {
+ st->buf.fmt = *fmt;
+ st->status = STATUS_CONVERT;
+ if (debug)
+ fprintf(stderr,"blit: %dx%d/[%s] => X11 direct\n",
+ fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid]);
+ return;
+ }
+ for (i = 0;;) {
+ conv = ng_conv_find_to(x11_dpy_fmtid, &i);
+ if (NULL == conv) {
+ st->status = STATUS_BROKEN;
+ if (debug)
+ fprintf(stderr,"blit: %dx%d/[%s] => can't display\n",
+ fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid]);
+ return;
+ }
+ if (debug)
+ fprintf(stderr,"blit test: %s\n",ng_vfmt_to_desc[conv->fmtid_in]);
+ if (conv->fmtid_in != fmt->fmtid)
+ continue;
+ break;
+ }
+ st->buf.fmt = *fmt;
+ st->status = STATUS_CONVERT;
+ st->conv = conv;
+ st->buf.fmt.fmtid = x11_dpy_fmtid;
+ st->buf.fmt.bytesperline = 0;
+ st->chandle = ng_convert_alloc(st->conv,fmt,&st->buf.fmt);
+ ng_convert_init(st->chandle);
+ if (debug)
+ fprintf(stderr,"blit: %dx%d/[%s] => X11 via [%s]\n",
+ fmt->width, fmt->height, ng_vfmt_to_desc[fmt->fmtid],
+ ng_vfmt_to_desc[st->buf.fmt.fmtid]);
+ return;
+}
+
+void blit_fini_frame(struct blit_state *st)
+{
+ switch (st->status) {
+ case STATUS_CONVERT:
+ if (st->chandle) {
+ ng_convert_fini(st->chandle);
+ st->chandle = NULL;
+ }
+ if (st->ximage) {
+ x11_destroy_ximage(XtDisplay(st->widget),st->ximage,st->shm);
+ st->ximage = NULL;
+ }
+ break;
+
+#if HAVE_LIBXV
+ case STATUS_XVIDEO:
+ if (st->xvimage) {
+ xv_destroy_ximage(XtDisplay(st->widget),st->xvimage,st->shm);
+ st->xvimage = NULL;
+ }
+ XvStopVideo(XtDisplay(st->widget), im_port, XtWindow(st->widget));
+ break;
+#endif
+
+#if HAVE_GL
+ case STATUS_OPENGL:
+ gl_cleanup(st->tex);
+ break;
+#endif
+
+ case STATUS_UNKNOWN:
+ case STATUS_BROKEN:
+ break;
+ }
+ memset(&st->fmt,0,sizeof(st->fmt));
+ memset(&st->buf,0,sizeof(st->buf));
+ st->status = STATUS_UNKNOWN;
+}
+
+void blit_fini(struct blit_state *st)
+{
+ free(st);
+}
+
+void blit_putframe(struct blit_state *st, struct ng_video_buf *buf)
+{
+ if (st->fmt.fmtid != buf->fmt.fmtid &&
+ st->fmt.width != buf->fmt.width &&
+ st->fmt.height != buf->fmt.height) {
+ blit_fini_frame(st);
+ blit_init_frame(st,&buf->fmt);
+ st->fmt = buf->fmt;
+ }
+
+ if (debug > 1)
+ fprintf(stderr,"blit: putframe\n");
+ switch (st->status) {
+ case STATUS_CONVERT:
+ if (NULL == st->chandle) {
+ memcpy(st->ximage->data,buf->data,buf->size);
+ ng_release_video_buf(buf);
+ } else {
+ buf = ng_convert_frame(st->chandle,&st->buf,buf);
+ }
+ x11_blit(XtDisplay(st->widget), XtWindow(st->widget),
+ st->gc,st->ximage,0,0,
+ (st->win_width - st->buf.fmt.width) >> 1,
+ (st->win_height - st->buf.fmt.height) >> 1,
+ st->buf.fmt.width, st->buf.fmt.height);
+ break;
+
+#ifdef HAVE_LIBXV
+ case STATUS_XVIDEO:
+ memcpy(st->xvimage->data,buf->data,buf->size);
+ ng_release_video_buf(buf);
+ xv_blit(XtDisplay(st->widget), XtWindow(st->widget),
+ st->gc, st->xvimage,
+ 0, 0, st->buf.fmt.width, st->buf.fmt.height,
+ st->wx, st->wy, st->ww, st->wh);
+ break;
+#endif
+
+#if HAVE_GL
+ case STATUS_OPENGL:
+ gl_blit(st->widget,buf->data,
+ st->buf.fmt.width, st->buf.fmt.height,
+ st->win_width, st->win_height,
+ st->tex, st->tw, st->th,
+ gl_formats[buf->fmt.fmtid].fmt,
+ gl_formats[buf->fmt.fmtid].type);
+ ng_release_video_buf(buf);
+ break;
+#endif
+
+ case STATUS_UNKNOWN:
+ case STATUS_BROKEN:
+ if (debug > 1)
+ fprintf(stderr,"blit: putframe: oops: status = %d\n",st->status);
+ ng_release_video_buf(buf);
+ break;
+ }
+}
diff --git a/x11/blit.c.rej b/x11/blit.c.rej
new file mode 100644
index 0000000..7eb6e90
--- /dev/null
+++ b/x11/blit.c.rej
@@ -0,0 +1,37 @@
+*************** static int gl_init(Widget widget)
+*** 538,551 ****
+ fprintf(stderr,"blit: gl: can't create context\n");
+ return -1;
+ }
+- glXMakeCurrent(XtDisplay(widget),XtWindow(widget),ctx);
+- if (debug)
+- fprintf(stderr, "blit: gl: DRI=%s\n",
+- glXIsDirect(XtDisplay(widget), ctx) ? "Yes" : "No");
+
+ /* there is no point in using OpenGL for image scaling if it
+ * isn't hardware accelerated ... */
+ if (!glXIsDirect(XtDisplay(widget), ctx))
+ return -1;
+
+ have_gl = 1;
+--- 546,565 ----
+ fprintf(stderr,"blit: gl: can't create context\n");
+ return -1;
+ }
+
+ /* there is no point in using OpenGL for image scaling if it
+ * isn't hardware accelerated ... */
++ if (debug)
++ fprintf(stderr, "blit: gl: DRI=%s\n",
++ glXIsDirect(XtDisplay(widget), ctx) ? "Yes" : "No");
+ if (!glXIsDirect(XtDisplay(widget), ctx))
++ return -1;
++
++ old_handler = XSetErrorHandler(catch_gl_error);
++ glXMakeCurrent(XtDisplay(widget),XtWindow(widget),ctx);
++ XSync(XtDisplay(widget), False);
++ XSetErrorHandler(old_handler);
++ if (gl_error)
+ return -1;
+
+ have_gl = 1;
diff --git a/xawtv.spec b/xawtv.spec
index e20b1a4..2c0393d 100644
--- a/xawtv.spec
+++ b/xawtv.spec
@@ -1,7 +1,7 @@
Name: xawtv
Group: Applications/Multimedia
Autoreqprov: on
-Version: 3.92
+Version: 3.93
Release: 0
License: GPL
Summary: v4l applications

Privacy Policy