changeset 8138:ca825957ed02

This patch adds direct rendering to vo_dfbmga. With only CRTC2 output all buffer setups are possible. If BES is used only EXPORT and TEMP work. At least that's how I think it works :) IP/IPB stuff was pretty much stolen from vo_xv.c. patch by Ville Syrj¸«£l¸«£ <syrjala@sci.fi>
author arpi
date Sun, 10 Nov 2002 13:58:46 +0000
parents 530d1c5f0c78
children 64c21a33ce31
files libvo/vo_dfbmga.c
diffstat 1 files changed, 242 insertions(+), 233 deletions(-) [+]
line wrap: on
line diff
--- a/libvo/vo_dfbmga.c	Sun Nov 10 13:57:42 2002 +0000
+++ b/libvo/vo_dfbmga.c	Sun Nov 10 13:58:46 2002 +0000
@@ -76,6 +76,11 @@
 static IDirectFBDisplayLayer *crtc2;
 static IDirectFBDisplayLayer *spic;
 
+static int num_bufs;
+static int current_buf;
+static int current_ip_buf;
+static IDirectFBSurface *bufs[3];
+
 static IDirectFBSurface *frame;
 static IDirectFBSurface *c2frame;
 static IDirectFBSurface *subframe;
@@ -99,6 +104,8 @@
 static int use_crtc2 = 1;
 static int use_spic  = 1;
 
+static int osd_changed;
+
 /******************************
 *	    vo_directfb       *
 ******************************/
@@ -110,14 +117,12 @@
  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 screen_width;
 static uint32_t screen_height;
+static uint32_t sub_width;
+static uint32_t sub_height;
 
 static char *
 pixelformat_name( DFBSurfacePixelFormat format )
@@ -181,8 +186,6 @@
 static uint32_t
 preinit( const char *arg )
 {
-     DFBSurfaceDescription dsc;
-
      if (vo_subdevice) {
           while (*vo_subdevice != '\0') {
                if (!strncmp(vo_subdevice, "bes", 3)) {
@@ -234,7 +237,7 @@
      }
 
      if (dfb->GetInputDevice( dfb, DIDID_KEYBOARD, &keyboard ) != DFB_OK)
-          dfb->Release( dfb );
+          return -1;
      keyboard->CreateEventBuffer( keyboard, &buffer );
      buffer->Reset( buffer );
 
@@ -250,8 +253,6 @@
 {
      DFBDisplayLayerConfig      dlc;
      DFBDisplayLayerConfigFlags failed;
-     DFBSurfaceDescription      dsc;
-     DFBResult                  ret;
 
      uint32_t out_width;
      uint32_t out_height;
@@ -283,20 +284,27 @@
                                   (1.0f - (float) out_height / 10000.0f) / 2.0f,
                                   (float) out_width  / 10000.0f,
                                   (float) out_height / 10000.0f );
+          bufs[0] = frame;
+          num_bufs = 1;
      } else {
           /* Draw to a temporary surface */
           DFBSurfaceDescription dsc;
 
-          dsc.flags       = DSDESC_CAPS |
-                            DSDESC_WIDTH | DSDESC_HEIGHT |
+          dsc.flags       = DSDESC_WIDTH | DSDESC_HEIGHT |
                             DSDESC_PIXELFORMAT;
-          dsc.caps        = DSCAPS_VIDEOONLY;
           dsc.width       = in_width;
           dsc.height      = in_height;
           dsc.pixelformat = dlc.pixelformat;
 
-          if (dfb->CreateSurface( dfb, &dsc, &frame ) != DFB_OK)
-               return -1;
+          for (num_bufs = 0; num_bufs < 3; num_bufs++) {
+               if (dfb->CreateSurface( dfb, &dsc, &bufs[num_bufs] ) != DFB_OK) {
+                    if (num_bufs == 0)
+                         return -1;
+               }
+          }
+          frame = bufs[0];
+          current_buf = 0;
+          current_ip_buf = 0;
      }
 
      if (use_crtc2) {
@@ -358,8 +366,11 @@
           c2frame->Clear( c2frame, 0, 0, 0, 0 );
 
           printf( "vo_dfbmga: CRTC2 surface %dx%d %s\n", dlc.width, dlc.height, pixelformat_name( dlc.pixelformat ) );
-     } else
-          use_spic = 0;
+     } else {
+          screen_width  = in_width;
+          screen_height = in_height;
+          use_spic      = 0;
+     }
 
      frame->GetPixelFormat( frame, &frame_format );
      frame_pixel_size = DFB_BYTES_PER_PIXEL( frame_format );
@@ -406,15 +417,14 @@
           subframe = c2frame;
      } else {
           /* Draw OSD to BES surface */
-          subframe            = frame;
-          screen_width        = in_width;
-          screen_height       = in_height;
+          subframe = frame;
      }
 
+     subframe->GetSize( subframe, &sub_width, &sub_height );
      subframe->GetPixelFormat( subframe, &subframe_format );
      subframe_pixel_size = DFB_BYTES_PER_PIXEL( subframe_format );
      printf( "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n",
-             screen_width, screen_height,
+             sub_width, sub_height,
              pixelformat_name( subframe_format ),
              use_crtc2 ? (use_spic ? "Sub-picture layer" : "CRTC2") : "BES" );
 
@@ -461,19 +471,20 @@
 	return &vo_info;
 }
 
-static void vo_draw_alpha_lut8( int w, int h,
-                                unsigned char* src,
-                                unsigned char *srca,
-                                int srcstride,
-                                unsigned char* dst,
-                                int dststride )
+static void
+vo_draw_alpha_lut8( int w, int h,
+                    unsigned char* src,
+                    unsigned char *srca,
+                    int srcstride,
+                    unsigned char* dst,
+                    int dststride )
 {
      int x;
 
      while (h--) {
           for (x = 0; x < w; x++) {
                if (srca[x])
-                    dst[x] |= ((255 - srca[x]) & 0xF0) | (src[x] >> 4);
+                    dst[x] = ((255 - srca[x]) & 0xF0) | (src[x] >> 4);
           }
           src  += srcstride;
           srca += srcstride;
@@ -491,7 +502,11 @@
      void *dst;
      int pitch;
 
-     subframe->Lock( subframe, DSLF_WRITE, &dst, &pitch );
+     if (use_spic && !osd_changed)
+          return;
+
+     if (subframe->Lock( subframe, DSLF_WRITE, &dst, &pitch ) != DFB_OK)
+          return;
 
      switch (subframe_format) {
      case DSPF_LUT8:
@@ -536,6 +551,7 @@
 			      ((uint8_t *) dst) + pitch * y0 + subframe_pixel_size * x0,
                               pitch );
 	  break;
+     default:
      }
 
      subframe->Unlock( subframe );
@@ -544,77 +560,7 @@
 static uint32_t
 draw_frame( uint8_t * src[] )
 {
-     void *dst;
-     int pitch;
-
-     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:
-     case DSPF_YUY2:
-     case DSPF_UYVY:
-          {
-               int i;
-               for (i = 0; i < in_height; i++) {
-                    memcpy( dst + i * pitch,
-                            src[0] + i * in_width * frame_pixel_size,
-                            in_width * frame_pixel_size );
-               }
-          }
-          break;
-     case DSPF_YV12:
-          {
-               int i;
-               for (i = 0; i < in_height; i++) {
-                    memcpy( dst + i * pitch,
-                            src[0] + i * in_width,
-                            in_width );
-               }
-               dst += pitch * in_height;
-               for (i = 0; i < in_height / 2; i++) {
-                    memcpy( dst + i * pitch / 2,
-                            src[2] + i * in_width / 2,
-                            in_width / 2 );
-               }
-               dst += pitch * in_height / 4;
-               for (i = 0; i < in_height / 2; i++) {
-                    memcpy( dst + i * pitch / 2,
-                            src[1] + i * in_width / 2,
-                            in_width / 2 );
-               }
-          }
-          break;
-     case DSPF_I420:
-          {
-               int i;
-               for (i = 0; i < in_height; i++) {
-                    memcpy( dst + i * pitch,
-                            src[0] + i * in_width,
-                            in_width );
-               }
-               dst += pitch * in_height;
-               for (i = 0; i < in_height / 2; i++) {
-                    memcpy( dst + i * pitch / 2,
-                            src[1] + i * in_width / 2,
-                            in_width / 2 );
-               }
-               dst += pitch * in_height / 4;
-               for (i = 0; i < in_height / 2; i++) {
-                    memcpy( dst + i * pitch / 2,
-                            src[2] + i * in_width / 2,
-                            in_width / 2 );
-               }
-          }
-          break;
-     }
-
-     frame->Unlock( frame );
-
-     return 0;
+     return -1;
 }
 
 static uint32_t
@@ -623,140 +569,102 @@
      void *dst;
      int pitch;
 
-     frame->Lock( frame, DSLF_WRITE, &dst, &pitch );
+     if (vo_directrendering)
+          frame->Unlock( frame );
+
+     if (frame->Lock( frame, DSLF_WRITE, &dst, &pitch ) != DFB_OK)
+          return VO_FALSE;
 
-     switch (frame_format) {
-     case DSPF_ARGB:
-     case DSPF_RGB32:
-     case DSPF_RGB24:
-     case DSPF_RGB16:
-     case DSPF_RGB15:
-     case DSPF_YUY2:
-     case DSPF_UYVY:
-          {
-               void *s;
-               int i;
+     memcpy_pic( dst + pitch * y + x, src[0],
+                 w, h, pitch, stride[0] );
+
+     dst += pitch * in_height;
+
+     x /= 2; y /= 2;
+     w /= 2; h /= 2;
+     pitch /= 2;
 
-               dst += y * pitch + x * frame_pixel_size;
-               s = src[0];
-               for (i = 0; i < h; i++) {
-                    memcpy( dst, s, w );
-                    dst += pitch;
-                    s += stride[0];
-               }
-          }
-          break;
-     case DSPF_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 DSPF_I420:
-          {
-               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;
-     }
+     if (frame_format == DSPF_I420 )
+          memcpy_pic( dst + pitch * y + x, src[1],
+                      w, h, pitch, stride[1] );
+     else 
+          memcpy_pic( dst + pitch * y + x, src[2],
+                      w, h, pitch, stride[2] );
+
+     dst += pitch * in_height / 2;
+
+     if (frame_format == DSPF_I420 )
+          memcpy_pic( dst + pitch * y + x, src[2],
+                      w, h, pitch, stride[2] );
+     else
+          memcpy_pic( dst + pitch * y + x, src[1],
+                      w, h, pitch, stride[1] );
 
      frame->Unlock( frame );
 
-     return 0;
+     return VO_TRUE;
 }
 
 static void
 draw_osd( void )
 {
-     if (use_spic)
-          subframe->Clear( subframe, 0, 0, 0, 0 );
-     else if (use_crtc2) {
-          /* Clear black bars around the picture */
-          subframe->SetColor( subframe, 0, 0, 0, 0 );
-          subframe->FillRectangle( subframe,
-                                  0, 0,
-                                  drect.x, drect.y + drect.h );
-          subframe->FillRectangle( subframe,
-                                  0, drect.y + drect.h,
-                                  drect.x + drect.w, drect.y );
-          subframe->FillRectangle( subframe,
-                                  drect.x, 0,
-                                  drect.x + drect.w, drect.y );
-          subframe->FillRectangle( subframe,
-                                  drect.x + drect.w, drect.y,
-                                  drect.x, drect.y + drect.h );
+     if (vo_directrendering)
+          frame->Unlock( frame );
+
+     osd_changed = vo_osd_changed( 0 );
+
+     if (osd_changed) {
+          if (use_spic) {
+               subframe->Clear( subframe, 0, 0, 0, 0 );
+          } else if (use_crtc2) {
+               /* Clear black bars around the picture */
+               subframe->SetColor( subframe, 0, 0, 0, 0 );
+               subframe->FillRectangle( subframe,
+                                        0, 0,
+                                        screen_width, drect.y );
+               subframe->FillRectangle( subframe,
+                                        0, drect.y + drect.h,
+                                        screen_width, drect.y );
+               subframe->FillRectangle( subframe,
+                                        0, drect.y,
+                                        drect.x, drect.h );
+               subframe->FillRectangle( subframe,
+                                        drect.x + drect.w, drect.y,
+                                        drect.x, drect.h );
+          }
      }
 
-     vo_draw_text( screen_width, screen_height, draw_alpha );
+     if (use_crtc2) {
+          /* Flip BES */
+          if (use_bes)
+               frame->Flip( frame, NULL, 0 );
 
-     subframe->Flip( subframe, NULL, DSFLIP_WAITFORSYNC );
+          /* Blit from BES/temp to CRTC2 */
+          c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX );
+          if (stretch)
+               c2frame->StretchBlit( c2frame, frame, NULL, &drect );
+          else
+               c2frame->Blit( c2frame, frame, NULL, drect.x, drect.y );
+     }
+
+     vo_draw_text( sub_width, sub_height, draw_alpha );
+
+     if (use_spic)
+          subframe->Flip( subframe, NULL, 0 );
 }
 
 static void
 flip_page( void )
 {
-     /* Flip is done by draw_osd() when only BES is used */
-     if (!use_crtc2)
-          return;
-
-     if (use_bes)
+     if (!use_crtc2) {
           /* Flip BES */
-          frame->Flip( frame, NULL, 0 );
+          frame->Flip( frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 0 );
+     } else {
+          /* Flip CRTC2 */
+          c2frame->Flip( c2frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 0 );
+     }
 
-     /* Blit from BES/temp to CRTC2 */
-     c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX );
-     if (stretch)
-          c2frame->StretchBlit( c2frame, frame, NULL, &drect );
-     else
-          c2frame->Blit( c2frame, frame, NULL, drect.x, drect.y );
-
-     if (use_spic)
-          /* Flip CRTC2 */
-          c2frame->Flip( c2frame, NULL, DSFLIP_WAITFORSYNC );
+     current_buf = 0;
 }
 
 static void
@@ -765,7 +673,10 @@
      buffer->Release( buffer );
      keyboard->Release( keyboard );
 
-     frame->Release( frame );
+     while (num_bufs--) {
+          frame = bufs[num_bufs];
+          frame->Release( frame );
+     }
      if (use_bes) {
           bes->SetOpacity( bes, 0 );
           bes->Release( bes );
@@ -789,9 +700,101 @@
       */
 }
 
+static uint32_t
+get_image( mp_image_t *mpi )
+{
+     void *dst;
+     int pitch;
+
+     if (use_bes &&
+         (mpi->type == MP_IMGTYPE_STATIC ||
+          mpi->flags & MP_IMGFLAG_READABLE))
+          return VO_FALSE;
+
+     if (mpi->flags & MP_IMGFLAG_READABLE &&
+         (mpi->type == MP_IMGTYPE_IPB || mpi->type == MP_IMGTYPE_IP)) {
+          int buf = current_buf;
+
+          if (num_bufs < 2)
+               return VO_FALSE;
+
+          current_ip_buf ^= 1;
+
+          if (mpi->type == MP_IMGTYPE_IPB && num_bufs < 3 && current_ip_buf)
+               return VO_FALSE;
+
+          buf = current_ip_buf;
+
+          if (mpi->type == MP_IMGTYPE_IPB)
+               buf++;
+
+          current_buf = buf;
+          frame = bufs[current_buf];
+     }
+
+     if (frame->Lock( frame, DSLF_WRITE | (mpi->flags & MP_IMGFLAG_READABLE ? DSLF_READ : 0),
+                      &dst, &pitch ) != DFB_OK)
+          return VO_FALSE;
+
+     if ((mpi->width == pitch) ||
+         (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))) {
+
+          mpi->planes[0] = dst;
+          mpi->width     = in_width;
+          mpi->stride[0] = pitch;
+
+          if (mpi->flags & MP_IMGFLAG_PLANAR) {
+               mpi->stride[1] = mpi->stride[2] = pitch / 2;
+
+               if (mpi->flags & MP_IMGFLAG_SWAPPED) {
+                    mpi->planes[1] = dst + in_height * pitch;
+                    mpi->planes[2] = mpi->planes[1] + in_height * pitch / 4;
+               } else {
+                    mpi->planes[2] = dst + in_height * pitch;
+                    mpi->planes[1] = mpi->planes[2] + in_height * pitch / 4;
+               }
+          }
+
+          mpi->flags |= MP_IMGFLAG_DIRECT;
+
+          return VO_TRUE;
+     }
+
+     frame->Unlock( frame );
+
+     return VO_FALSE;
+}
+
+
+
+static uint32_t
+draw_image( mp_image_t *mpi )
+{
+     if (mpi->flags & (MP_IMGFLAG_DIRECT | MP_IMGFLAG_DRAW_CALLBACK))
+          return VO_TRUE;
+
+     if (mpi->flags & MP_IMGFLAG_PLANAR)
+          return draw_slice( mpi->planes, mpi->stride,
+                             mpi->w, mpi->h, 0, 0 );
+     else {
+          void *dst;
+          int pitch;
+
+          if (frame->Lock( frame, DSLF_WRITE, &dst, &pitch ) != DFB_OK)
+               return VO_FALSE;
+          memcpy_pic( dst, mpi->planes[0],
+                      mpi->w * (mpi->bpp / 8), mpi->h,
+                      pitch, mpi->stride[0] );
+          frame->Unlock( frame );
+
+          return VO_TRUE;
+     }
+}
+
 static int
-directfb_set_video_eq( char *data, int value )
+set_equalizer( char *data, int value )
 {
+     DFBResult res;
      DFBColorAdjustment ca;
      float factor = (float) 0xffff / 200.0;
 
@@ -816,27 +819,32 @@
 
      /* Prefer CRTC2 over BES */
      if (use_crtc2)
-          crtc2->SetColorAdjustment( crtc2, &ca );
-     else if (use_bes)
-          bes->SetColorAdjustment( bes, &ca );
+          res = crtc2->SetColorAdjustment( crtc2, &ca );
+     else
+          res = bes->SetColorAdjustment( bes, &ca );
 
-     return 0;
+     if (res != DFB_OK)
+          return VO_FALSE;
+
+     return VO_TRUE;
 }
 
 static int
-directfb_get_video_eq( char *data, int *value )
+get_equalizer( char *data, int *value )
 {
+     DFBResult res;
      DFBColorAdjustment ca;
      float factor = 200.0 / (float) 0xffff;
 
      /* Prefer CRTC2 over BES */
      if (use_crtc2)
-          crtc2->GetColorAdjustment( crtc2, &ca );
-     else if (use_bes)
-          bes->GetColorAdjustment( bes, &ca );
+          res = crtc2->GetColorAdjustment( crtc2, &ca );
      else
-          return 0;
+          res = bes->GetColorAdjustment( bes, &ca );
 
+     if (res != DFB_OK)
+          return VO_FALSE;
+     
      if (!strcasecmp( data, "brightness" ) &&
          (ca.flags & DCAF_BRIGHTNESS))
           *value = (ca.brightness - 0x8000) * factor;
@@ -850,7 +858,7 @@
          (ca.flags & DCAF_SATURATION))
           *value = (ca.saturation - 0x8000) * factor;
 
-     return 0;
+     return VO_TRUE;
 }
 
 static uint32_t
@@ -859,6 +867,13 @@
      switch (request) {
      case VOCTRL_QUERY_FORMAT:
 	  return query_format( *((uint32_t *) data) );
+
+     case VOCTRL_GET_IMAGE:
+          return get_image( data );
+
+     case VOCTRL_DRAW_IMAGE:
+          return draw_image( data );
+
      case VOCTRL_SET_EQUALIZER:
           {
                va_list ap;
@@ -868,10 +883,7 @@
                value = va_arg( ap, int );
                va_end( ap );
 
-               if (directfb_set_video_eq( data, value ))
-                    return VO_FALSE;
-
-               return VO_TRUE;
+               return set_equalizer( data, value );
           }
      case VOCTRL_GET_EQUALIZER:
           {
@@ -882,10 +894,7 @@
                value = va_arg( ap, int* );
                va_end( ap );
 
-               if (directfb_get_video_eq( data, value ))
-                    return VO_FALSE;
-
-               return VO_TRUE;
+               return get_equalizer( data, value );
           }
      }