Example #1
0
DFBResult uc_ovl_update(UcDriverData* ucdrv,
                        UcOverlayData* ucovl,
                        int action,
                        CoreSurface* surface)
{
     int sw, sh, sp, sfmt;   // Source width, height, pitch and format
     int dx, dy;             // Destination position
     int dw, dh;             // Destination width and height
     VideoMode *videomode;
     DFBRectangle scr;       // Screen size

     bool write_buffers = false;
     bool write_settings = false;

     volatile u8* vio = ucdrv->hwregs;

     u32 win_start, win_end;     // Overlay register settings
     u32 zoom, mini;
     u32 dcount, falign, qwpitch;
     u32 y_start, u_start, v_start;
     u32 v_ctrl, fifo_ctrl;

     int offset = surface->front_buffer->video.offset;


     if (!ucovl->v1.isenabled) return DFB_OK;

     qwpitch = 0;

     // Get screen size
     videomode = dfb_system_current_mode();
     scr.w = videomode ? videomode->xres : 720;
     scr.h = videomode ? videomode->yres : 576;
     scr.x = 0;
     scr.y = 0;

     if (ucovl->scrwidth != scr.w) {
          // FIXME: fix uc_ovl_setup_fifo()
          //    uc_ovl_setup_fifo(ucovl, scr.w);
          action |= UC_OVL_CHANGE;
     }

     D_ASSERT(surface);

     sw = surface->config.size.w;
     sh = surface->config.size.h;
     sp = surface->front_buffer->video.pitch;
     sfmt = surface->config.format;

     if (ucovl->deinterlace) {
          /*if (ucovl->field)
               offset += sp;*/

          sh /= 2;
          //sp *= 2;
     }

     if (action & UC_OVL_CHANGE) {

          if ((sw > 4096) || (sh > 4096) ||
              (sw < 32) || (sh < 1) || (sp > 0x1fff)) {
               D_DEBUG("Layer surface size is out of bounds.");
               return DFB_INVAREA;
          }

          dx = ucovl->v1.win.x;
          dy = ucovl->v1.win.y;
          dw = ucovl->v1.win.w;
          dh = ucovl->v1.win.h;

          // Get image format, FIFO size, etc.

          uc_ovl_map_v1_control(sfmt, sw, ucovl->hwrev, ucovl->extfifo_on,
                                &v_ctrl, &fifo_ctrl);

          if (ucovl->deinterlace) {
               v_ctrl |= /*V1_BOB_ENABLE |*/ V1_FRAME_BASE;
          }

          // Get layer window.
          // The parts that fall outside the screen are clipped.

          uc_ovl_map_window(scr.w, scr.h, &(ucovl->v1.win), sw, sh,
                            &win_start, &win_end, &ucovl->v1.ox, &ucovl->v1.oy);

          // Get scaling and data-fetch parameters

          // Note: the *_map_?zoom() functions return false if the scaling
          // is out of bounds. We don't act on it for now, because it only
          // makes the display look strange.

          zoom = 0;
          mini = 0;

          uc_ovl_map_vzoom(sh, dh, &zoom, &mini);
          uc_ovl_map_hzoom(sw, dw, &zoom, &mini, &falign, &dcount);
          qwpitch = uc_ovl_map_qwpitch(falign, sfmt, sw);

          write_settings = true;
     }

     if (action & (UC_OVL_FIELD | UC_OVL_FLIP | UC_OVL_CHANGE)) {
          int field = 0;
          // Update the buffer pointers

          if (ucovl->deinterlace) {
               field = ucovl->field;
          }

          uc_ovl_map_buffer(sfmt, offset,
                            ucovl->v1.ox, ucovl->v1.oy, sw, surface->config.size.h, sp, 0/*field*/, &y_start,
                            &u_start, &v_start);

          if (field) {
               y_start |= 0x08000000;
          }

          write_buffers = true;
     }

     // Write to the hardware

/*    if (write_settings || write_buffers)
        uc_ovl_vcmd_wait(vio);*/

     if (write_settings) {

          VIDEO_OUT(vio, V1_CONTROL, v_ctrl);
          VIDEO_OUT(vio, V_FIFO_CONTROL, fifo_ctrl);

          VIDEO_OUT(vio, V1_WIN_START_Y, win_start);
          VIDEO_OUT(vio, V1_WIN_END_Y, win_end);

          VIDEO_OUT(vio, V1_SOURCE_HEIGHT, (sh << 16) | dcount);
          VIDEO_OUT(vio, V12_QWORD_PER_LINE, qwpitch);
          VIDEO_OUT(vio, V1_STRIDE, sp | ((sp >> 1) << 16));

          VIDEO_OUT(vio, V1_MINI_CONTROL, mini);
          VIDEO_OUT(vio, V1_ZOOM_CONTROL, zoom);
     }

     if (write_buffers) {

          VIDEO_OUT(vio, V1_STARTADDR_0, y_start);
          VIDEO_OUT(vio, V1_STARTADDR_CB0, u_start);
          VIDEO_OUT(vio, V1_STARTADDR_CR0, v_start);
     }

     if (write_settings || write_buffers) {
          VIDEO_OUT(vio, V_COMPOSE_MODE, V1_COMMAND_FIRE);
     }

     return DFB_OK;
}
Example #2
0
static DFBResult
uc_ovl_flip_region( CoreLayer             *layer,
                    void                  *driver_data,
                    void                  *layer_data,
                    void                  *region_data,
                    CoreSurface           *surface,
                    DFBSurfaceFlipFlags    flags,
                    CoreSurfaceBufferLock *lock )
{
    //printf("Entering %s ... \n", __PRETTY_FUNCTION__);

    UcDriverData*  ucdrv = (UcDriverData*) driver_data;
    UcOverlayData* ucovl = (UcOverlayData*) layer_data;
    DFBResult    ret;
    FBDev *dfb_fbdev = dfb_system_data();

    dfb_surface_flip(surface, false);

    ucovl->field = 0;
    ucovl->lock = lock;

    if (ucdrv->canfliponvsync)
    {
        if (ucovl->config.options & DLOP_FIELD_PARITY)
        {
            struct fb_flip flip;
            int field_option;

            field_option = VIAFB_WAIT_FLIP; // ensure last pending flip complete
            ioctl(dfb_fbdev->fd, FBIO_WAITFORVSYNC, &field_option);

            flip.device = VIAFB_FLIP_V1;
            flip.field = ucovl->config.parity;
            flip.count = 0; // until we implement this

            uc_ovl_map_buffer(surface->config.format,
                lock->offset,
                ucovl->v1.ox, ucovl->v1.oy, surface->config.size.w, surface->config.size.h,
                lock->pitch, 0,
                &flip.offset[0], &flip.offset[1], &flip.offset[2]);

            ioctl(dfb_fbdev->fd, FBIO_FLIPONVSYNC, &flip);
        }
        else
        {
            ret = uc_ovl_update(ucdrv, ucovl, UC_OVL_FLIP, surface, lock);
            if (ret)
                return ret;
        }
    }
    else
    {
        if (ucovl->config.options & DLOP_FIELD_PARITY)
        {
            int field_option;
        
            if (ucovl->config.parity == 0)  // top field first?
                field_option = VIAFB_WAIT_BOTTOMFIELD;
            else
                field_option = VIAFB_WAIT_TOPFIELD;
            ioctl(dfb_fbdev->fd, FBIO_WAITFORVSYNC, &field_option);
            // that actually waits for VBLANK so we need a further delay
            // to be sure the field has started and that the flip will
            // take effect on the next field
            usleep(2500);
        }
    
        ret = uc_ovl_update(ucdrv, ucovl, UC_OVL_FLIP, surface, lock);
        if (ret)
            return ret;
    }

    if (flags & DSFLIP_WAIT)
        dfb_layer_wait_vsync(layer);

    return DFB_OK;
}