From 537084d264c4bb5fc9d02504d7e79961fd8e83c7 Mon Sep 17 00:00:00 2001 From: Gernot Ziegler Date: Mon, 27 Oct 2003 18:34:48 +0000 Subject: introducing NVidia accelerated OpenGL videosinks :) Original commit message from CVS: introducing NVidia accelerated OpenGL videosinks :) --- sys/glsink/gstgl_nvimage.c | 256 ++++++++++++++++++++++++--------------------- 1 file changed, 134 insertions(+), 122 deletions(-) (limited to 'sys/glsink/gstgl_nvimage.c') 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 #include -#define GL_GLEXT_PROTOTYPES - -// VERY dangerous: -#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 #include #include #include #include -#include +//#include #include #include +// 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); -- cgit v1.2.1