Mercurial > mplayer.hg
view libvo/vo_directfb.c @ 7401:8b90281ed8aa
- fixed some bugs in RLE decoder
- some cleanup, home i didn't break it...
author | arpi |
---|---|
date | Sun, 15 Sep 2002 13:29:00 +0000 |
parents | eca7dbad0166 |
children | 5b39e79af5fe |
line wrap: on
line source
/* MPlayer video driver for DirectFramebuffer device (C) 2001 Written by Jiri Svoboda <Jiri.Svoboda@seznam.cz> Inspired by vo_sdl and vo_fbdev. To get second head working delete line 120 from fbdev.c (from DirectFB sources version 0.9.7) Line contains following: fbdev->fd = open( "/dev/fb0", O_RDWR ); Parts of this code taken from DirectFB examples: (c) Copyright 2000 convergence integrated media GmbH. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // directfb includes #include <directfb.h> // other things #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <ctype.h> #include <assert.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <sys/kd.h> #include <linux/fb.h> #include "config.h" #include "video_out.h" #include "video_out_internal.h" #include "fastmemcpy.h" #include "sub.h" #include "../postproc/rgb2rgb.h" #include "aspect.h" #ifndef min #define min(x,y) (((x)<(y))?(x):(y)) #endif LIBVO_EXTERN(directfb) static vo_info_t vo_info = { "Direct Framebuffer Device", "directfb", "Jiri Svoboda Jiri.Svoboda@seznam.cz", "" }; extern int verbose; /****************************** * directfb * ******************************/ /* * (Globals) */ static IDirectFB *dfb = NULL; static IDirectFBSurface *primary = NULL; static IDirectFBInputDevice *keyboard = NULL; static IDirectFBDisplayLayer *videolayer = NULL; static DFBDisplayLayerConfig dlc; static unsigned int screen_width = 0; static unsigned int screen_height = 0; static DFBSurfacePixelFormat frame_format; static unsigned int frame_pixel_size = 0; static unsigned int source_pixel_size = 0; static int xoffset=0,yoffset=0; #define DFBCHECK(x...) \ { \ DFBResult err = x; \ \ if (err != DFB_OK) \ { \ fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ DirectFBErrorFatal( #x, err ); \ } \ } /* * The frame is to be loaded into a surface that we can blit from. */ static IDirectFBSurface *frame = NULL; /* * A buffer for input events. */ #if DIRECTFBVERSION > 908 static IDirectFBEventBuffer *buffer = NULL; #else static IDirectFBInputBuffer *buffer = NULL; #endif /****************************** * vo_directfb * ******************************/ /* command line/config file options */ #ifdef HAVE_FBDEV extern char *fb_dev_name; #else char *fb_dev_name; #endif static void (*draw_alpha_p)(int w, int h, unsigned char *src, unsigned char *srca, int stride, unsigned char *dst, int dstride); static uint32_t in_width; static uint32_t in_height; static uint32_t out_width=1; static uint32_t out_height=1; static uint32_t pixel_format; static int fs; static int flip; static int stretch=0; struct modes_t { int valid; unsigned int width; unsigned int height; int overx,overy; } modes [4]; static unsigned int best_bpp=5; // videolayer stuff static int videolayeractive=0; static int videolayerpresent=0; //some info about videolayer - filled on preinit struct vlayer_t { int iv12; int i420; int yuy2; int uyvy; int brightness; int saturation; int contrast; int hue; int hwscale; } videolayercaps; // workabout for DirectFB bug static int buggyYV12BitBlt=0; static int memcpyBitBlt=0; // static int hwstretchblit=0; #define DIRECTRENDER #ifdef DIRECTRENDER static int dr_enabled=0; static int framelocked=0; #endif #define FLIPPING #ifdef FLIPPING static int do_flipping=1; // turn (on) off flipping - prepared for cmd line switch static int wait_vsync_after_flip=0; static int flipping=0; // flipping is active static int invram=0; // backbuffer in video memory static int blitperformed=0; // in case of temporary frame we will blit before drawing osd #endif // primary & frame stuff static int frameallocated=0; static int primaryallocated=0; DFBEnumerationResult enum_modes_callback( unsigned int width,unsigned int height,unsigned int bpp, void *data) { int overx=0,overy=0,closer=0,over=0; unsigned int index=bpp/8-1; int we_are_under=0; if (verbose) printf("DirectFB: Validator entered %i %i %i\n",width,height,bpp); overx=width-out_width; overy=height-out_height; if (!modes[index].valid) { modes[index].valid=1; modes[index].width=width; modes[index].height=height; modes[index].overx=overx; modes[index].overy=overy; if (verbose) printf("DirectFB: Mode added %i %i %i\n",width,height,bpp); } if ((modes[index].overy<0)||(modes[index].overx<0)) we_are_under=1; // stored mode is smaller than req mode if (abs(overx*overy)<abs(modes[index].overx * modes[index].overy)) closer=1; // current mode is closer to desired res if ((overx>=0)&&(overy>=0)) over=1; // current mode is bigger or equaul to desired res if ((closer && (over || we_are_under)) || (we_are_under && over)) { modes[index].valid=1; modes[index].width=width; modes[index].height=height; modes[index].overx=overx; modes[index].overy=overy; if (verbose) printf("DirectFB: Better mode added %i %i %i\n",width,height,bpp); }; return DFENUM_OK; } #if DIRECTFBVERSION > 912 DFBEnumerationResult enum_layers_callback( DFBDisplayLayerID id, DFBDisplayLayerDescription desc, void *data ) { DFBDisplayLayerCapabilities caps = desc.caps; #else DFBEnumerationResult enum_layers_callback( unsigned int id, DFBDisplayLayerCapabilities caps, void *data ) { #endif IDirectFBDisplayLayer **layer = (IDirectFBDisplayLayer **)data; if (verbose) { printf("\nDirectFB: Layer %d:\n", id ); if (caps & DLCAPS_SURFACE) printf( " - Has a surface.\n" ); if (caps & DLCAPS_ALPHACHANNEL) printf( " - Supports blending based on alpha channel.\n" ); #if DIRECTFBVERSION > 909 if (caps & DLCAPS_SRC_COLORKEY) printf( " - Supports source based color keying.\n" ); if (caps & DLCAPS_DST_COLORKEY) printf( " - Supports destination based color keying.\n" ); #else if (caps & DLCAPS_COLORKEYING) printf( " - Supports color keying.\n" ); #endif if (caps & DLCAPS_FLICKER_FILTERING) printf( " - Supports flicker filtering.\n" ); /* renamed in dfb v. 0.9.13 if (caps & DLCAPS_INTERLACED_VIDEO) printf( " - Can natively display interlaced video.\n" ); */ if (caps & DLCAPS_OPACITY) printf( " - Supports blending based on global alpha factor.\n" ); if (caps & DLCAPS_SCREEN_LOCATION) printf( " - Can be positioned on the screen.\n" ); if (caps & DLCAPS_BRIGHTNESS) printf( " - Brightness can be adjusted.\n" ); if (caps & DLCAPS_CONTRAST) printf( " - Contrast can be adjusted.\n" ); if (caps & DLCAPS_HUE) printf( " - Hue can be adjusted.\n" ); if (caps & DLCAPS_SATURATION) printf( " - Saturation can be adjusted.\n" ); printf("\n"); } /* We take the first layer not being the primary */ if (id != DLID_PRIMARY) { DFBResult ret; ret = dfb->GetDisplayLayer( dfb, id, layer ); if (ret) DirectFBError( "dfb->GetDisplayLayer failed", ret ); else return DFENUM_CANCEL; } return DFENUM_OK; } static uint32_t preinit(const char *arg) { DFBSurfaceDescription dsc; DFBResult ret; DFBDisplayLayerConfigFlags failed; /* * (Initialize) */ if (verbose) printf("DirectFB: Preinit entered\n"); DFBCHECK (DirectFBInit (NULL,NULL)); if (!((directfb_major_version <= 0) && (directfb_minor_version <= 9) && (directfb_micro_version < 7))) { if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER"))) fb_dev_name = "/dev/fb0"; DFBCHECK (DirectFBSetOption ("fbdev",fb_dev_name)); } // use own bitblt for YV12 beacuse bug in dfb till 0.9.11 if ((directfb_major_version <= 0) && (directfb_minor_version <= 9) && (directfb_micro_version <= 11)) { buggyYV12BitBlt=1; if (verbose) printf("DirectFB: Buggy YV12BitBlt!\n"); } #ifdef FLIPPING // activate flipping from release 0.9.11 if ((directfb_major_version <= 0) && (directfb_minor_version <= 9) && (directfb_micro_version <= 10)) { do_flipping=0; } else { // (de)activated by default - should be overwritten by cmd line option // do_flipping=1; } // wait for vsync if ver <0.9.13 if ((directfb_major_version <= 0) && (directfb_minor_version <= 9) && (directfb_micro_version <= 12)) { wait_vsync_after_flip=1; if (verbose) printf("DirectFB: Manual wait for vsync enabled!\n"); } else { wait_vsync_after_flip=0; } #endif // uncomment this if you do not wish to create a new vt for DirectFB // DFBCHECK (DirectFBSetOption ("no-vt-switch","")); // uncomment this if you want to allow vt switching // DFBCHECK (DirectFBSetOption ("vt-switching","")); #if DIRECTFBVERSION > 908 // uncomment this if you want to hide gfx cursor (req dfb >=0.9.9) DFBCHECK (DirectFBSetOption ("no-cursor","")); #endif DFBCHECK (DirectFBSetOption ("bg-color","00000000")); DFBCHECK (DirectFBCreate (&dfb)); DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN)); // lets try to get YUY2 layer - borrowed from DirectFb examples /* Enumerate display layers */ DFBCHECK (dfb->EnumDisplayLayers( dfb, enum_layers_callback, &videolayer )); if (!videolayer) { if (verbose) printf("DirectFB: No videolayer found\n"); // no videolayer found // printf( "\nNo additional layers have been found.\n" ); videolayeractive=0; } else { // just to be sure that layer is hidden during config videolayer->SetOpacity(videolayer,0); // there is an additional layer so test it for YUV formats // some videolayers support RGB formats - not used now if (verbose) printf("DirectFB: Testing videolayer caps\n"); dlc.flags = DLCONF_PIXELFORMAT; #if DIRECTFBVERSION > 908 dlc.pixelformat = DSPF_YV12; ret = videolayer->TestConfiguration( videolayer, &dlc, &failed ); if (ret==DFB_OK) { videolayercaps.iv12=1; if (verbose) printf("DirectFB: Videolayer supports YV12 format\n"); } else { videolayercaps.iv12=0; if (verbose) printf("DirectFB: Videolayer doesn't support YV12 format\n"); }; dlc.pixelformat = DSPF_I420; ret = videolayer->TestConfiguration( videolayer, &dlc, &failed ); if (ret==DFB_OK) { videolayercaps.i420=1; if (verbose) printf("DirectFB: Videolayer supports I420 format\n"); } else { videolayercaps.i420=0; if (verbose) printf("DirectFB: Videolayer doesn't support I420 format\n"); }; #else videolayercaps.yuy2=0; #endif dlc.pixelformat = DSPF_YUY2; ret = videolayer->TestConfiguration( videolayer, &dlc, &failed ); if (ret==DFB_OK) { videolayercaps.yuy2=1; if (verbose) printf("DirectFB: Videolayer supports YUY2 format\n"); } else { videolayercaps.yuy2=0; if (verbose) printf("DirectFB: Videolayer doesn't support YUY2 format\n"); }; dlc.pixelformat = DSPF_UYVY; ret = videolayer->TestConfiguration( videolayer, &dlc, &failed ); if (ret==DFB_OK) { videolayercaps.uyvy=1; if (verbose) printf("DirectFB: Videolayer supports UYVY format\n"); } else { videolayercaps.uyvy=0; if (verbose) printf("DirectFB: Videolayer doesn't support UYVY format\n"); }; // test for color caps { DFBDisplayLayerCapabilities caps; #if DIRECTFBVERSION > 912 DFBDisplayLayerDescription desc; videolayer->GetDescription(videolayer,&desc); caps = desc.caps; #else videolayer->GetCapabilities(videolayer,&caps); #endif if (caps & DLCAPS_BRIGHTNESS) { videolayercaps.brightness=1; } else { videolayercaps.brightness=0; }; if (caps & DLCAPS_CONTRAST) { videolayercaps.contrast=1; } else { videolayercaps.contrast=0; }; if (caps & DLCAPS_HUE) { videolayercaps.hue=1; } else { videolayercaps.hue=0; }; if (caps & DLCAPS_SATURATION) { videolayercaps.saturation=1; } else { videolayercaps.saturation=0; }; // test if layer can change size/position if (caps & DLCAPS_SCREEN_LOCATION) { videolayercaps.hwscale=1; } else { videolayercaps.hwscale=0; }; } // is there a working yuv ? if no we will not use videolayer if ((videolayercaps.iv12==0)&&(videolayercaps.i420==0)&&(videolayercaps.yuy2==0)&&(videolayercaps.uyvy==0)) { // videolayer doesn't work with yuv so release it videolayerpresent=0; videolayer->SetOpacity(videolayer,0); videolayer->Release(videolayer); } else { videolayerpresent=1; }; } // check generic card capabilities (for hw scaling) { DFBCardCapabilities caps; DFBCHECK (dfb->GetCardCapabilities(dfb,&caps)); if (caps.acceleration_mask & DFXL_STRETCHBLIT) hwstretchblit=1; else hwstretchblit=0; if (verbose && hwstretchblit) printf("DirectFB: Card supports hw stretch blit\n"); } // just look at RGB things for main layer modes[0].valid=0; modes[1].valid=0; modes[2].valid=0; modes[3].valid=0; DFBCHECK (dfb->EnumVideoModes(dfb,enum_modes_callback,NULL)); /* * (Get keyboard) */ ret = dfb->GetInputDevice (dfb, DIDID_KEYBOARD, &keyboard); if (ret==DFB_OK) { if (verbose) { printf("DirectFB: Keyboard init OK\n"); } } else { keyboard = NULL; printf("DirectFB: Keyboard init FAILED\n"); } /* * Create an input buffer for the keyboard. */ #if DIRECTFBVERSION > 908 if (keyboard) DFBCHECK (keyboard->CreateEventBuffer (keyboard, &buffer)); #else if (keyboard) DFBCHECK (keyboard->CreateInputBuffer (keyboard, &buffer)); #endif // just to start with clean ... if (buffer) buffer->Reset(buffer); return 0; } static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) { /* * (Locals) */ DFBSurfaceDescription dsc; DFBResult ret; int vm = fullscreen & 0x02; int zoom = fullscreen & 0x04; if (verbose) printf("DirectFB: Config entered [%ix%i]\n",width,height); if (verbose) printf("DirectFB: With requested format: %s\n",vo_format_name(format)); fs = fullscreen & 0x01; flip = fullscreen & 0x08; pixel_format=format; in_width = width; in_height = height; if (d_width) { out_width = d_width; out_height = d_height; } else { d_width = out_width = in_width; d_height = out_height = in_height; } // just look at RGB things for main layer - once again - now we now desired screen size modes[0].valid=0; modes[1].valid=0; modes[2].valid=0; modes[3].valid=0; DFBCHECK (dfb->EnumVideoModes(dfb,enum_modes_callback,NULL)); if (vm) { // need better algorithm just hack switch (format) { case IMGFMT_RGB32: case IMGFMT_BGR32: if (modes[3].valid) { dfb->SetVideoMode(dfb,modes[3].width,modes[3].height,32); if (verbose) printf("DirectFB: Trying to set videomode [%ix%i 32 bpp]\n",modes[3].width,modes[3].height); }; break; case IMGFMT_RGB24: case IMGFMT_BGR24: if (modes[2].valid) { dfb->SetVideoMode(dfb,modes[2].width,modes[2].height,24); if (verbose) printf("DirectFB: Trying to set videomode [%ix%i 24 bpp]\n",modes[2].width,modes[2].height); }; break; case IMGFMT_RGB16: case IMGFMT_BGR16: case IMGFMT_RGB15: case IMGFMT_BGR15: if (modes[1].valid) { dfb->SetVideoMode(dfb,modes[1].width,modes[1].height,16); if (verbose) printf("DirectFB: Trying to set videomode [%ix%i 16 bpp]\n",modes[1].width,modes[1].height); }; break; default: // try all of them in order 24bit 16bit 32bit 8bit if (modes[2].valid) { dfb->SetVideoMode(dfb,modes[2].width,modes[2].height,24); if (verbose) printf("DirectFB: Trying to set videomode [%ix%i 24 bpp]\n",modes[2].width,modes[2].height); } else if (modes[1].valid) { dfb->SetVideoMode(dfb,modes[1].width,modes[1].height,16); if (verbose) printf("DirectFB: Trying to set videomode [%ix%i 16 bpp]\n",modes[1].width,modes[1].height); } else if (modes[3].valid) { dfb->SetVideoMode(dfb,modes[3].width,modes[3].height,32); if (verbose) printf("DirectFB: Trying to set videomode [%ix%i 32 bpp]\n",modes[3].width,modes[3].height); } else if (modes[0].valid) { dfb->SetVideoMode(dfb,modes[0].width,modes[0].height,8); if (verbose) printf("DirectFB: Trying to set videomode [%ix%i 8 bpp]\n",modes[0].width,modes[0].height); } break; }; } // release primary if it is already allocated if (primaryallocated) { if (verbose ) printf("DirectFB: Release primary\n"); primary->Release (primary); primaryallocated=0; }; videolayeractive=0; // will be enabled on succes later if (videolayerpresent) { // try to set proper w a h values matching image size dlc.flags = DLCONF_WIDTH | DLCONF_HEIGHT; dlc.width = in_width; dlc.height = in_height; ret = videolayer->SetConfiguration( videolayer, &dlc ); if (ret) { if (verbose) printf("DirectFB: Set layer size failed\n"); }; // try to set correct pixel format (closest to required) dlc.flags = DLCONF_PIXELFORMAT; dlc.pixelformat = 0; switch (pixel_format) { case IMGFMT_YV12: #if DIRECTFBVERSION > 908 if (videolayercaps.i420==1) { dlc.pixelformat=DSPF_I420; break; } else if (videolayercaps.iv12==1) { dlc.pixelformat=DSPF_YV12; break; }; #endif case IMGFMT_YUY2: if (videolayercaps.yuy2==1) { dlc.pixelformat=DSPF_YUY2; break; // temporary disabled - do not have conv tool to uyvy /* } else if (videolayercaps.uyvy==1) { dlc.pixelformat=DSPF_UYVY; break; */ #if DIRECTFBVERSION > 908 } else if (videolayercaps.i420==1) { dlc.pixelformat=DSPF_I420; break; } else if (videolayercaps.iv12==1) { dlc.pixelformat=DSPF_YV12; break; #endif }; // shouldn't happen - if it reaches here -> bug case IMGFMT_RGB32: dlc.pixelformat = DSPF_ARGB; break; case IMGFMT_BGR32: dlc.pixelformat = DSPF_ARGB; break; case IMGFMT_RGB24: dlc.pixelformat = DSPF_RGB24; break; case IMGFMT_BGR24: dlc.pixelformat = DSPF_RGB24; break; case IMGFMT_RGB16: dlc.pixelformat = DSPF_RGB16; break; case IMGFMT_BGR16: dlc.pixelformat = DSPF_RGB16; break; case IMGFMT_RGB15: dlc.pixelformat = DSPF_RGB15; break; case IMGFMT_BGR15: dlc.pixelformat = DSPF_RGB15; break; default: dlc.pixelformat = DSPF_RGB24; break; } if (verbose) switch (dlc.pixelformat) { case DSPF_ARGB: printf("DirectFB: layer format ARGB\n"); break; case DSPF_RGB32: printf("DirectFB: layer format RGB32\n"); break; case DSPF_RGB24: printf("DirectFB: layer format RGB24\n"); break; case DSPF_RGB16: printf("DirectFB: layer format RGB16\n"); break; case DSPF_RGB15: printf("DirectFB: layer format RGB15\n"); break; case DSPF_YUY2: printf("DirectFB: layer format YUY2\n"); break; case DSPF_UYVY: printf("DirectFB: layer format UYVY\n"); break; #if DIRECTFBVERSION > 908 case DSPF_YV12: printf("DirectFB: layer format YV12\n"); break; case DSPF_I420: printf("DirectFB: layer format I420\n"); break; #endif default: printf("DirectFB: - unknown format ->exit\n"); return 1; } ret =videolayer->SetConfiguration( videolayer, &dlc ); if (!ret) { if (verbose) printf("DirectFB: SetConfiguration for layer OK\n"); #ifdef FLIPPING // try to set flipping for videolayer if (do_flipping) { dlc.flags = DLCONF_BUFFERMODE; dlc.buffermode = DLBM_BACKVIDEO; invram = 1; flipping = 1; ret =videolayer->SetConfiguration( videolayer, &dlc ); if (ret!=DFB_OK) { invram = 0; if (!((directfb_major_version <= 0) && (directfb_minor_version <= 9) && (directfb_micro_version <= 11))) { dlc.buffermode = DLBM_BACKSYSTEM; ret =videolayer->SetConfiguration( videolayer, &dlc ); if (ret!=DFB_OK) { flipping = 0; } } else { flipping = 0; }; } if (verbose) if (flipping) { printf("DirectFB: SetFlipping for layer: OK (vram=%i)\n",invram); } else { printf("DirectFB: SetFlipping for layer: FAILED\n"); } } else flipping=0; #endif ret = videolayer->GetSurface( videolayer, &primary ); if (!ret){ videolayeractive=1; if (verbose) printf("DirectFB: Get surface for layer: OK\n"); primaryallocated=1; // set videolayer to be visible videolayer->SetOpacity(videolayer,0xFF); } else { videolayeractive=0; if (videolayer) videolayer->SetOpacity(videolayer,0); }; } else { videolayeractive=0; if (videolayer) videolayer->SetOpacity(videolayer,0); }; } // for flipping we will use BitBlt not integrated directfb flip (if necessary) dsc.flags = DSDESC_CAPS | DSDESC_PIXELFORMAT; dsc.caps = DSCAPS_PRIMARY /*| DSCAPS_VIDEOONLY*/; switch (format) { case IMGFMT_RGB32: dsc.pixelformat = DSPF_ARGB; source_pixel_size= 4; break; case IMGFMT_BGR32: dsc.pixelformat = DSPF_ARGB; source_pixel_size= 4; break; case IMGFMT_RGB24: dsc.pixelformat = DSPF_RGB24; source_pixel_size= 3; break; case IMGFMT_BGR24: dsc.pixelformat = DSPF_RGB24; source_pixel_size= 3; break; case IMGFMT_RGB16: dsc.pixelformat = DSPF_RGB16; source_pixel_size= 2; break; case IMGFMT_BGR16: dsc.pixelformat = DSPF_RGB16; source_pixel_size= 2; break; case IMGFMT_RGB15: dsc.pixelformat = DSPF_RGB15; source_pixel_size= 2; break; case IMGFMT_BGR15: dsc.pixelformat = DSPF_RGB15; source_pixel_size= 2; break; default: dsc.pixelformat = DSPF_RGB24; source_pixel_size=2; break; //YUV formats }; if (!videolayeractive) { #ifdef FLIPPING if (do_flipping) { flipping = 1; invram = 0; dsc.caps |= DSCAPS_FLIPPING; ret = dfb->CreateSurface( dfb, &dsc, &primary ); if (ret!=DFB_OK) { dsc.caps &= ~DSCAPS_FLIPPING; DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary )); flipping = 0; } else { // test flipping again DFBCHECK (primary->GetCapabilities(primary,&dsc.caps)); if (!(dsc.caps & DSCAPS_FLIPPING)) { printf("DirectFB: Error - surface sucesfully created with flipping flag, but doesn't support it.\n"); flipping = 0; } else { // test fliping in real - sometimes flips fails even if shouldn't DFBResult ret; ret = primary->Flip(primary,NULL,0); if (ret!=DFB_OK) { // recreate surface as non flipping printf("DirectFB: Error - surface sucesfully created with flipping flag, but test flip failed.\n"); flipping = 0; dsc.caps &= ~DSCAPS_FLIPPING; primary->Release(primary); DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary )); } } } /* if (verbose) if (flipping) { printf("DirectFB: Flipping for primary: OK\n"); } else { printf("DirectFB: Flipping for primary: FAILED\n"); } */ } else { flipping = 0; #endif DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary )); #ifdef FLIPPING } #endif if (verbose) printf("DirectFB: Get primary surface: OK\n"); primaryallocated=1; } #ifdef FLIPPING // final check for flipping - based on real caps DFBCHECK (primary->GetCapabilities(primary,&dsc.caps)); if (!(dsc.caps & DSCAPS_FLIPPING)) { printf("DirectFB: Flipping si NOT active.\n"); flipping = 0; } else { printf("DirectFB: Flipping is active.\n"); flipping = 1; } // } #endif DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height)); DFBCHECK (primary->GetPixelFormat (primary, &frame_format)); // temporary frame buffer dsc.flags = DSDESC_CAPS | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_WIDTH; dsc.width = in_width; dsc.height = in_height; // at this time use pixel req format or format of main disp switch (format) { case IMGFMT_RGB32: dsc.pixelformat = DSPF_ARGB; break; case IMGFMT_BGR32: dsc.pixelformat = DSPF_ARGB; break; case IMGFMT_RGB24: dsc.pixelformat = DSPF_RGB24; break; case IMGFMT_BGR24: dsc.pixelformat = DSPF_RGB24; break; case IMGFMT_RGB16: dsc.pixelformat = DSPF_RGB16; break; case IMGFMT_BGR16: dsc.pixelformat = DSPF_RGB16; break; case IMGFMT_RGB15: dsc.pixelformat = DSPF_RGB15; break; case IMGFMT_BGR15: dsc.pixelformat = DSPF_RGB15; break; default: dsc.pixelformat = frame_format; break; // uknown or YUV -> retain layer format eg. RGB or YUY2 }; /* * Create a surface based on the description of the source frame */ #if DIRECTFBVERSION > 908 if (((dsc.pixelformat==DSPF_YV12)||(dsc.pixelformat==DSPF_I420)) && buggyYV12BitBlt) { memcpyBitBlt = 1; } else { memcpyBitBlt = 0; }; #else memcpyBitBlt = 0; #endif // release frame if it is already allocated if (frameallocated) { if (verbose ) printf("DirectFB: Release frame\n"); frame->Release (frame); frameallocated=0; }; // picture size and position aspect_save_orig(in_width,in_height); aspect_save_prescale(d_width,d_height); if (videolayeractive) {// try to set pos for YUY2 layer and proper aspect ratio aspect_save_screenres(10000,10000); aspect(&out_width,&out_height,A_ZOOM); ret = videolayer->SetScreenLocation(videolayer,(1-(float)out_width/10000)/2,(1-(float)out_height/10000)/2,((float)out_width/10000),((float)out_height/10000)); xoffset = 0; yoffset = 0; } else { // aspect ratio correction for zoom to fullscreen aspect_save_screenres(screen_width,screen_height); if(fs) /* -fs */ aspect(&out_width,&out_height,A_ZOOM); else aspect(&out_width,&out_height,A_NOZOOM); xoffset = (screen_width - out_width) / 2; yoffset = (screen_height - out_height) / 2; } if (((out_width != in_width) || (out_height != in_height)) && (!videolayeractive)) {stretch = 1;} else stretch=0; //yuy doesn't like strech and should not be needed #ifdef FLIPPING // frame will not be allocated in case of overlay or nonstrech blit on primary if (flipping && (!stretch)) { frame = primary; frameallocated = 0; if (verbose) printf("DirectFB: Frame is NOT used (flipping is active).\n"); } else { #endif /* dsc.caps = DSCAPS_SYSTEMONLY; //let dfb decide where frame should be - preparation for AGP support */ dsc.flags &=~DSDESC_CAPS; DFBCHECK (dfb->CreateSurface( dfb, &dsc, &frame)); frameallocated=1; #ifdef FLIPPING if (verbose) if (flipping) { printf("DirectFB: Frame created (flipping&stretch is active).\n"); } else { printf("DirectFB: Frame created (flipping is NOT active).\n"); }; }; #endif DFBCHECK (frame->GetPixelFormat (frame, &frame_format)); switch (frame_format) { case DSPF_ARGB: if (verbose) printf("DirectFB: frame format ARGB\n"); frame_pixel_size = 4; break; case DSPF_RGB32: if (verbose) printf("DirectFB: frame format RGB32\n"); frame_pixel_size = 4; break; case DSPF_RGB24: if (verbose) printf("DirectFB: frame format RGB24\n"); frame_pixel_size = 3; break; case DSPF_RGB16: if (verbose) printf("DirectFB: frame format RGB16\n"); frame_pixel_size = 2; break; case DSPF_RGB15: if (verbose) printf("DirectFB: frame format RGB15\n"); frame_pixel_size = 2; break; case DSPF_YUY2: if (verbose) printf("DirectFB: frame format YUY2\n"); frame_pixel_size = 2; break; case DSPF_UYVY: if (verbose) printf("DirectFB: frame format UYVY\n"); frame_pixel_size = 2; break; #if DIRECTFBVERSION > 908 case DSPF_YV12: if (verbose) printf("DirectFB: frame format YV12\n"); frame_pixel_size = 1; break; case DSPF_I420: if (verbose) printf("DirectFB: frame format I420\n"); frame_pixel_size = 1; break; #endif default: printf("DirectFB: - unknown format ->exit\n"); return 1; } if ((out_width < in_width || out_height < in_height) && (!fs)) { printf("Screensize is smaller than video size !\n"); // return 1; // doesn't matter we will rescale } // yuv2rgb transform init if (((format == IMGFMT_YV12) || (format == IMGFMT_YUY2)) && (!videolayeractive)){ yuv2rgb_init(frame_pixel_size * 8,MODE_RGB);}; if ((verbose)&&(memcpyBitBlt)) printf("DirectFB: Using memcpyBitBlt\n"); #ifdef DIRECTRENDER //direct rendering is enabled in case of same buffer and img format if ((format==IMGFMT_RGB32)&&(frame_format ==DSPF_ARGB) || (format==IMGFMT_BGR32)&&(frame_format ==DSPF_ARGB) || (format==IMGFMT_RGB24)&&(frame_format ==DSPF_RGB24) || (format==IMGFMT_BGR24)&&(frame_format ==DSPF_RGB24) || (format==IMGFMT_RGB16)&&(frame_format ==DSPF_RGB16) || (format==IMGFMT_BGR16)&&(frame_format ==DSPF_RGB16) || (format==IMGFMT_RGB15)&&(frame_format ==DSPF_RGB15) || (format==IMGFMT_BGR15)&&(frame_format ==DSPF_RGB15) || #if DIRECTFBVERSION > 908 (format==IMGFMT_YUY2)&&(frame_format ==DSPF_YUY2) || (format==IMGFMT_YV12)&&(frame_format ==DSPF_I420) || (format==IMGFMT_YV12)&&(frame_format ==DSPF_YV12)){ #else (format==IMGFMT_YUY2)&&(frame_format ==DSPF_YUY2)){ #endif dr_enabled=1; if (verbose) printf("DirectFB: Direct rendering supported\n"); } else { dr_enabled=0; if (verbose) printf("DirectFB: Direct rendering not supported\n"); }; #endif if (verbose) printf("DirectFB: Config finished [%ix%i]\n",out_width,out_height); return 0; } static uint32_t query_format(uint32_t format) { int ret = VFCAP_CSP_SUPPORTED|VFCAP_OSD; /* osd/sub is supported on every bpp */ // preinit(NULL); if (verbose ) printf("DirectFB: Format query: %s\n",vo_format_name(format)); switch (format) { // primary case IMGFMT_RGB32: case IMGFMT_BGR32: case IMGFMT_RGB24: case IMGFMT_BGR24: case IMGFMT_RGB16: case IMGFMT_BGR16: case IMGFMT_RGB15: case IMGFMT_BGR15: if (hwstretchblit) ret |=VFCAP_HWSCALE_UP|VFCAP_HWSCALE_DOWN; break; // overlay case IMGFMT_YUY2: case IMGFMT_YV12: if (videolayercaps.hwscale) ret |=VFCAP_HWSCALE_UP|VFCAP_HWSCALE_DOWN; break; } switch (format) { // RGB mode works only if color depth is same as on screen and this driver doesn't know before init // so we couldn't report supported formats well // Just support those detected by preinit case IMGFMT_RGB32: case IMGFMT_BGR32: if (modes[3].valid) return ret; break; case IMGFMT_RGB24: case IMGFMT_BGR24: if (modes[2].valid) return ret; break; case IMGFMT_RGB16: case IMGFMT_BGR16: case IMGFMT_RGB15: case IMGFMT_BGR15: if (modes[1].valid) return ret; break; case IMGFMT_YUY2: if (videolayerpresent) { if (videolayercaps.hwscale) ret |=VFCAP_HWSCALE_UP|VFCAP_HWSCALE_DOWN; if (videolayercaps.yuy2) { return ret|VFCAP_CSP_SUPPORTED_BY_HW; // disabled - MPlayer will do conversion automatically /* } else { return ret; */ }; }; break; case IMGFMT_YV12: if ((videolayerpresent) && (videolayercaps.i420 || videolayercaps.iv12)) return ret|VFCAP_CSP_SUPPORTED_BY_HW; // disabled - MPlayer will do conversion automatically /* else return ret; */ break; } return 0; } static const vo_info_t *get_info(void) { return &vo_info; } static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) { void *dst; int pitch; int len; static IDirectFBSurface *surface = NULL; #ifdef DIRECTRENDER if(framelocked) { frame->Unlock(frame); framelocked=0; }; #endif #ifdef FLIPPING if (flipping && stretch) { DFBCHECK (primary->Lock(primary,DSLF_WRITE,&dst,&pitch)); } else { #endif DFBCHECK (frame->Lock(frame,DSLF_WRITE,&dst,&pitch)); #ifdef FLIPPING } #endif switch(frame_format) { case DSPF_RGB32: case DSPF_ARGB: vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + frame_pixel_size*x0,pitch); break; case DSPF_RGB24: vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + frame_pixel_size*x0,pitch); break; case DSPF_RGB16: vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + frame_pixel_size*x0,pitch); break; case DSPF_RGB15: vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + frame_pixel_size*x0,pitch); break; case DSPF_YUY2: vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + frame_pixel_size*x0,pitch); break; case DSPF_UYVY: vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + frame_pixel_size*x0 + 1,pitch); break; #if DIRECTFBVERSION > 908 case DSPF_I420: case DSPF_YV12: vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + frame_pixel_size*x0,pitch); break; #endif } #ifdef FLIPPING if (flipping && stretch) { DFBCHECK (primary->Unlock(primary)); } else { #endif DFBCHECK (frame->Unlock(frame)); #ifdef FLIPPING } #endif } static uint32_t draw_frame(uint8_t *src[]) { void *dst; int pitch; int len; // printf("Drawframe\n"); #ifdef DIRECTRENDER if(framelocked) { frame->Unlock(frame); framelocked=0; }; #endif DFBCHECK (frame->Lock(frame,DSLF_WRITE,&dst,&pitch)); switch (frame_format) { case DSPF_ARGB: case DSPF_RGB32: case DSPF_RGB24: case DSPF_RGB16: case DSPF_RGB15: switch (pixel_format) { case IMGFMT_YV12: yuv2rgb(dst,src[0],src[1],src[2],in_width,in_height,pitch,in_width,in_width/2); break; /* how to handle this? need conversion from YUY2 to RGB*/ /* case IMGFMT_YUY2: yuv2rgb(dst,src[0],src[0]+1,src[0]+3,1,in_height*in_width/2,frame_pixel_size*2,4,4); //odd pixels yuv2rgb(dst+1,src[0]+2,src[0]+1,src[0]+3,1,in_height*in_width/2,frame_pixel_size*2,4,4); //even pixels break;*/ // RGB - just copy default: if (source_pixel_size==frame_pixel_size) { if (pitch==(in_width*frame_pixel_size)) { memcpy(dst,src[0],in_width * in_height * source_pixel_size); } else { int i; int sp=in_width*source_pixel_size; int ll=min(sp,pitch); for (i=0;i<in_height;i++) { memcpy(dst+i*pitch,src[0]+i*sp,ll); }; }; }; }; break; case DSPF_YUY2: switch (pixel_format) { case IMGFMT_YV12: yv12toyuy2(src[0],src[1],src[2],dst,in_width,in_height,in_width,in_width >>1,pitch); break; case IMGFMT_YUY2: if (pitch==(in_width*2)) { memcpy(dst,src[0],in_width * in_height * source_pixel_size); } else { int i; for (i=0;i<in_height;i++) { memcpy(dst+i*pitch,src[0]+i*in_width*2,in_width*2); } } break; // hopefully there will be no RGB in this case otherwise convert - not implemented }; break; #if DIRECTFBVERSION > 908 case DSPF_YV12: switch (pixel_format) { case IMGFMT_YV12: { int i; int p=min(in_width,pitch); for (i=0;i<in_height;i++) { memcpy(dst+i*pitch,src[0]+i*in_width,p); } dst += pitch*in_height; p = p/2; for (i=0;i<in_height/2;i++) { memcpy(dst+i*pitch/2,src[2]+i*in_width/2,p); } dst += pitch*in_height/4; for (i=0;i<in_height/2;i++) { memcpy(dst+i*pitch/2,src[1]+i*in_width/2,p); } }; break; case IMGFMT_YUY2: yuy2toyv12(src[0],dst,dst+pitch*in_height+pitch*in_height/4,dst+pitch*in_height,in_width,in_height,pitch,pitch/2,pitch/2); break; // hopefully there will be no RGB in this case otherwise convert - not implemented } break; case DSPF_I420: switch (pixel_format) { case IMGFMT_YV12: { int i; int p=min(in_width,pitch); for (i=0;i<in_height;i++) { memcpy(dst+i*pitch,src[0]+i*in_width,p); } dst += pitch*in_height; p = p/2; for (i=0;i<in_height/2;i++) { memcpy(dst+i*pitch/2,src[1]+i*in_width/2,p); } dst += pitch*in_height/4; for (i=0;i<in_height/2;i++) { memcpy(dst+i*pitch/2,src[2]+i*in_width/2,p); } }; break; case IMGFMT_YUY2: yuy2toyv12(src[0],dst,dst+pitch*in_height,dst+pitch*in_height+pitch*in_height/4,in_width,in_height,pitch,pitch/2,pitch/2); break; // hopefully there will be no RGB in this case otherwise convert - not implemented } break; #endif } DFBCHECK (frame->Unlock(frame)); return 0; } static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y) { int err; void *dst; uint8_t *s; int pitch; int i; #ifdef DIRECTRENDER if(framelocked) { frame->Unlock(frame); framelocked=0; }; #endif err = frame->Lock(frame,DSLF_WRITE,&dst,&pitch); // err = primary->Lock(primary,DSLF_WRITE,&dst,&pitch); // for direct rendering // printf("Drawslice w=%i h=%i x=%i y=%i pitch=%i\n",w,h,x,y,pitch); if (err) { printf("DirectFB: Frame lock failed!"); return 1; }; switch (frame_format) { case DSPF_ARGB: case DSPF_RGB32: case DSPF_RGB24: case DSPF_RGB16: case DSPF_RGB15: switch (pixel_format) { case IMGFMT_YV12: yuv2rgb(dst+ y * pitch + frame_pixel_size*x ,src[0],src[1],src[2],w,h,pitch,stride[0],stride[1]); break; default: if (source_pixel_size==frame_pixel_size) { dst += x * frame_pixel_size; s = src[0]; for (i=y;i<(y+h);i++) { memcpy(dst,s,w); dst += (pitch); s += stride[0]; }; } break; } break; case DSPF_YUY2: switch (pixel_format) { case IMGFMT_YV12: yv12toyuy2(src[0],src[1],src[2],dst + pitch*y + frame_pixel_size*x ,w,h,stride[0],stride[1],pitch); break; // hopefully there will be no RGB in this case otherwise convert - not implemented } break; #if DIRECTFBVERSION > 908 case DSPF_YV12: switch (pixel_format) { case IMGFMT_YV12: { void *d,*s; int i; d = dst + pitch*y + x; s = src[0]; for (i=0;i<h;i++) { memcpy(d,s,w); d+=pitch; s+=stride[0]; } d = dst + pitch*in_height + pitch*y/4 + x/2; s = src[2]; for (i=0;i<h/2;i++) { memcpy(d,s,w/2); d+=pitch/2; s+=stride[2]; } d = dst + pitch*in_height + pitch*in_height/4 + pitch*y/4 + x/2; s = src[1]; for (i=0;i<h/2;i++) { memcpy(d,s,w/2); d+=pitch/2; s+=stride[1]; } }; break; /* case IMGFMT_YUY2: { int i; for (i=y;i<(y+h);i++) { yuy2toyv12(src[0]+i*stride[0],dst+i*pitch+x*frame_pixel_size,dst+pitch*(in_height+i/2)+x*frame_pixel_size/2,dst+pitch*(in_height+in_height/4+i/2)+x*frame_pixel_size/2,w,h,pitch,pitch/2,pitch/2); } } break; */ // hopefully there will be no RGB in this case otherwise convert - not implemented } break; case DSPF_I420: switch (pixel_format) { case IMGFMT_YV12: { void *d,*s; int i; d = dst + pitch*y + x; s = src[0]; for (i=0;i<h;i++) { memcpy(d,s,w); d+=pitch; s+=stride[0]; } d = dst + pitch*in_height + pitch*y/4 + x/2; s = src[1]; for (i=0;i<h/2;i++) { memcpy(d,s,w/2); d+=pitch/2; s+=stride[1]; } d = dst + pitch*in_height + pitch*in_height/4 + pitch*y/4 + x/2; s = src[2]; for (i=0;i<h/2;i++) { memcpy(d,s,w/2); d+=pitch/2; s+=stride[2]; } }; break; /* case IMGFMT_YUY2: { int i; for (i=y;i<(y+h);i++) { yuy2toyv12(src[0]+i*stride[0],dst+i*pitch+x*frame_pixel_size,dst+pitch*(in_height+in_height/4+i/2)+x*frame_pixel_size/2,dst+pitch*(in_height+i/2)+x*frame_pixel_size/2,w,h,pitch,pitch/2,pitch/2); } } break; */ // hopefully there will be no RGB in this case otherwise convert - not implemented } break; #endif }; frame->Unlock(frame); // primary->Unlock(primary); return 0; } extern void mplayer_put_key(int code); #include "../linux/keycodes.h" static void check_events(void) { if (buffer) { DFBInputEvent event; //if (verbose) printf ("DirectFB: Check events entered\n"); #if DIRECTFBVERSION > 909 if (buffer->GetEvent(buffer, DFB_EVENT (&event)) == DFB_OK) { #else if (buffer->GetEvent(buffer, &event) == DFB_OK) { #endif if (event.type == DIET_KEYPRESS) { #if DIRECTFBVERSION > 910 switch (event.key_symbol) { case DIKS_ESCAPE: mplayer_put_key('q'); break; case DIKS_PAGE_UP: mplayer_put_key(KEY_PAGE_UP);break; case DIKS_PAGE_DOWN: mplayer_put_key(KEY_PAGE_DOWN);break; case DIKS_CURSOR_UP: mplayer_put_key(KEY_UP);break; case DIKS_CURSOR_DOWN: mplayer_put_key(KEY_DOWN);break; case DIKS_CURSOR_LEFT: mplayer_put_key(KEY_LEFT);break; case DIKS_CURSOR_RIGHT: mplayer_put_key(KEY_RIGHT);break; case DIKS_INSERT: mplayer_put_key(KEY_INSERT);break; case DIKS_DELETE: mplayer_put_key(KEY_DELETE);break; case DIKS_HOME: mplayer_put_key(KEY_HOME);break; case DIKS_END: mplayer_put_key(KEY_END);break; default:mplayer_put_key(event.key_symbol); }; #else /* DirectFB < 0.9.11 */ switch (event.keycode) { case DIKC_ESCAPE: mplayer_put_key('q');break; case DIKC_KP_PLUS: mplayer_put_key('+');break; case DIKC_KP_MINUS: mplayer_put_key('-');break; case DIKC_TAB: mplayer_put_key('\t');break; case DIKC_PAGEUP: mplayer_put_key(KEY_PAGE_UP);break; case DIKC_PAGEDOWN: mplayer_put_key(KEY_PAGE_DOWN);break; case DIKC_UP: mplayer_put_key(KEY_UP);break; case DIKC_DOWN: mplayer_put_key(KEY_DOWN);break; case DIKC_LEFT: mplayer_put_key(KEY_LEFT);break; case DIKC_RIGHT: mplayer_put_key(KEY_RIGHT);break; case DIKC_ASTERISK: case DIKC_KP_MULT:mplayer_put_key('*');break; case DIKC_KP_DIV: mplayer_put_key('/');break; case DIKC_INSERT: mplayer_put_key(KEY_INSERT);break; case DIKC_DELETE: mplayer_put_key(KEY_DELETE);break; case DIKC_HOME: mplayer_put_key(KEY_HOME);break; case DIKC_END: mplayer_put_key(KEY_END);break; default:mplayer_put_key(event.key_ascii); }; #endif }; }; } // empty buffer, because of repeating (keyboard repeat is faster than key handling // and this causes problems during seek) // temporary workabout should be solved in the future if (buffer) buffer->Reset(buffer); //if (verbose) printf ("DirectFB: Check events finished\n"); } static void draw_osd(void) { // if flipping is active we will draw directly to primary // we will also blit from frame to primary if necessary #ifdef FLIPPING if (stretch && flipping) { DFBRectangle rect; rect.x=xoffset; rect.y=yoffset; rect.w=out_width; rect.h=out_height; #ifdef DIRECTRENDER if(framelocked) { frame->Unlock(frame); framelocked=0; }; #endif // lets clear blackborders primary->SetColor(primary,0,0,0,0); // top primary->FillRectangle(primary,0,0,screen_width,yoffset); // bottom primary->FillRectangle(primary,0,screen_height-yoffset,screen_width,yoffset); //left // primary->FillRectangle(primary,0,yoffset,xoffset,screen_height-2*yoffset); //right // primary->FillRectangle(primary,screen_width-xoffset-1,yoffset,xoffset,screen_height-2*yoffset); DFBCHECK (primary->StretchBlit(primary,frame,NULL,&rect)); blitperformed=1; vo_draw_text(screen_width, screen_height, draw_alpha); } else { #endif vo_draw_text(in_width, in_height, draw_alpha); #ifdef FLIPPING } #endif } static void flip_page(void) { DFBSurfaceBlittingFlags flags=DSBLIT_NOFX; // if (verbose) printf("DirectFB: Flip page entered"); DFBCHECK (primary->SetBlittingFlags(primary,flags)); #ifdef DIRECTRENDER if(framelocked) { frame->Unlock(frame); framelocked=0; }; #endif if (stretch #ifdef FLIPPING && (!blitperformed) #endif ) { DFBRectangle rect; rect.x=xoffset; rect.y=yoffset; rect.w=out_width; rect.h=out_height; DFBCHECK (primary->StretchBlit(primary,frame,NULL,&rect)); #ifdef FLIPPING blitperformed=0; #endif } else { #ifdef FLIPPING if (!flipping) { #endif #if DIRECTFBVERSION > 908 if (!memcpyBitBlt) { #endif DFBCHECK (primary->Blit(primary,frame,NULL,xoffset,yoffset)); #if DIRECTFBVERSION > 908 } else { int err,err2; void *dst,*src; int pitch,pitch2; // printf("MemcpyBlit"); err = frame->Lock(frame,DSLF_READ,&src,&pitch); err2 = primary->Lock(primary,DSLF_WRITE,&dst,&pitch2); // printf("DirectFB: pitch=%i pitch2=%i\n",pitch,pitch2); if (pitch==pitch2) { memcpy(dst,src,in_height * pitch * 1.5); } else { int i; int p=min(pitch,pitch2); for (i=0;i<in_height;i++) { memcpy (dst+i*pitch2,src+i*pitch,p); }; dst+= in_height * pitch2; src+= in_height * pitch; p=p/2; for (i=0;i<in_height/2;i++) { memcpy (dst+i*pitch2/2,src+i*pitch/2,p); }; dst+= in_height * pitch2/4; src+= in_height * pitch/4; for (i=0;i<in_height/2;i++) { memcpy (dst+i*pitch2/2,src+i*pitch/2,p); }; } frame->Unlock(frame); primary->Unlock(primary); }; #endif #ifdef FLIPPING }; #endif }; #ifdef FLIPPING if (flipping) { if (videolayeractive && wait_vsync_after_flip) { DFBCHECK (primary->Flip (primary, NULL, /*DSFLIP_WAITFORSYNC*/0)); /* workabout for videolayer flip will take place on next vsync, but pointers are updated instanlty -> -> decoding goes into "new" buffer which is still displayed -> -> so wait for vsync to be safe (and have surfaces REALLY flipped) */ dfb->WaitForSync(dfb); } else { DFBCHECK (primary->Flip (primary, NULL, DSFLIP_WAITFORSYNC)); }; }; #endif } static void uninit(void) { if (verbose ) printf("DirectFB: uninit entered\n"); /* * (Release) */ if (verbose ) printf("DirectFB: Release buffer\n"); if (buffer) buffer->Release (buffer); if (verbose ) printf("DirectFB: Release keyboard\n"); if (keyboard) keyboard->Release (keyboard); if (frameallocated) { if (verbose ) printf("DirectFB: Release frame\n"); frame->Release (frame); frameallocated=0; }; // we will not release dfb and layer because there could be a new film if (verbose ) printf("DirectFB: Release primary\n"); primary->Release (primary); // switch off BES if (videolayer) videolayer->SetOpacity(videolayer,0); #if DIRECTFBVERSION > 908 if (verbose&&videolayer ) printf("DirectFB: Release videolayer\n"); if (videolayer) videolayer->Release(videolayer); if (verbose ) printf("DirectFB: Release DirectFB library\n"); dfb->Release (dfb); #endif if (verbose ) printf("DirectFB: Uninit done.\n"); } static uint32_t directfb_set_video_eq(char *data, int value) //data==name { DFBColorAdjustment ca; float factor = (float)0xffff / 200.0; DFBDisplayLayerCapabilities caps; if (videolayer) { #if DIRECTFBVERSION > 912 DFBDisplayLayerDescription desc; videolayer->GetDescription(videolayer,&desc); caps = desc.caps; #else videolayer->GetCapabilities(videolayer,&caps); #endif ca.flags=DCAF_NONE; if (! strcmp( data,"brightness" )) { if (caps & DLCAPS_BRIGHTNESS) { ca.brightness = value * factor +0x8000; ca.flags |= DCAF_BRIGHTNESS; if (verbose) printf("DirectFB: SetVEq Brightness 0x%X %i\n",ca.brightness,value); } else return VO_FALSE; } if (! strcmp( data,"contrast" )) { if ((caps & DLCAPS_CONTRAST)) { ca.contrast = value * factor + 0x8000; ca.flags |= DCAF_CONTRAST; if (verbose) printf("DirectFB: SetVEq Contrast 0x%X %i\n",ca.contrast,value); } else return VO_FALSE; } if (! strcmp( data,"hue" )) { if ((caps & DLCAPS_HUE)) { ca.hue = value * factor + 0x8000; ca.flags |= DCAF_HUE; if (verbose) printf("DirectFB: SetVEq Hue 0x%X %i\n",ca.hue,value); } else return VO_FALSE; } if (! strcmp( data,"saturation" )) { if ((caps & DLCAPS_SATURATION)) { ca.saturation = value * factor + 0x8000; ca.flags |= DCAF_SATURATION; if (verbose) printf("DirectFB: SetVEq Saturation 0x%X %i\n",ca.saturation,value); } else return VO_FALSE; } if (ca.flags != DCAF_NONE) { videolayer->SetColorAdjustment(videolayer,&ca); return VO_TRUE; } } return VO_FALSE; } static uint32_t directfb_get_video_eq(char *data, int *value) // data==name { DFBColorAdjustment ca; float factor = 200.0 / (float)0xffff; DFBDisplayLayerCapabilities caps; if (videolayer) { #if DIRECTFBVERSION > 912 DFBDisplayLayerDescription desc; videolayer->GetDescription(videolayer,&desc); caps = desc.caps; #else videolayer->GetCapabilities(videolayer,&caps); #endif videolayer->GetColorAdjustment(videolayer,&ca); if (! strcmp( data,"brightness" )) { if (caps & DLCAPS_BRIGHTNESS) { *value = (int) ((ca.brightness-0x8000) * factor); if (verbose) printf("DirectFB: GetVEq Brightness 0x%X %i\n",ca.brightness,*value); return VO_TRUE; } else return VO_FALSE; } if (! strcmp( data,"contrast" )) { if ((caps & DLCAPS_CONTRAST)) { *value = (int) ((ca.contrast-0x8000) * factor); if (verbose) printf("DirectFB: GetVEq Contrast 0x%X %i\n",ca.contrast,*value); return VO_TRUE; } else return VO_FALSE; } if (! strcmp( data,"hue" )) { if ((caps & DLCAPS_HUE)) { *value = (int) ((ca.hue-0x8000) * factor); if (verbose) printf("DirectFB: GetVEq Hue 0x%X %i\n",ca.hue,*value); return VO_TRUE; } else return VO_FALSE; } if (! strcmp( data,"saturation" )) { if ((caps & DLCAPS_SATURATION)) { *value = (int) ((ca.saturation-0x8000) * factor); if (verbose) printf("DirectFB: GetVEq Saturation 0x%X %i\n",ca.saturation,*value); return VO_TRUE; } else return VO_FALSE; } } return VO_FALSE; } #ifdef DIRECTRENDER static uint32_t get_image(mp_image_t *mpi){ int err; void *dst; int pitch; // printf("DirectFB: get_image() called\n"); // now we are always in system memory (in this version - mybe will change in future) #ifdef FLIPPING if((mpi->flags&MP_IMGFLAG_READABLE) && invram) return VO_FALSE; // slow video ram #endif // printf("width=%d vs. pitch=%d, flags=0x%X \n",mpi->width,pitch,mpi->flags); if((mpi->width==pitch/frame_pixel_size) || (mpi->flags&(MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_ACCEPT_WIDTH))){ // we're lucky or codec accepts stride => ok, let's go! if(mpi->flags&MP_IMGFLAG_PLANAR){ #if DIRECTFBVERSION > 908 err = frame->Lock(frame,DSLF_WRITE/*|DSLF_READ*/,&dst,&pitch); // err = primary->Lock(primary,DSLF_WRITE,&dst,&pitch); // for real direct rendering if (err) { printf("DirectFB: Frame lock failed!"); return VO_FALSE; }; framelocked=1; //YV12 format mpi->planes[0]=dst; switch(frame_format) { case DSPF_I420: mpi->planes[1]=dst + pitch*in_height; mpi->planes[2]=mpi->planes[1] + pitch*in_height/4; break; case DSPF_YV12: mpi->planes[2]=dst + pitch*in_height; mpi->planes[1]=mpi->planes[1] + pitch*in_height/4; break; } mpi->width=mpi->stride[0]=pitch; mpi->stride[1]=mpi->stride[2]=pitch/2; #else return VO_FALSE; #endif } else { err = frame->Lock(frame,DSLF_WRITE/*|DSLF_READ*/,&dst,&pitch); // err = primary->Lock(primary,DSLF_WRITE,&dst,&pitch); // for real direct rendering if (err) { printf("DirectFB: Frame lock failed!"); return VO_FALSE; }; framelocked=1; //YUY2 and RGB formats mpi->planes[0]=dst; mpi->width=pitch/frame_pixel_size; mpi->stride[0]=pitch; } mpi->flags|=MP_IMGFLAG_DIRECT; // printf("DirectFB: get_image() SUCCESS -> Direct Rendering ENABLED\n"); return VO_TRUE; } if(framelocked) { frame->Unlock(frame); framelocked=0; }; return VO_FALSE; } #endif static uint32_t control(uint32_t request, void *data, ...) { switch (request) { case VOCTRL_SET_EQUALIZER: { va_list ap; int value; va_start(ap, data); value = va_arg(ap, int); va_end(ap); return(directfb_set_video_eq(data, value)); } case VOCTRL_GET_EQUALIZER: { va_list ap; int *value; va_start(ap, data); value = va_arg(ap, int*); va_end(ap); return(directfb_get_video_eq(data, value)); } case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data)); #ifdef DIRECTRENDER case VOCTRL_GET_IMAGE: // printf("DirectFB: control(VOCTRL_GET_IMAGE) called\n"); if (dr_enabled) return get_image(data); #endif } return VO_NOTIMPL; }