#define DISP // this can be 3 or 4 (regarding 24bpp and 32bpp) #define BYTES_PP 3 #define TEXTUREFORMAT_32BPP // Hmm. Enabling this makes about 20% speedup too! (Celeron2+G400+UtahGLX) //#define TEXSUBIMAGE_BUG_WORKAROUND /* * video_out_gl.c, X11/OpenGL interface * based on video_out_x11 by Aaron Holtzman, * and WS opengl window manager by Pontscho/Fresh! */ #include #include #include #include #include "config.h" #include "video_out.h" #include "video_out_internal.h" LIBVO_EXTERN(gl) #include #include //#include #include #include #include "yuv2rgb.h" #include static vo_info_t vo_info = { "X11 (OpenGL)", "gl", "Arpad Gereoffy ", "" }; /* private prototypes */ static void Display_Image (unsigned char *ImageData); /* local data */ static unsigned char *ImageData=NULL; /* X11 related variables */ static Display *mydisplay; static Window mywindow; //static GC mygc; //static XImage *myximage; //static int depth,mode; static XWindowAttributes attribs; static int X_already_started = 0; static int texture_id=1; static GLXContext wsGLXContext; //XVisualInfo * wsVisualInfo; int wsGLXAttrib[] = { GLX_RGBA, GLX_RED_SIZE,1, GLX_GREEN_SIZE,1, GLX_BLUE_SIZE,1, // GLX_DEPTH_SIZE,16, GLX_DOUBLEBUFFER, None }; static uint32_t image_width; static uint32_t image_height; static uint32_t image_format; static uint32_t image_bpp; static uint32_t image_bytes; static uint32_t texture_width; static uint32_t texture_height; static resize(int x,int y){ printf("Resize: %dx%d\n",x,y); glViewport( 0, 0, x, y ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, image_width, image_height, 0, -1,1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* connect to server, create and map window, * allocate colors and (shared) memory */ static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) { int screen; unsigned int fg, bg; char *hello = (title == NULL) ? "OpenGL rulez" : title; char *name = ":0.0"; XSizeHints hint; XVisualInfo *vinfo; XEvent xev; XGCValues xgcv; XSetWindowAttributes xswa; unsigned long xswamask; image_height = height; image_width = width; image_format = format; if (X_already_started) return -1; if(getenv("DISPLAY")) name = getenv("DISPLAY"); mydisplay = XOpenDisplay(name); if (mydisplay == NULL) { fprintf(stderr,"Can not open display\n"); return -1; } screen = DefaultScreen(mydisplay); hint.x = 0; hint.y = 0; hint.width = d_width; hint.height = d_height; hint.flags = PPosition | PSize; /* Get some colors */ bg = WhitePixel(mydisplay, screen); fg = BlackPixel(mydisplay, screen); /* Make the window */ XGetWindowAttributes(mydisplay, DefaultRootWindow(mydisplay), &attribs); #if 0 /* * * depth in X11 terminology land is the number of bits used to * actually represent the colour. * * bpp in X11 land means how many bits in the frame buffer per * pixel. * * ex. 15 bit color is 15 bit depth and 16 bpp. Also 24 bit * color is 24 bit depth, but can be 24 bpp or 32 bpp. */ depth = attribs.depth; if (depth != 15 && depth != 16 && depth != 24 && depth != 32) { /* The root window may be 8bit but there might still be * visuals with other bit depths. For example this is the * case on Sun/Solaris machines. */ depth = 24; } //BEGIN HACK //mywindow = XCreateSimpleWindow(mydisplay, DefaultRootWindow(mydisplay), //hint.x, hint.y, hint.width, hint.height, 4, fg, bg); // #endif // XMatchVisualInfo(mydisplay, screen, depth, TrueColor, &vinfo); vinfo=glXChooseVisual( mydisplay,screen,wsGLXAttrib ); xswa.background_pixel = 0; xswa.border_pixel = 1; // xswa.colormap = XCreateColormap(mydisplay, RootWindow(mydisplay,screen), vinfo.visual, AllocNone); xswa.colormap = XCreateColormap(mydisplay, RootWindow(mydisplay,screen), vinfo->visual, AllocNone); xswamask = CWBackPixel | CWBorderPixel | CWColormap; // xswamask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWCursor | CWOverrideRedirect | CWSaveUnder | CWX | CWY | CWWidth | CWHeight; mywindow = XCreateWindow(mydisplay, RootWindow(mydisplay,screen), hint.x, hint.y, hint.width, hint.height, 4, vinfo->depth,CopyFromParent,vinfo->visual,xswamask,&xswa); wsGLXContext=glXCreateContext( mydisplay,vinfo,NULL,True ); // XStoreName( wsDisplay,wsMyWin,wsSysName ); printf("GLXcontect ok\n"); XSelectInput(mydisplay, mywindow, StructureNotifyMask); /* Tell other applications about this window */ XSetStandardProperties(mydisplay, mywindow, hello, hello, None, NULL, 0, &hint); /* Map window. */ XMapWindow(mydisplay, mywindow); /* Wait for map. */ do { XNextEvent(mydisplay, &xev); } while (xev.type != MapNotify || xev.xmap.event != mywindow); XSelectInput(mydisplay, mywindow, NoEventMask); glXMakeCurrent( mydisplay,mywindow,wsGLXContext ); XFlush(mydisplay); XSync(mydisplay, False); // mygc = XCreateGC(mydisplay, mywindow, 0L, &xgcv); // myximage = XGetImage(mydisplay, mywindow, 0, 0, // width, image_height, AllPlanes, ZPixmap); // ImageData = myximage->data; // bpp = myximage->bits_per_pixel; XSelectInput(mydisplay, mywindow, StructureNotifyMask); // !!!! printf("Window setup ok\n"); #if 0 // If we have blue in the lowest bit then obviously RGB mode = ((myximage->blue_mask & 0x01) != 0) ? MODE_RGB : MODE_BGR; #ifdef WORDS_BIGENDIAN if (myximage->byte_order != MSBFirst) #else if (myximage->byte_order != LSBFirst) #endif { fprintf( stderr, "No support fon non-native XImage byte order!\n" ); return -1; } printf("DEPTH=%d BPP=%d\n",depth,bpp); #endif /* * If depth is 24 then it may either be a 3 or 4 byte per pixel * format. We can't use bpp because then we would lose the * distinction between 15/16bit depth (2 byte formate assumed). * * FIXME - change yuv2rgb_init to take both depth and bpp * parameters */ texture_width=32; while(texture_width256)texture_width=256; // voodoo3 hack texture_height=texture_width; if(format==IMGFMT_YV12){ yuv2rgb_init(8*BYTES_PP, MODE_RGB); printf("YUV init OK!\n"); image_bpp=8*BYTES_PP; image_bytes=BYTES_PP; } else { image_bpp=format&0xFF; image_bytes=(image_bpp+7)/8; } ImageData=malloc(texture_width*texture_height*image_bytes); memset(ImageData,128,texture_width*texture_height*image_bytes); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glDisable(GL_CULL_FACE); printf("Creating %dx%d texture...\n",texture_width,texture_height); #if 1 // glBindTexture(GL_TEXTURE_2D, texture_id); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifdef TEXTUREFORMAT_32BPP glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture_width, texture_height, 0, #else glTexImage2D(GL_TEXTURE_2D, 0, BYTES_PP, texture_width, texture_height, 0, #endif (image_bytes==4)?GL_RGBA:GL_BGR, GL_UNSIGNED_BYTE, ImageData); #endif resize(d_width,d_height); glClearColor( 1.0f,1.0f,1.0f,0.0f ); glClear( GL_COLOR_BUFFER_BIT ); printf("OpenGL setup OK!\n"); X_already_started++; return 0; } static const vo_info_t* get_info(void) { return &vo_info; } static void Terminate_Display_Process(void) { getchar(); /* wait for enter to remove window */ XDestroyWindow(mydisplay, mywindow); XCloseDisplay(mydisplay); X_already_started = 0; } static void FlipImage() { // XPutImage(mydisplay, mywindow, mygc, myximage, 0, 0, 0, 0, myximage->width, myximage->height); // XFlush(mydisplay); int i; XEvent wsEvent; XEvent xev; while ( XPending( mydisplay ) ) { XNextEvent( mydisplay,&wsEvent ); switch( wsEvent.type ) { // case Expose: if ( wsReDraw ) wsReDraw( wsDisplay,wsEvent.xany.window ); break; case ConfigureNotify: //wsWindowWidth=wsEvent.xconfigure.width; //wsWindowHeight=wsEvent.xconfigure.height; #if 0 XUnmapWindow( mydisplay,mywindow ); XMapWindow( mydisplay,mywindow ); /* Wait for map. */ do { XNextEvent(mydisplay, &xev);} while (xev.type != MapNotify || xev.xmap.event != mywindow); #endif resize( wsEvent.xconfigure.width, wsEvent.xconfigure.height ); break; } } glEnable(GL_TEXTURE_2D); // glBindTexture(GL_TEXTURE_2D, texture_id); glColor3f(1,1,1); glBegin(GL_QUADS); glTexCoord2f(0,0);glVertex2i(0,0); glTexCoord2f(0,1);glVertex2i(0,texture_height); glTexCoord2f(1,1);glVertex2i(texture_width,texture_height); glTexCoord2f(1,0);glVertex2i(texture_width,0); glEnd(); // glFlush(); glFinish(); glXSwapBuffers( mydisplay,mywindow ); } static inline void flip_page_x11(void) { // Display_Image(myximage, ImageData); // Display_Image(ImageData); FlipImage(); } static void flip_page(void) { return flip_page_x11(); } static inline uint32_t draw_slice_x11(uint8_t *src[], uint32_t slice_num) { uint8_t *dst; int i; dst = ImageData;// + image_width * 16 * BYTES_PP * slice_num; yuv2rgb(dst , src[0], src[1], src[2], image_width, 16, image_width*BYTES_PP, image_width, image_width/2 ); // emms (); #ifdef TEXSUBIMAGE_BUG_WORKAROUND for(i=0;i<16;i++){ glTexSubImage2D( GL_TEXTURE_2D, // target 0, // level 0, // x offset 16*slice_num+i, // y offset image_width, // width 1, // height (BYTES_PP==4)?GL_RGBA:GL_RGB, // format GL_UNSIGNED_BYTE, // type ImageData+i*BYTES_PP*image_width ); // *pixels } #else //printf("uploading slice \n"); glTexSubImage2D( GL_TEXTURE_2D, // target 0, // level 0, // x offset 16*slice_num, // y offset image_width, // width 16, // height (BYTES_PP==4)?GL_RGBA:GL_RGB, // format GL_UNSIGNED_BYTE, // type ImageData ); // *pixels #endif return 0; } static uint32_t draw_slice(uint8_t *src[], uint32_t slice_num) { return draw_slice_x11(src,slice_num); } #define MIN(a,b) (((a)<(b))?(a):(b)) static inline uint32_t draw_frame_x11_yv12(uint8_t *src[]) { int i; // printf("Converting YUV->RGB...\n"); yuv2rgb(ImageData, src[0], src[1], src[2], image_width, image_height, image_width*BYTES_PP, image_width, image_width/2 ); // printf("Ready!\n"); // emms (); // for(i=0;i