Ticket #3486: 3486-v1.patch

File 3486-v1.patch, 11.9 KB (added by danielk, 17 years ago)
  • libs/libmythtv/videoout_ivtv.h

     
    11#ifndef VIDEOOUT_IVTV_H_
    22#define VIDEOOUT_IVTV_H_
    33
     4// Linux system headers
     5#include <linux/fb.h>
     6
     7// Qt headers
    48#include <qstring.h>
    59#include <qmutex.h>
    6 #include <cassert>
    710
     11// MythTV headers
    812#include "videooutbase.h"
    913
     14#ifdef USING_IVTV_HEADER
     15#include <linux/ivtv.h>
     16#else
     17#include "ivtv_myth.h"
     18#endif
     19
    1020class NuppelVideoPlayer;
    1121
    1222class VideoOutputIvtv: public VideoOutput
     
    108118    bool last_normal;
    109119    int last_mask;
    110120    eAlphaState alphaState;
     121
     122    bool old_ioctl;
     123    struct fb_var_screeninfo ivtvfb_var;
     124    struct fb_var_screeninfo ivtvfb_var_old;
     125#ifdef IVTVFB_IOCTL_GET_COLORKEY
     126    struct ivtvfb_ioctl_colorkey ivtvfb_colorkey;
     127    struct ivtvfb_ioctl_colorkey ivtvfb_colorkey_old;
     128#endif
    111129};
    112130
    113131#endif
  • libs/libmythtv/videoout_ivtv.cpp

     
    7373
    7474    last_normal(true),        last_mask(0x2),
    7575
    76     alphaState(kAlpha_Solid)
     76    alphaState(kAlpha_Solid), old_ioctl(true)
    7777{
    7878}
    7979
     
    103103
    104104    VERBOSE(VB_PLAYBACK, LOC + "ClearOSD");
    105105
    106     struct ivtv_osd_coords osdcoords;
    107     bzero(&osdcoords, sizeof(osdcoords));
     106    bzero(osdbuf_aligned, osdbufsize);
    108107
    109     if (ioctl(fbfd, IVTVFB_IOCTL_GET_ACTIVE_BUFFER, &osdcoords) < 0)
    110     {
    111         VERBOSE(VB_IMPORTANT, LOC_ERR +
    112                 "Failed to get active buffer for ClearOSD()" + ENO);
    113     }
    114108    struct ivtvfb_ioctl_dma_host_to_ivtv_args prep;
    115109    bzero(&prep, sizeof(prep));
    116110
    117111    prep.source = osdbuf_aligned;
    118112    prep.dest_offset = 0;
    119     prep.count = osdcoords.max_offset;
    120113
    121     bzero(osdbuf_aligned, osdbufsize);
     114    if (old_ioctl == true)
     115    {
     116        struct ivtv_osd_coords osdcoords;
     117        bzero(&osdcoords, sizeof(osdcoords));
    122118
     119        if (ioctl(fbfd, IVTVFB_IOCTL_GET_ACTIVE_BUFFER, &osdcoords) < 0)
     120        {
     121            VERBOSE(VB_IMPORTANT, LOC_ERR +
     122                    "Failed to get active buffer for ClearOSD()" + ENO);
     123        }
     124        prep.count = osdcoords.max_offset;
     125    }
     126    else
     127        prep.count = ivtvfb_var.xres_virtual * ivtvfb_var.yres * (ivtvfb_var.bits_per_pixel / 8);
     128
     129    if (old_ioctl == false)
     130        ioctl(fbfd, FBIOPAN_DISPLAY, &ivtvfb_var);
     131
    123132    if (ioctl(fbfd, IVTVFB_IOCTL_PREP_FRAME, &prep) < 0)
    124133        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to prepare frame" + ENO);
    125134}
     
    140149        VERBOSE(VB_PLAYBACK, LOC + "SetAlpha(Embedded)");
    141150#endif
    142151
    143     alphaState = newAlphaState;
    144 
    145152    struct ivtvfb_ioctl_state_info fbstate;
    146153    bzero(&fbstate, sizeof(fbstate));
    147154    if (ioctl(fbfd, IVTVFB_IOCTL_GET_STATE, &fbstate) < 0)
    148155        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to query alpha state" + ENO);
    149156
    150     if (alphaState == kAlpha_Local)
     157    if (newAlphaState == kAlpha_Local)
    151158    {
    152159        fbstate.status &= ~IVTVFB_STATUS_GLOBAL_ALPHA;
    153160        fbstate.status |= IVTVFB_STATUS_LOCAL_ALPHA;
     
    158165        fbstate.status &= ~IVTVFB_STATUS_LOCAL_ALPHA;
    159166    }
    160167
    161     if (alphaState == kAlpha_Solid)
     168    if (newAlphaState == kAlpha_Solid)
    162169        fbstate.alpha = 255;
    163     else if (alphaState == kAlpha_Clear)
     170    else if (newAlphaState == kAlpha_Clear)
    164171        fbstate.alpha = 0;
    165     else if (alphaState == kAlpha_Embedded)
     172    else if (newAlphaState == kAlpha_Embedded)
    166173        fbstate.alpha = gContext->GetNumSetting("PVR350EPGAlphaValue", 164);
    167174
     175    // If using the new ioctl we need to check the fb mode
     176    if (old_ioctl == false)
     177    {
     178        struct fb_var_screeninfo *tmpfb_var = NULL;
     179
     180        // If EPG switched on, select old fb mode
     181        if (newAlphaState == kAlpha_Embedded)
     182            tmpfb_var = &ivtvfb_var_old;
     183        // If EPG switched off, select new fb mode
     184        else if (newAlphaState != kAlpha_Embedded && alphaState == kAlpha_Embedded)
     185            tmpfb_var = &ivtvfb_var;
     186
     187        // Change fb mode if required
     188        if (tmpfb_var)
     189        {
     190            if ((ivtvfb_var_old.bits_per_pixel != 32) &&
     191                 (ivtvfb_var_old.bits_per_pixel != 8))
     192            {
     193                // Hide osd during mode change
     194#ifdef FB_BLANK_NORMAL
     195                ioctl(fbfd, FBIOBLANK, FB_BLANK_NORMAL);
     196#else
     197                ioctl(fbfd, FBIOBLANK, VESA_VSYNC_SUSPEND);
     198#endif
     199                tmpfb_var->activate = FB_ACTIVATE_NOW;
     200                if (ioctl(fbfd, FBIOPUT_VSCREENINFO, tmpfb_var) < 0)
     201                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to switch framebuffer settings for EPG" + ENO);
     202
     203                // Restore osd
     204#ifdef FB_BLANK_UNBLANK
     205                ioctl(fbfd, FBIOBLANK, FB_BLANK_UNBLANK);
     206#else
     207                ioctl(fbfd, FBIOBLANK, VESA_NO_BLANKING);
     208#endif
     209            }
     210            // Reset display pan
     211            ivtvfb_var.xoffset = 0;
     212            ivtvfb_var.yoffset = 0;
     213            ioctl(fbfd, FBIOPAN_DISPLAY, &ivtvfb_var);
     214        }
     215    }
     216
    168217    if (ioctl(fbfd, IVTVFB_IOCTL_SET_STATE, &fbstate) < 0)
    169218        VERBOSE(VB_IMPORTANT, LOC_ERR +
    170219                "Failed to set ivtv alpha values." + ENO);
     220
     221    alphaState = newAlphaState;
    171222}
    172223
    173224void VideoOutputIvtv::InputChanged(int width, int height, float aspect,
     
    244295        bzero(&igfb, sizeof(igfb));
    245296
    246297        if (ioctl(fbfd, IVTVFB_IOCTL_GET_FRAME_BUFFER, &igfb) < 0)
    247             VERBOSE(VB_IMPORTANT, LOC_ERR + "Getting frame buffer" + ENO);
     298        {
     299            if (errno == EINVAL)
     300            {
     301                struct fb_fix_screeninfo ivtvfb_fix;
     302                if (ioctl(fbfd, FBIOGET_FSCREENINFO, &ivtvfb_fix) < 0)
     303                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Getting frame buffer" + ENO);
     304                else
     305                {
     306                    old_ioctl = false;
     307                    ioctl(fbfd, FBIOGET_VSCREENINFO, &ivtvfb_var_old);
     308                }
     309            }
     310            else
     311                VERBOSE(VB_IMPORTANT, LOC_ERR + "Getting frame buffer" + ENO);
     312        }
    248313
    249         stride = igfb.sizex * 4;
    250 
    251314        long pagesize = sysconf(_SC_PAGE_SIZE);
    252315        long pagemask = ~(pagesize-1);
    253316        osdbuffer = new char[osdbufsize + pagesize];
     
    256319
    257320        bzero(osdbuf_aligned, osdbufsize);
    258321
    259         ClearOSD();
     322        if (old_ioctl == true)
     323        {
     324            struct ivtv_osd_coords osdcoords;
     325            stride = igfb.sizex * 4;
     326            bzero(&osdcoords, sizeof(osdcoords));
     327            osdcoords.lines = video_dim.height();
     328            osdcoords.offset = 0;
     329            osdcoords.pixel_stride = video_dim.width() * 2;
     330            if (ioctl(fbfd, IVTVFB_IOCTL_SET_ACTIVE_BUFFER, &osdcoords) < 0)
     331                VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting active buffer" + ENO);
     332        }
     333        else
     334        {
     335            bzero (&ivtvfb_var, sizeof(ivtvfb_var));
    260336
    261         struct ivtv_osd_coords osdcoords;
    262         bzero(&osdcoords, sizeof(osdcoords));
    263         osdcoords.lines = video_dim.height();
    264         osdcoords.offset = 0;
    265         osdcoords.pixel_stride = video_dim.width() * 2;
     337            // Switch dimensions to match the framebuffer
     338            video_dim = QSize(ivtvfb_var_old.xres, ivtvfb_var_old.yres);
    266339
    267         if (ioctl(fbfd, IVTVFB_IOCTL_SET_ACTIVE_BUFFER, &osdcoords) < 0)
    268             VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting active buffer" + ENO);
     340            memcpy(&ivtvfb_var,&ivtvfb_var_old,sizeof ivtvfb_var);
    269341
     342            // The OSD only supports 32bpp, so only change mode if needed
     343            if (ivtvfb_var_old.bits_per_pixel != 32)
     344            {
     345                ivtvfb_var.xres_virtual = ivtvfb_var.xres;
     346                ivtvfb_var.yres_virtual = ivtvfb_var.yres;
     347                ivtvfb_var.xoffset = 0;
     348                ivtvfb_var.yoffset = 0;
     349                ivtvfb_var.bits_per_pixel = 32;
     350                ivtvfb_var.nonstd = 0;
     351                ivtvfb_var.activate = FB_ACTIVATE_NOW;
     352
     353                if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &ivtvfb_var) < 0)
     354                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting frame buffer" + ENO);
     355            }
     356            else
     357            {
     358                ivtvfb_var.xoffset = 0;
     359                ivtvfb_var.yoffset = 0;
     360                ioctl(fbfd, FBIOPAN_DISPLAY, &ivtvfb_var);
     361            }
     362
     363            stride = ivtvfb_var.xres_virtual * 4;
     364        }
     365
     366#ifdef IVTVFB_IOCTL_GET_COLORKEY
     367        // Setup color-key. This helps when X isn't running on the PVR350
     368        ioctl(fbfd,IVTVFB_IOCTL_GET_COLORKEY, &ivtvfb_colorkey_old);
     369        ivtvfb_colorkey.state = 1;
     370        ivtvfb_colorkey.colorKey = 0x00010001;
     371        ioctl(fbfd,IVTVFB_IOCTL_SET_COLORKEY, &ivtvfb_colorkey);
     372#endif
     373        ClearOSD();
     374
    270375        SetAlpha(kAlpha_Clear);
    271376    }
    272377
     
    286391    {
    287392        Stop(true /* hide */);
    288393
     394        if (old_ioctl == false)
     395        {
     396            ivtvfb_var_old.activate = FB_ACTIVATE_NOW;
     397
     398            if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &ivtvfb_var_old) < 0)
     399                VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to restore framebuffer settings" + ENO);
     400        }
     401
     402#ifdef IVTVFB_IOCTL_GET_COLORKEY
     403        // Restore old colorkey
     404        ioctl(fbfd,IVTVFB_IOCTL_SET_COLORKEY, &ivtvfb_colorkey_old);
     405#endif
    289406        close(videofd);
    290407        videofd = -1;
    291408    }
     
    450567
    451568    VideoFrame tmpframe;
    452569    init(&tmpframe, FMT_ARGB32, (unsigned char *)osdbuf_aligned,
    453          stride, video_dim.height(), 32, 4 * stride * video_dim.height());
     570         stride, video_dim.height(), 32, stride * video_dim.height());
    454571
    455572    OSDSurface *surface = NULL;
    456573    if (osd)
     
    506623    pipon = (bool) pipPlayer;
    507624
    508625    // If there is an OSD, make sure we draw OSD surface
    509     lastcleared &= !osd;
     626    lastcleared &= !osdon;
    510627
    511 #if 0
    512 // These optimizations have been disabled until someone with a real PVR-350
    513 // setup can test them Feb 7th, 2006 -- dtk
    514628    // If nothing on OSD surface, just set the alpha to zero
    515     if (lastcleared && drawanyway)
     629    if (!osdon && !pipon)
    516630    {
     631        if (lastcleared == true)
     632            return;
     633
     634        lastcleared = true;
    517635        SetAlpha(kAlpha_Clear);
    518         return;
     636#ifdef IVTVFB_IOCTL_GET_COLORKEY
     637#ifdef WORDS_BIGENDIAN
     638        wmemset((wchar_t *)osdbuf_aligned, 0x01000100, osdbufsize/4);
     639#else
     640        wmemset((wchar_t *)osdbuf_aligned, 0x00010001, osdbufsize/4);
     641#endif
     642#endif
    519643    }
    520644
    521645    // If there has been no OSD change and no draw has been forced we're done
    522646    if (ret <= 0 && !drawanyway)
    523647        return;
    524 #endif
    525648
    526649    // The OSD surface needs to be updated...
    527650    struct ivtvfb_ioctl_dma_host_to_ivtv_args prep;
     
    529652    prep.source = osdbuf_aligned;
    530653    prep.count  = video_dim.height() * stride;
    531654
     655    // This shouldn't be here. OSD should be rendered correctly to start with
     656#ifdef WORDS_BIGENDIAN
     657    int b_index, i_index;
     658    unsigned int *osd_int = (unsigned int *)osdbuf_aligned;
     659    if (lastcleared != true)
     660    {
     661        for (b_index = 0, i_index = 0; b_index < prep.count; b_index += 4, i_index ++)
     662        {
     663            if (osd_int[i_index])
     664            {
     665                osd_int[i_index] =
     666                        ((unsigned char)osdbuf_aligned[b_index+0]) |
     667                        ((unsigned char)osdbuf_aligned[b_index+1] << 8) |
     668                        ((unsigned char)osdbuf_aligned[b_index+2] << 16) |
     669                        ((unsigned char)osdbuf_aligned[b_index+3] << 24);
     670            }
     671        }
     672    }
     673#endif
     674
     675    if (old_ioctl == false)
     676        ioctl(fbfd, FBIOPAN_DISPLAY, &ivtvfb_var);
     677
    532678    if (ioctl(fbfd, IVTVFB_IOCTL_PREP_FRAME, &prep) < 0)
    533679        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to process frame" + ENO);
    534680
    535     SetAlpha(kAlpha_Local);
     681    if (lastcleared != true)
     682        SetAlpha(kAlpha_Local);
    536683}
    537684
    538685/** \fn VideoOutputIvtv::Start(int,int)