summaryrefslogtreecommitdiffstats
path: root/sys/glsink/gstgl_nvimage.c
diff options
context:
space:
mode:
authorGernot Ziegler <gz@lysator.liu.se>2003-10-27 18:34:48 +0000
committerGernot Ziegler <gz@lysator.liu.se>2003-10-27 18:34:48 +0000
commit537084d264c4bb5fc9d02504d7e79961fd8e83c7 (patch)
tree96be4d2e4328649022e919f155ff90d3c0c128c3 /sys/glsink/gstgl_nvimage.c
parentbf156442acd3af570fae1bfe4cd1641ca704e09b (diff)
downloadgst-plugins-bad-537084d264c4bb5fc9d02504d7e79961fd8e83c7.tar.gz
gst-plugins-bad-537084d264c4bb5fc9d02504d7e79961fd8e83c7.tar.bz2
gst-plugins-bad-537084d264c4bb5fc9d02504d7e79961fd8e83c7.zip
introducing NVidia accelerated OpenGL videosinks :)
Original commit message from CVS: introducing NVidia accelerated OpenGL videosinks :)
Diffstat (limited to 'sys/glsink/gstgl_nvimage.c')
-rw-r--r--sys/glsink/gstgl_nvimage.c256
1 files changed, 134 insertions, 122 deletions
diff --git a/sys/glsink/gstgl_nvimage.c b/sys/glsink/gstgl_nvimage.c
index faa5224c..61d18749 100644
--- a/sys/glsink/gstgl_nvimage.c
+++ b/sys/glsink/gstgl_nvimage.c
@@ -13,19 +13,18 @@
#include <stdlib.h>
#include <sys/types.h>
-#define GL_GLEXT_PROTOTYPES
-
-// VERY dangerous:
-#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/glx.h>
#include <GL/gl.h>
-#include <GL/glext.h>
+//#include <GL/glext.h>
#include <GL/glu.h>
#include <string.h>
+// too lazy to write an API for this ;)
+#include "regcomb_yuvrgb.c"
+
#include "gstglsink.h"
typedef struct _GstGLImageConnection GstGLImageConnection;
@@ -102,8 +101,12 @@ gst_gl_nvimage_connection (GstImageConnection *conn)
gboolean
gst_gl_nvimage_check_xvideo ()
{
- int ver, rel, req, ev, err;
+ //int ver, rel, req, ev, err;
+ if (!GL_ARB_multitexture_Init()) return FALSE;
+ if (!GL_EXT_paletted_texture_Init()) return FALSE;
+ if (!GL_NV_register_combiners_Init()) return FALSE;
+
#if 0
if (display == NULL)
return FALSE;
@@ -111,15 +114,15 @@ gst_gl_nvimage_check_xvideo ()
return TRUE;
#endif
- return FALSE;
+ return TRUE;
}
static GstCaps *
gst_gl_nvimage_get_caps (GstImageInfo *info)
{
- gint i;
- int adaptors;
- int formats;
+ //gint i;
+ //int adaptors;
+ //int formats;
GstCaps *caps = NULL;
GstGLImageInfo *xinfo = gst_gl_nvimage_info (info);
@@ -128,14 +131,14 @@ gst_gl_nvimage_get_caps (GstImageInfo *info)
if (gst_gl_nvimage_check_xvideo () == FALSE)
{
- g_warning("GL_NVImage: Server has no NVidia extension support\n");
+ g_warning("GL_NVImage: Server has no NVidia extension support\n");
return NULL;
}
caps = gst_caps_append (caps, GST_CAPS_NEW (
"xvimage_caps",
"video/raw",
- "format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y', 'C', '1', '2')),
+ "format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y', 'V', '1', '2')),
"width", GST_PROPS_INT_RANGE (0, 1024),
"height", GST_PROPS_INT_RANGE (0, 1024))
);
@@ -145,9 +148,9 @@ gst_gl_nvimage_get_caps (GstImageInfo *info)
static GstImageConnection *
gst_gl_nvimage_set_caps (GstImageInfo *info, GstCaps *caps)
{
- gint i, j = 0;
- int adaptors;
- int formats;
+ //gint i, j = 0;
+ //int adaptors;
+ //int formats;
GstGLImageConnection *conn;
GstGLImageInfo *xinfo = gst_gl_nvimage_info (info);
guint32 format;
@@ -166,6 +169,12 @@ gst_gl_nvimage_set_caps (GstImageInfo *info, GstCaps *caps)
"format", &format,
NULL);
+ // maybe I should a bit more checking here, e.g. maximum size smaller than maximum texture extents
+ if (format != GST_MAKE_FOURCC ('Y', 'V', '1', '2'))
+ {
+ GST_DEBUG (GST_CAT_PLUGIN_INFO, "GL_NVImage: Format is invalid !\n");
+ return NULL;
+ }
if (0) //conn->port == (XvPortID) -1)
{
/* this happens if the plugin can't handle the caps, so no warning */
@@ -173,6 +182,7 @@ gst_gl_nvimage_set_caps (GstImageInfo *info, GstCaps *caps)
return NULL;
}
+ GST_DEBUG (GST_CAT_PLUGIN_INFO, "GL_NVImage: caps %p are ok, creating image", caps);
return (GstImageConnection *) conn;
}
@@ -182,35 +192,22 @@ gst_gl_nvimage_get_image (GstImageInfo *info, GstImageConnection *conn)
GstNvImage *image;
GstGLImageInfo *xinfo = gst_gl_nvimage_info (info);
GstGLImageConnection *nvconn = gst_gl_nvimage_connection (conn);
- int slot = 0;
/* checks */
if (xinfo == NULL) return NULL;
if (nvconn == NULL) return NULL;
- // I should also check the current GLX context ! Don't have to, I am guarantueed to always be in the same thread
+ // I should also check the current GLX context !
+ // Ah, Don't have to, I am guarantueed to always be in the same thread
image = g_new0(GstNvImage, 1);
- for (slot = 0; slot < AGP_BUFSLOTS; slot++)
- {
- if (!nvconn->m_bufslots[slot]) break;
- }
-
image->data.size = nvconn->w * nvconn->h * 3/2;
- if (slot < AGP_BUFSLOTS) // found an AGP buffer slot
- {
- image->data.data = nvconn->m_memory + slot * YUVTEX_SIZE;
- image->slot = slot; // store for freeing
- nvconn->m_bufslots[slot] = 1; // it is now taken
- }
- else
- {
- g_warning("Allocating from main memory !");
- image->data.data = g_malloc(image->data.size);
- image->slot = AGP_BUFSLOTS; // no AGP slot
- }
+ //g_warning("Allocating %d bytes from main memory !", image->data.size);
+ image->data.data = g_malloc(image->data.size);
+ //image->slot = AGP_BUFSLOTS; // no AGP slot
+
image->conn = nvconn;
if (image->data.data == NULL)
@@ -229,52 +226,125 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image)
GstNvImage *im = (GstNvImage *) image;
GstGLImageInfo *xinfo = gst_gl_nvimage_info (info);
+ int img_width = im->conn->w;
+ int img_height = im->conn->h;
+ int uv_width = img_width >> 1;
+ int uv_height = img_height >> 1;
+
+ unsigned char *buf_y = im->data.data;
+ unsigned char *buf_v = (buf_y + img_width * img_height);
+ unsigned char *buf_u = buf_v + ((img_width/2) * (img_height/2));
+
/* checks omitted for speed (and lazyness), do we need them? */
g_assert (xinfo != NULL);
- /* Upload the texture here */
- g_warning("PUTTING IMAGE - BROOOKEN");
-
// both upload the video, and redraw the screen
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -50.0);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
//glTranslatef(0,1,0);
- glRotatef(xinfo->rotX-250,1,0,0);
+ glRotatef(xinfo->rotX,1,0,0);
glRotatef(xinfo->rotY,0,1,0);
- int zoom = xinfo->zoom;
- glScaled(zoom,zoom,zoom);
- //Draws the surface rectangle
- glBindTexture(GL_TEXTURE_2D, im->conn->ytex_id);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, im->conn->w, im->conn->h, GL_RGBA,
- GL_UNSIGNED_BYTE, im->data.data);
- float xmax = (float)im->conn->w/TEX_XSIZE;
- float ymax = (float)im->conn->h/TEX_YSIZE;
+ if (xinfo->info.demo)
+ {
+ //xinfo->rotX += 0.2;
+ //xinfo->rotY -= 0.2;
+ float zoom = xinfo->zoom;
+ glScalef(zoom,zoom,zoom);
+
+ if (xinfo->zoom > 2.0)
+ xinfo->zoomdir = -0.05;
+
+ if (xinfo->zoom < 1.0)
+ xinfo->zoomdir = 0.05;
- glColor4f(1,1,1,1);
- glBegin(GL_QUADS);
+ xinfo->zoom += xinfo->zoomdir;
+ }
- glNormal3f(0, -1, 0);
-
- glTexCoord2f(xmax, 0);
- glVertex3f(4,0,-4);
+ //Draws the surface rectangle
+
+ if (Ywidth != im->conn->w || Yheight != im->conn->h)
+ {
+ Ywidth = im->conn->w; Yheight = im->conn->h; UVwidth = im->conn->w/2; UVheight = im->conn->h/2;
+ Initialize_Backend(Ywidth,Yheight,UVwidth,UVheight,GL_LINEAR);
+ }
- glTexCoord2f(0, 0);
- glVertex3f(-4,0,-4);
+ LoadYUVPlanes(Yhandle,Uhandle,Vhandle,img_width,img_height,uv_width,uv_height,buf_y,buf_u,buf_v);
+ float xmax = (float)(im->conn->w-1)/tex_xsize;
+ float ymax = (float)(im->conn->h-1)/tex_ysize;
- glTexCoord2f(0, ymax);
- glVertex3f(-4,0,4);
+ /* Upload the texture here */
+ //g_warning("PUTTING IMAGE %f %f %d %d\n", xmax, ymax, tex_xsize, tex_ysize);
- glTexCoord2f(xmax, ymax);
- glVertex3f(4,0,4);
+ //glColor4f(1,1,1,1); // do NOT set a color here ! Done by Initialize_Backend, or actually SetConst !
+ glBegin(GL_QUADS);
+
+ glNormal3f(0, -1, 0);
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0,0);
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,0);
+ glMultiTexCoord2fARB(GL_TEXTURE2_ARB,0,0);
+ glVertex3f(-4,4,0);
+
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0,ymax);
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,ymax);
+ glMultiTexCoord2fARB(GL_TEXTURE2_ARB,0,ymax);
+ glVertex3f(-4,-4,0);
+
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB,xmax,ymax);
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB,xmax,ymax);
+ glMultiTexCoord2fARB(GL_TEXTURE2_ARB,xmax,ymax);
+ glVertex3f(4,-4,0);
+
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB,xmax,0);
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB,xmax,0);
+ glMultiTexCoord2fARB(GL_TEXTURE2_ARB,xmax,0);
+ glVertex3f(4,4,0);
glEnd();
glPopMatrix();
+ if (xinfo->info.dumpvideo)
+ {
+ static int framenr = 0;
+ char capfilename[255];
+ static guint8 *cap_image_data = NULL, *cap_image_data2 = NULL;
+ int i;
+
+ // hmmmm, is this reentrant ?!
+ if (cap_image_data == NULL)
+ cap_image_data = (guint8 *)malloc(img_width * img_height * 3);
+
+ if (cap_image_data2 == NULL)
+ cap_image_data2 = (guint8 *)malloc(img_width * img_height * 3);
+
+ printf("Recording frame #%d\n", framenr);
+ glReadPixels(0,0,img_width,img_height,GL_RGB,GL_UNSIGNED_BYTE,cap_image_data);
+ // invert the pixels
+ for (i = 0; i < img_height; i++)
+ memcpy(cap_image_data2 + i * img_width * 3, cap_image_data + (img_height-1-i) * img_width * 3, img_width*3);
+
+ sprintf(capfilename, "cap%04d.ppm", framenr);
+ FILE *outfile = fopen(capfilename, "wb");
+ if (outfile != NULL)
+ {
+ fprintf(outfile, "P6\n");
+ fprintf(outfile,"# created by raw_zb\n");
+ fprintf(outfile,"%d %d\n",img_width,img_height);
+ fprintf(outfile,"255\n");
+ fwrite(cap_image_data2, sizeof(char), img_width*img_height*3, outfile);
+ fclose(outfile);
+ }
+ framenr++;
+ }
+
+
glXSwapBuffers(xinfo->dpy, xinfo->win);
}
@@ -301,76 +371,18 @@ gst_gl_nvimage_open_conn (GstImageConnection *conn, GstImageInfo *info)
GstGLImageInfo *xinfo = gst_gl_nvimage_info (info);
GstGLImageConnection *xconn = gst_gl_nvimage_connection (conn);
- unsigned char data_sep[2][2] = {{0, 255}, {0, 255}};
- int slot;
-
- g_warning("Opening NVidia Connection");
- xconn->m_memory = (unsigned char*)glXAllocateMemoryNV(AGP_BUFSLOTS*YUVTEX_SIZE, 0, 1.0, 1.0);
-
- if (!xconn->m_memory)
- {
- printf("Unable to acquire graphics card mem... will acquire in normal memory.\n");
- for (slot = 0; slot < AGP_BUFSLOTS; slot++)
- xconn->m_bufslots[slot] = 1;
- }
- else
- {
- // maybe this fast writable memory, awfully slow to read from, though
- glPixelDataRangeNV(GL_WRITE_PIXEL_DATA_RANGE_NV, AGP_BUFSLOTS*YUVTEX_SIZE, xconn->m_memory);
- glEnableClientState(GL_WRITE_PIXEL_DATA_RANGE_NV);
-
- for (slot = 0; slot < AGP_BUFSLOTS; slot++)
- xconn->m_bufslots[slot] = 0;
- }
-
- glGenTextures(1, &xconn->ytex_id);
- glBindTexture(GL_TEXTURE_2D, xconn->ytex_id);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8_ALPHA8, TEX_XSIZE, TEX_YSIZE, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
-
- glActiveTextureARB(GL_TEXTURE1_ARB);
- glGenTextures(1, &xconn->uvtex_id);
- glBindTexture(GL_TEXTURE_2D, xconn->uvtex_id);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8_ALPHA8, TEX_XSIZE/2, TEX_YSIZE/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
-
- glActiveTextureARB(GL_TEXTURE2_ARB);
- glGenTextures(1, &xconn->septex_id);
- glBindTexture(GL_TEXTURE_2D, xconn->septex_id);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data_sep);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
-
- glFlushPixelDataRangeNV(GL_WRITE_PIXEL_DATA_RANGE_NV);
- //glEnable(GL_TEXTURE_2D);
- glActiveTextureARB(GL_TEXTURE0_ARB);
- glEnable(GL_TEXTURE_2D);
- glActiveTextureARB(GL_TEXTURE1_ARB);
- glEnable(GL_TEXTURE_2D);
- glActiveTextureARB(GL_TEXTURE2_ARB);
- glEnable(GL_TEXTURE_2D);
- glActiveTextureARB(GL_TEXTURE0_ARB);
+ g_warning("Opening NVidia GL context connection, using register combiners.\n");
+ {
+ Ywidth = TEX_XSIZE; Yheight = TEX_YSIZE; UVwidth = TEX_XSIZE/2; UVheight = TEX_YSIZE/2;
+ Initialize_Backend(Ywidth,Yheight,UVwidth,UVheight,GL_LINEAR);
+ }
}
static void
gst_gl_nvimage_close_conn (GstImageConnection *conn, GstImageInfo *info)
{
GstGLImageConnection *xconn = gst_gl_nvimage_connection (conn);
- GstGLImageInfo *xinfo = gst_gl_nvimage_info (info);
+ //GstGLImageInfo *xinfo = gst_gl_nvimage_info (info);
// anything needed in here ? Oh, maybe drawing de-init, or something
glDeleteTextures(1, &xconn->ytex_id);