Ticket #5324: mythtv-vid-19.diff

File mythtv-vid-19.diff, 44.0 KB (added by mark.kendall@…, 16 years ago)

Rewrite of deinterlacing code. Combine YUV2RGB and deinterlacing. Use 3 different fragment programs for progressive, top field and bottom field. Now properly deinterlaces luma and chroma channels and much faster. FrameBufferObjects? no longer a requirement.

  • libs/libmythtv/openglvideo.cpp

    diff -ur -X excl mythtv-vid-18a/libs/libmythtv/openglvideo.cpp mythtv-vid-19/libs/libmythtv/openglvideo.cpp
    old new  
    2626class OpenGLFilter
    2727{
    2828    public:
    29         GLuint         fragmentProgram;
     29        vector<GLuint> fragmentPrograms;
    3030        uint           numInputs;
    31         bool           rotateFrameBuffers;
    3231        vector<GLuint> frameBuffers;
    3332        vector<GLuint> frameBufferTextures;
    3433        DisplayBuffer  outputBuffer;
     
    4039    masterViewportSize(0,0),  display_visible_rect(0,0,0,0),
    4140    display_video_rect(0,0,0,0), video_rect(0,0,0,0),
    4241    frameBufferRect(0,0,0,0), softwareDeinterlacer(QString::null),
    43     hardwareDeinterlacing(false),
     42    hardwareDeinterlacer(QString::null), hardwareDeinterlacing(false),
    4443    useColourControl(false),  viewportControl(false),
    4544    inputTextureSize(0,0),    currentFrameNum(0),
    4645    inputUpdated(false),     
     
    6362{
    6463    ShutDownYUV2RGB();
    6564
    66     for (uint i = 0; i < inputTextures.size(); i++)
    67         gl_context->DeleteTexture(inputTextures[i]);
    68     inputTextures.clear();
     65    DeleteTextures(&inputTextures);
     66    DeleteTextures(&referenceTextures);
    6967
    7068    if (!filters.empty())
    7169    {
     
    190188    return true;
    191189}
    192190
    193 OpenGLFilterType OpenGLVideo::GetDeintFilter(void) const
    194 {
    195     if (filters.count(kGLFilterKernelDeint))
    196         return kGLFilterKernelDeint;
    197     if (filters.count(kGLFilterLinearBlendDeint))
    198         return kGLFilterLinearBlendDeint;
    199     if (filters.count(kGLFilterOneFieldDeint))
    200         return kGLFilterOneFieldDeint;
    201     if (filters.count(kGLFilterBobDeintDFR))
    202         return kGLFilterBobDeintDFR;
    203     if (filters.count(kGLFilterOneFieldDeintDFR))
    204         return kGLFilterOneFieldDeintDFR;
    205     if (filters.count(kGLFilterLinearBlendDeintDFR))
    206         return kGLFilterLinearBlendDeintDFR;
    207     if (filters.count(kGLFilterKernelDeintDFR))
    208         return kGLFilterKernelDeintDFR;
    209     if (filters.count(kGLFilterFieldOrderDFR))
    210         return kGLFilterFieldOrderDFR;
    211 
    212     return kGLFilterNone;
    213 }
    214 
    215191bool OpenGLVideo::OptimiseFilters(void)
    216192{
    217     // if video height does not match display rect height, add resize stage
    218     // to preserve field information N.B. assumes interlaced
    219     // if video rectangle is smaller than display rectangle, add resize stage
    220     // to improve performance
    221 
    222     bool needResize =  ((video_dim.height() != display_video_rect.height()) ||
    223                         (video_dim.width()  <  display_video_rect.width()));
    224     if (needResize && !filters.count(kGLFilterResize) &&
    225         !(AddFilter(kGLFilterResize)))
    226     {
    227         return false;
    228     }
     193    bool resize =  ((video_dim.height() < display_video_rect.height()) ||
     194                    (video_dim.width()  <  display_video_rect.width()));
     195
     196    if (resize && !filters.count(kGLFilterResize))
     197        AddFilter(kGLFilterResize);
     198    else if (!resize && filters.count(kGLFilterResize) &&
     199             !filters.count(kGLFilterYUV2RGBA))
     200        RemoveFilter(kGLFilterResize);
    229201
    230202    glfilt_map_t::reverse_iterator it;
    231203
     
    233205    // and link filters
    234206    uint buffers_needed = 1;
    235207    bool last_filter    = true;
    236     bool needtorotate   = false;
    237208    for (it = filters.rbegin(); it != filters.rend(); it++)
    238209    {
    239         it->second->outputBuffer = kFrameBufferObject;
    240         it->second->rotateFrameBuffers = needtorotate;
    241210        if (!last_filter)
    242211        {
     212            it->second->outputBuffer = kFrameBufferObject;
    243213            uint buffers_have = it->second->frameBuffers.size();
    244214            int buffers_diff = buffers_needed - buffers_have;
    245215            if (buffers_diff > 0)
     
    278248            it->second->outputBuffer = kDefaultBuffer;
    279249            last_filter = false;
    280250        }
    281 
    282251        buffers_needed = it->second->numInputs;
    283         needtorotate = (it->first == kGLFilterKernelDeint ||
    284                         it->first == kGLFilterLinearBlendDeint ||
    285                         it->first == kGLFilterOneFieldDeintDFR ||
    286                         it->first == kGLFilterLinearBlendDeintDFR ||
    287                         it->first == kGLFilterKernelDeintDFR ||
    288                         it->first == kGLFilterFieldOrderDFR);
    289 
    290252    }
    291253
    292     bool deinterlacing = hardwareDeinterlacing;
    293     hardwareDeinterlacing = true;
    294 
    295     SetDeinterlacing(false);
    296     if (deinterlacing)
    297         SetDeinterlacing(deinterlacing);
     254    SetFiltering();
    298255
    299256    return true;
    300257}
     
    304261{
    305262    // filter settings included for performance only
    306263    // no (obvious) quality improvement over GL_LINEAR throughout
    307     if (filters.empty())
    308         return;
    309 
    310     if (filters.size() == 1)
     264    if (filters.empty() || filters.size() == 1)
    311265    {
    312266        SetTextureFilters(&inputTextures, GL_LINEAR, GL_CLAMP_TO_EDGE);
    313267        return;
    314268    }
    315269
    316270    SetTextureFilters(&inputTextures, GL_NEAREST, GL_CLAMP_TO_EDGE);
    317     vector<GLuint> textures;
    318     glfilt_map_t::iterator it;
    319     for (it = filters.begin(); it != filters.end(); it++)
    320         SetTextureFilters(&(it->second->frameBufferTextures),
    321                           GL_NEAREST, GL_CLAMP_TO_EDGE);
    322271
    323     // resize or last active (ie don't need resize) need GL_LINEAR
    324272    glfilt_map_t::reverse_iterator rit;
    325     bool next = false;
    326     bool resize = filters.count(kGLFilterResize);
     273    int last_filter = 0;
     274
    327275    for (rit = filters.rbegin(); rit != filters.rend(); rit++)
    328276    {
    329         if (next && (rit->second->outputBuffer != kNoBuffer))
     277        if (last_filter == 1)
    330278        {
    331279            SetTextureFilters(&(rit->second->frameBufferTextures),
    332280                              GL_LINEAR, GL_CLAMP_TO_EDGE);
    333             return;
    334281        }
    335 
    336         if (resize)
     282        else if (last_filter > 1)
    337283        {
    338             next |= ((rit->first == kGLFilterResize) ||
    339                      (rit->second->outputBuffer == kDefaultBuffer));
     284            SetTextureFilters(&(rit->second->frameBufferTextures),
     285                              GL_NEAREST, GL_CLAMP_TO_EDGE);
    340286        }
    341287    }
    342 
    343     SetTextureFilters(&inputTextures, GL_LINEAR, GL_CLAMP_TO_EDGE);
    344288}
    345289
    346290// locking ok
     
    349293    if (filters.count(filter))
    350294        return true;
    351295
     296    bool success = true;
     297
    352298    VERBOSE(VB_PLAYBACK, LOC + QString("Creating %1 filter.")
    353299            .arg(FilterToString(filter)));
    354300
    355301    OpenGLFilter *temp = new OpenGLFilter();
    356302
    357303    temp->numInputs = 1;
    358 
    359     if ((filter == kGLFilterLinearBlendDeint) ||
    360         (filter == kGLFilterKernelDeint) ||
    361         (filter == kGLFilterFieldOrderDFR))
    362     {
    363         temp->numInputs = 2;
    364     }
    365     else if ((filter == kGLFilterOneFieldDeintDFR) ||
    366              (filter == kGLFilterKernelDeintDFR) ||
    367              (filter == kGLFilterLinearBlendDeintDFR))
    368     {
    369         temp->numInputs = 3;
    370     }
    371 
    372304    GLuint program = 0;
     305
    373306    if (filter != kGLFilterNone && filter != kGLFilterResize)
    374307    {
    375308        program = AddFragmentProgram(filter);
    376309        if (!program)
    377             return false;
     310            success = false;
     311        else
     312            temp->fragmentPrograms.push_back(program);
    378313    }
    379314
    380     temp->fragmentProgram    = program;
    381315    temp->outputBuffer       = kDefaultBuffer;
    382     temp->rotateFrameBuffers = false;
    383316
    384317    temp->frameBuffers.clear();
    385318    temp->frameBufferTextures.clear();
    386319
    387320    filters[filter] = temp;
    388321
    389     if (OptimiseFilters())
     322    success &= OptimiseFilters();
     323
     324    if (success)
    390325        return true;
    391326
    392327    RemoveFilter(filter);
     
    400335    if (!filters.count(filter))
    401336        return true;
    402337
    403     VERBOSE(VB_PLAYBACK, QString("Removing %1 filter")
     338    VERBOSE(VB_PLAYBACK, LOC + QString("Removing %1 filter")
    404339            .arg(FilterToString(filter)));
    405340
    406     gl_context->DeleteFragmentProgram(filters[filter]->fragmentProgram);
    407 
    408341    vector<GLuint> temp;
    409342    vector<GLuint>::iterator it;
    410343
     344    temp = filters[filter]->fragmentPrograms;
     345    for (it = temp.begin(); it != temp.end(); it++)
     346        gl_context->DeleteFragmentProgram(*it);
     347    filters[filter]->fragmentPrograms.clear();
     348
    411349    temp = filters[filter]->frameBuffers;
    412350    for (it = temp.begin(); it != temp.end(); it++)
    413351        gl_context->DeleteFrameBuffer(*it);
     352    filters[filter]->frameBuffers.clear();
    414353
    415     temp = filters[filter]->frameBufferTextures;
    416     for (it = temp.begin(); it != temp.end(); it++)
    417         gl_context->DeleteTexture((*(it)));
     354    DeleteTextures(&(filters[filter]->frameBufferTextures));
    418355
    419356    filters.erase(filter);
    420357
     
    422359}
    423360
    424361// locking ok
    425 bool OpenGLVideo::AddDeinterlacer(const QString &filter)
     362void OpenGLVideo::TearDownDeinterlacer(void)
     363{
     364    if (!filters.count(kGLFilterYUV2RGB))
     365        return;
     366
     367    OpenGLFilter *tmp = filters[kGLFilterYUV2RGB];
     368
     369    if (tmp->fragmentPrograms.size() == 3)
     370    {
     371        gl_context->DeleteFragmentProgram(tmp->fragmentPrograms[2]);
     372        tmp->fragmentPrograms.pop_back();
     373    }
     374
     375    if (tmp->fragmentPrograms.size() == 2)
     376    {
     377        gl_context->DeleteFragmentProgram(tmp->fragmentPrograms[1]);
     378        tmp->fragmentPrograms.pop_back();
     379    }
     380           
     381    DeleteTextures(&referenceTextures);
     382}
     383
     384bool OpenGLVideo::AddDeinterlacer(const QString &deinterlacer)
    426385{
    427386    OpenGLContextLocker ctx_lock(gl_context);
    428387
    429     QString current_deinterlacer = GetDeinterlacer();
     388    if (!filters.count(kGLFilterYUV2RGB))
     389        return false;
    430390
    431     if (current_deinterlacer == filter)
     391    if (hardwareDeinterlacer == deinterlacer)
    432392        return true;
    433393
    434     if (!current_deinterlacer.isEmpty())
    435         RemoveFilter(current_deinterlacer);
     394    TearDownDeinterlacer();
    436395
    437     return AddFilter(filter);
     396    bool success = true;
     397
     398    uint ref_size = 2;
     399
     400    if (deinterlacer == "openglbobdeint" ||
     401        deinterlacer == "openglonefield" ||
     402        deinterlacer == "opengldoubleratefieldorder")
     403    {
     404        ref_size = 0;
     405    }
     406
     407    if (ref_size > 0)
     408    {
     409        bool use_pbo = gl_context->IsFeatureSupported(kGLExtPBufObj);
     410
     411        for (; ref_size > 0; ref_size--)
     412        {
     413            GLuint tex = CreateVideoTexture(actual_video_dim, inputTextureSize, use_pbo);
     414            if (tex)
     415            {
     416                referenceTextures.push_back(tex);
     417            }
     418            else
     419            {
     420                success = false;
     421            }
     422        }
     423    }
     424
     425    uint prog1 = AddFragmentProgram(kGLFilterYUV2RGB,
     426                                    deinterlacer, kScan_Interlaced);
     427    uint prog2 = AddFragmentProgram(kGLFilterYUV2RGB,
     428                                    deinterlacer, kScan_Intr2ndField);
     429 
     430    if (prog1 && prog2)
     431    {
     432        filters[kGLFilterYUV2RGB]->fragmentPrograms.push_back(prog1);
     433        filters[kGLFilterYUV2RGB]->fragmentPrograms.push_back(prog2);
     434    }
     435    else
     436    {
     437        success = false;
     438    }
     439
     440    if (success)
     441    {
     442        hardwareDeinterlacer = deinterlacer;
     443        return true;
     444    }
     445
     446    hardwareDeinterlacer = "";
     447    TearDownDeinterlacer();
     448 
     449    return false;
    438450}
    439451
    440452// locking ok
    441 uint OpenGLVideo::AddFragmentProgram(OpenGLFilterType name)
     453uint OpenGLVideo::AddFragmentProgram(OpenGLFilterType name,
     454                                     QString deint, FrameScanType field)
    442455{
    443456    if (!gl_context->IsFeatureSupported(kGLExtFragProg))
    444457    {
     
    446459        return 0;
    447460    }
    448461
    449     QString program = GetProgramString(name);
    450     QString texType = (textureRects) ? "RECT" : "2D";
    451     program.replace("%1", texType);
     462    QString program = GetProgramString(name, deint, field);
    452463
    453464    uint ret;
    454465    if (gl_context->CreateFragmentProgram(program, ret))
    455     {
    456         VERBOSE(VB_PLAYBACK, LOC + QString("Created fragment program %1.")
    457                 .arg(FilterToString(name)));
    458 
    459466        return ret;
    460     }
    461467
    462468    return 0;
    463469}
     
    558564
    559565    if (filters.count(kGLFilterYUV2RGB) && (frame->codec == FMT_YV12))
    560566    {
     567        if (hardwareDeinterlacing)
     568            RotateTextures();
     569
    561570        gl_context->UpdateTexture(inputTextures[0], frame->buf,
    562571                                  frame->offsets, frame->pitches, FMT_YV12,
    563572                                  frame->interlaced_frame && !soft_bob);
     
    692701    if (deinterlacing == hardwareDeinterlacing)
    693702        return;
    694703
    695     OpenGLContextLocker ctx_lock(gl_context);
    696 
    697     VERBOSE(VB_PLAYBACK, LOC + QString("Turning %1 deinterlacing.")
    698             .arg(deinterlacing ? "on" : "off"));
    699 
    700704    hardwareDeinterlacing = deinterlacing;
    701 
    702     glfilt_map_t::iterator it = filters.begin();
    703     for (; it != filters.end(); it++)
    704     {
    705         it->second->outputBuffer = kFrameBufferObject;
    706 
    707         if ((it->first >= kGLFilterLinearBlendDeint) &&
    708             (it->first <= kGLFilterOneFieldDeintDFR) &&
    709             !deinterlacing)
    710         {
    711             it->second->outputBuffer = kNoBuffer;
    712         }
    713     }
    714 
    715     glfilt_map_t::reverse_iterator rit = filters.rbegin();
    716     for (; rit != filters.rend(); rit++)
    717     {
    718         if (rit->second->outputBuffer == kFrameBufferObject)
    719         {
    720             rit->second->outputBuffer = kDefaultBuffer;
    721             break;
    722         }
    723     }
    724 
    725     SetFiltering();
    726705}
    727706
    728707// locking ok
     
    740719    vector<GLuint> inputs = inputTextures;
    741720    QSize inputsize = inputTextureSize;
    742721    QSize realsize  = GetTextureSize(video_dim);
     722    uint  numfilters = filters.size();
    743723
    744724    glfilt_map_t::iterator it;
    745725    for (it = filters.begin(); it != filters.end(); it++)
    746726    {
    747         if (it->second->rotateFrameBuffers &&
    748             !(it->first == kGLFilterYUV2RGB && scan == kScan_Intr2ndField))
    749         {
    750             Rotate(&(it->second->frameBufferTextures));
    751             Rotate(&(it->second->frameBuffers));
    752         }
    753 
    754         // skip disabled filters
    755         if (it->second->outputBuffer == kNoBuffer)
    756             continue;
    757 
    758727        OpenGLFilterType type = it->first;
    759728        OpenGLFilter *filter = it->second;
    760729
     
    766735            continue;
    767736        }
    768737
    769         // skip colour conversion for frames already in frame buffer
    770         if (!inputUpdated && (frame == currentFrameNum) &&
    771             (type == kGLFilterYUV2RGB) && (frame != 0) &&
    772             (!(softwareDeinterlacing && softwareDeinterlacer == "bobdeint")))
    773         {
    774             inputs = filter->frameBufferTextures;
    775             inputsize = realsize;
    776             continue;
    777         }
    778 
    779738        // texture coordinates
    780739        float t_right = (float)video_dim.width();
    781740        float t_bottom  = (float)video_dim.height();
     
    802761            trueheight /= inputsize.height();
    803762        }
    804763
    805         float line_height = (trueheight / (float)video_dim.height());
    806         float bob = line_height / 2.0f;
    807 
    808         if (type == kGLFilterBobDeintDFR)
     764        // software bobdeint
     765        if ((softwareDeinterlacer == "bobdeint") &&
     766            softwareDeinterlacing &&
     767            (filter->outputBuffer == kDefaultBuffer))
    809768        {
    810             if (scan == kScan_Interlaced)
    811             {
    812                 t_bottom += bob;
    813                 t_top += bob;
    814             }
    815             if (scan == kScan_Intr2ndField)
    816             {
    817                 t_bottom -= bob;
    818                 t_top -= bob;
    819             }
    820         }
    821 
    822         if (softwareDeinterlacer == "bobdeint" &&
    823             softwareDeinterlacing && (type == kGLFilterYUV2RGB ||
    824             (type == kGLFilterResize && filters.size() == 1)))
    825         {
    826             bob = line_height / 4.0f;
     769            float bob = (trueheight / (float)video_dim.height()) / 4.0f;
    827770            if (scan == kScan_Interlaced)
    828771            {
    829772                t_top /= 2;
     
    853796        float vtop   = display.top();
    854797        float vbot   = display.bottom();
    855798
     799        // hardware bobdeint
     800        if (filter->outputBuffer == kDefaultBuffer &&
     801            hardwareDeinterlacing &&
     802            hardwareDeinterlacer == "openglbobdeint")
     803        {
     804            float bob = ((float)display.height() / (float)video_dim.height())
     805                        / 2.0f;
     806            if (scan == kScan_Interlaced)
     807            {
     808                vbot -= bob;
     809                vtop -= bob;
     810            }
     811            if (scan == kScan_Intr2ndField)
     812            {
     813                vbot += bob;
     814                vtop += bob;
     815            }
     816        }
     817
    856818        // resize for interactive tv
    857819        if (videoResize && filter->outputBuffer == kDefaultBuffer)
    858820            CalculateResize(vleft, vtop, vright, vbot);
    859821
    860         // invert horizontally if last filter
    861         if (it == filters.begin())
    862         {
    863             // flip vertical positioning to translate from X coordinate system
    864             // to opengl coordinate system
    865             vtop = (visible.height()- 1) - display.top();
    866             vbot = vtop - (display.height() - 1);
    867          }
    868         else if (it != filters.begin() &&
    869                 (filter->frameBuffers.empty() ||
    870                  filter->outputBuffer == kDefaultBuffer))
    871         {
    872             // this is the last filter and we have already inverted the video frame
    873             // now need to adjust for vertical offsets
    874             vbot = (visible.height()- 1) - display.top();
    875             vtop = vbot - (display.height() - 1);
     822        // invert horizontally
     823        if (((type == kGLFilterYUV2RGB) || (type == kGLFilterYUV2RGBA)) ||
     824            (filter->outputBuffer == kDefaultBuffer && numfilters == 1))
     825        {
     826            float temp = vtop;
     827            vtop = vbot;
     828            vbot = temp;
    876829        }
    877830
    878831        // bind correct frame buffer (default onscreen) and set viewport
     
    902855                }
    903856                break;
    904857
    905             case kNoBuffer:
     858            default:
    906859                continue;
    907860        }
    908861
    909862        // bind correct textures
    910         for (uint i = 0; i < inputs.size(); i++)
     863        uint active_tex = 0;
     864        for (; active_tex < inputs.size(); active_tex++)
    911865        {
    912             glActiveTexture(GL_TEXTURE0 + i);
    913             glBindTexture(textureType, inputs[i]);
     866            glActiveTexture(GL_TEXTURE0 + active_tex);
     867            glBindTexture(textureType, inputs[active_tex]);
     868        }
     869
     870        if (!referenceTextures.empty() &&
     871            hardwareDeinterlacing &&
     872            type == kGLFilterYUV2RGB)
     873        {
     874            uint max = inputs.size() + referenceTextures.size();
     875            uint ref = 0;
     876            for (; active_tex < max; active_tex++, ref++)
     877            {
     878                glActiveTexture(GL_TEXTURE0 + active_tex);
     879                glBindTexture(textureType, referenceTextures[ref]);
     880            }
    914881        }
    915882
    916883        // enable fragment program and set any environment variables
    917884        if ((type != kGLFilterNone) && (type != kGLFilterResize))
    918885        {
    919886            glEnable(GL_FRAGMENT_PROGRAM_ARB);
    920             gl_context->BindFragmentProgram(filter->fragmentProgram);
    921             float field = -line_height;
     887            GLuint program = 0;
     888
     889            if (type == kGLFilterYUV2RGB)
     890            {
     891                if (hardwareDeinterlacing &&
     892                    filter->fragmentPrograms.size() == 3)
     893                {
     894                    if (scan == kScan_Interlaced)
     895                        program = 1;
     896                    else if (scan == kScan_Intr2ndField)
     897                        program = 2;
     898                }
     899            }
     900
     901            gl_context->BindFragmentProgram(filter->fragmentPrograms[program]);
    922902
    923903            switch (type)
    924904            {
     
    928908                        gl_context->SetColourParams();
    929909                    break;
    930910
    931                 case kGLFilterBobDeintDFR:
    932                 case kGLFilterOneFieldDeintDFR:
    933                 case kGLFilterKernelDeintDFR:
    934                 case kGLFilterFieldOrderDFR:
    935                 case kGLFilterLinearBlendDeintDFR:
    936                     if (scan == kScan_Intr2ndField)
    937                         field *= -1;
    938 
    939                 case kGLFilterOneFieldDeint:
    940                 case kGLFilterKernelDeint:
    941                 case kGLFilterLinearBlendDeint:
    942                     gl_context->InitFragmentParams(
    943                         0, line_height * 2.0f, field, 0.0f, 0.0f);
    944                     break;
    945 
    946911                case kGLFilterNone:
    947912                case kGLFilterResize:
    948913                    break;
     
    1010975    inputUpdated = false;
    1011976}
    1012977
    1013 void OpenGLVideo::Rotate(vector<GLuint> *target)
     978void OpenGLVideo::RotateTextures(void)
    1014979{
    1015     if (target->size() < 2)
     980   if (referenceTextures.size() < 2)
    1016981        return;
    1017982
    1018     GLuint tmp = (*target)[target->size() - 1];
    1019     for (uint i = target->size() - 1; i > 0;  i--)
    1020         (*target)[i] = (*target)[i - 1];
     983    GLuint tmp = referenceTextures[referenceTextures.size() - 1];
     984
     985    for (uint i = referenceTextures.size() - 1; i > 0;  i--)
     986        referenceTextures[i] = referenceTextures[i - 1];
     987 
     988    referenceTextures[0] = inputTextures[0];
     989    inputTextures[0] = tmp;
     990}
     991
     992void OpenGLVideo::DeleteTextures(vector<uint> *textures)
     993{
     994    if ((*textures).empty())
     995        return;
    1021996
    1022     (*target)[0] = tmp;
     997    for (uint i = 0; i < (*textures).size(); i++)
     998        gl_context->DeleteTexture((*textures)[i]);
     999    (*textures).clear();
    10231000}
    10241001
    10251002// locking ok
     
    10421019        ret = kGLFilterYUV2RGB;
    10431020    else if (filter.contains("osd"))
    10441021        ret = kGLFilterYUV2RGBA;
    1045     else if (filter.contains("openglkerneldeint"))
    1046         ret = kGLFilterKernelDeint;
    1047     else if (filter.contains("opengllinearblend"))
    1048         ret = kGLFilterLinearBlendDeint;
    1049     else if (filter.contains("openglonefield"))
    1050         ret = kGLFilterOneFieldDeint;
    1051     else if (filter.contains("openglbobdeint"))
    1052         ret = kGLFilterBobDeintDFR;
    1053     else if (filter.contains("opengldoubleratelinearblend"))
    1054         ret = kGLFilterLinearBlendDeintDFR;
    1055     else if (filter.contains("opengldoubleratekerneldeint"))
    1056         ret = kGLFilterKernelDeintDFR;
    1057     else if (filter.contains("opengldoublerateonefield"))
    1058         ret = kGLFilterOneFieldDeintDFR;
    1059     else if (filter.contains("opengldoubleratefieldorder"))
    1060         ret = kGLFilterFieldOrderDFR;
    10611022    else if (filter.contains("resize"))
    10621023        ret = kGLFilterResize;
    10631024
     
    10751036            return "master";
    10761037        case kGLFilterYUV2RGBA:
    10771038            return "osd";
    1078         case kGLFilterKernelDeint:
    1079             return "openglkerneldeint";
    1080         case kGLFilterLinearBlendDeint:
    1081             return "opengllinearblend";
    1082         case kGLFilterOneFieldDeint:
    1083             return "openglonefield";
    1084         case kGLFilterBobDeintDFR:
    1085             return "openglbobdeint";
    1086         case kGLFilterLinearBlendDeintDFR:
    1087             return "opengldoubleratelinearblend";
    1088         case kGLFilterKernelDeintDFR:
    1089             return "opengldoubleratekerneldeint";
    1090         case kGLFilterOneFieldDeintDFR:
    1091             return "opengldoublerateonefield";
    1092         case kGLFilterFieldOrderDFR:
    1093             return "opengldoubleratefieldorder";
    10941039        case kGLFilterResize:
    10951040            return "resize";
    10961041    }
     
    10981043    return "";
    10991044}
    11001045
    1101 static const QString colour_control_fast =
    1102 "PARAM  adj  = program.env[0];"
    1103 "SUB res, res, 0.5;"
    1104 "MAD res, res, adj.zzzy, adj.wwwx;";
    1105 
    1106 static const QString init_fast =
    1107 "ATTRIB tex  = fragment.texcoord[0];"
    1108 "TEMP tmp, res;"
    1109 "TEX res, tex, texture[0], %1;";
    1110 
    1111 static const QString init_fast_alpha =
    1112 "MOV result.color.a, res.g;";
    1113 
    1114 static const QString end_fast =
    1115 "SUB tmp, res.rbgg, { 0.5, 0.5 };"
    1116 "MAD res, res.a, 1.164, -0.063;"
    1117 "MAD res, { 0, -.392, 2.017 }, tmp.xxxw, res;"
    1118 "MAD result.color, { 1.596, -.813, 0, 0 }, tmp.yyyw, res;";
     1046static const QString attrib_fast =
     1047"ATTRIB tex  = fragment.texcoord[0];\n";
     1048
     1049static const QString var_alpha =
     1050"TEMP alpha;\n";
     1051
     1052static const QString tex_alpha =
     1053"TEX alpha, tex, texture[3], %1;\n";
     1054
     1055static const QString tex_fast =
     1056"TEX res, tex, texture[0], %1;\n";
     1057
     1058static const QString param_colour =
     1059"PARAM  adj  = program.env[0];\n";
     1060
     1061static const QString calc_colour_fast =
     1062"SUB res, res, 0.5;\n"
     1063"MAD res, res, adj.zzzy, adj.wwwx;\n";
     1064
     1065static const QString end_alpha =
     1066"MOV result.color.a, alpha.a;\n";
     1067
     1068static const QString var_fast =
     1069"TEMP tmp, res;\n";
     1070
     1071static const QString calc_fast_alpha =
     1072"MOV result.color.a, res.g;\n";
     1073
     1074static const QString end_fast =
     1075"SUB tmp, res.rbgg, { 0.5, 0.5 };\n"
     1076"MAD res, res.a, 1.164, -0.063;\n"
     1077"MAD res, { 0, -.392, 2.017 }, tmp.xxxw, res;\n"
     1078"MAD result.color, { 1.596, -.813, 0, 0 }, tmp.yyyw, res;\n";
    11191079
    11201080static const QString end_fast_alpha =
    1121 "SUB tmp, res.rbgg, { 0.5, 0.5 };"
    1122 "MAD res, res.a, 1.164, -0.063;"
    1123 "MAD res, { 0, -.392, 2.017 }, tmp.xxxw, res;"
    1124 "MAD result.color.rgb, { 1.596, -.813, 0, 0 }, tmp.yyyw, res;";
     1081"SUB tmp, res.rbgg, { 0.5, 0.5 };\n"
     1082"MAD res, res.a, 1.164, -0.063;\n"
     1083"MAD res, { 0, -.392, 2.017 }, tmp.xxxw, res;\n"
     1084"MAD result.color.rgb, { 1.596, -.813, 0, 0 }, tmp.yyyw, res;\n";
     1085
     1086static const QString var_deint =
     1087"TEMP other, current, mov, prev;\n";
     1088
     1089static const QString field_calc =
     1090"MUL prev, tex.yyyy, %2;\n"
     1091"FRC prev, prev;\n"
     1092"SUB prev, prev, 0.5;\n";
     1093
     1094static const QString bobdeint[2] = {
     1095field_calc +
     1096"ADD other, tex, {0.0, %3, 0.0, 0.0};\n"
     1097"TEX other, other, texture[0], %1;\n"
     1098"CMP res, prev, res, other;\n",
     1099field_calc +
     1100"SUB other, tex, {0.0, %3, 0.0, 0.0};\n"
     1101"TEX other, other, texture[0], %1;\n"
     1102"CMP res, prev, other, res;\n"
     1103};
    11251104
    1126 // locking ok
    1127 QString OpenGLVideo::GetProgramString(OpenGLFilterType name)
     1105static const QString deint_end_top =
     1106"CMP other, mov, current, other;\n"
     1107"CMP res, prev, current, other;\n";
     1108
     1109static const QString deint_end_bot =
     1110"CMP other, mov, current, other;\n"
     1111"CMP res, prev, other, current;\n";
     1112
     1113static const QString motion_calc =
     1114"ABS mov, mov;\n"
     1115"SUB mov, mov, 0.07;\n";
     1116
     1117static const QString motion_top =
     1118"SUB mov, prev, current;\n" + motion_calc;
     1119
     1120static const QString motion_bot =
     1121"SUB mov, res, current;\n" + motion_calc;
     1122
     1123static const QString doublerateonefield[2] = {
     1124"TEX current, tex, texture[1], %1;\n"
     1125"TEX prev, tex, texture[2], %1;\n"
     1126"ADD other, tex, {0.0, %3, 0.0, 0.0};\n"
     1127"TEX other, other, texture[1], %1;\n"
     1128+ motion_top + field_calc + deint_end_top,
     1129
     1130"TEX current, tex, texture[1], %1;\n"
     1131"SUB other, tex, {0.0, %3, 0.0, 0.0};\n"
     1132"TEX other, other, texture[1], %1;\n"
     1133+ motion_bot + field_calc + deint_end_bot
     1134};
     1135
     1136static const QString linearblend[2] = {
     1137"TEX current, tex, texture[1], %1;\n"
     1138"TEX prev, tex, texture[2], %1;\n"
     1139"ADD other, tex, {0.0, %3, 0.0, 0.0};\n"
     1140"TEX other, other, texture[1], %1;\n"
     1141"SUB mov, tex, {0.0, %3, 0.0, 0.0};\n"
     1142"TEX mov, mov, texture[1], %1;\n"
     1143"LRP other, 0.5, other, mov;\n"
     1144+ motion_top + field_calc + deint_end_top,
     1145
     1146"TEX current, tex, texture[1], %1;\n"
     1147"SUB other, tex, {0.0, %3, 0.0, 0.0};\n"
     1148"TEX other, other, texture[1], %1;\n"
     1149"ADD mov, tex, {0.0, %3, 0.0, 0.0};\n"
     1150"TEX mov, mov, texture[1], %1;\n"
     1151"LRP other, 0.5, other, mov;\n"
     1152+ motion_bot + field_calc + deint_end_bot
     1153};
     1154
     1155static const QString kerneldeint[2] = {
     1156"TEX current, tex, texture[1], %1;\n"
     1157"TEX prev, tex, texture[2], %1;\n"
     1158+ motion_top +
     1159"MUL other, 0.125, prev;\n"
     1160"MAD other, 0.125, current, other;\n"
     1161"ADD prev, tex, {0.0, %3, 0.0, 0.0};\n"
     1162"TEX prev, prev, texture[1], %1;\n"
     1163"MAD other, 0.5, prev, other;\n"
     1164"SUB prev, tex, {0.0, %3, 0.0, 0.0};\n"
     1165"TEX prev, prev, texture[1], %1;\n"
     1166"MAD other, 0.5, prev, other;\n"
     1167"ADD prev, tex, {0.0, %4, 0.0, 0.0};\n"
     1168"TEX mov, prev, texture[1], %1;\n"
     1169"MAD other, -0.0625, mov, other;\n"
     1170"TEX mov, prev, texture[2], %1;\n"
     1171"MAD other, -0.0625, mov, other;\n"
     1172"SUB prev, tex, {0.0, %4, 0.0, 0.0};\n"
     1173"TEX mov, prev, texture[1], %1;\n"
     1174"MAD other, -0.0625, mov, other;\n"
     1175"TEX mov, prev, texture[2], %1;\n"
     1176"MAD other, -0.0625, mov, other;\n"
     1177+ field_calc + deint_end_top,
     1178
     1179"TEX current, tex, texture[1], %1;\n"
     1180+ motion_bot +
     1181"MUL other, 0.125, res;\n"
     1182"MAD other, 0.125, current, other;\n"
     1183"ADD prev, tex, {0.0, %3, 0.0, 0.0};\n"
     1184"TEX prev, prev, texture[1], %1;\n"
     1185"MAD other, 0.5, prev, other;\n"
     1186"SUB prev, tex, {0.0, %3, 0.0, 0.0};\n"
     1187"TEX prev, prev, texture[1], %1;\n"
     1188"MAD other, 0.5, prev, other;\n"
     1189"ADD prev, tex, {0.0, %4, 0.0, 0.0};\n"
     1190"TEX mov, prev, texture[1], %1;\n"
     1191"MAD other, -0.0625, mov, other;\n"
     1192"TEX mov, prev, texture[0], %1;\n"
     1193"MAD other, -0.0625, mov, other;\n"
     1194"SUB prev, tex, {0.0, %4, 0.0, 0.0};\n"
     1195"TEX mov, prev, texture[1], %1;\n"
     1196"MAD other, -0.0625, mov, other;\n"
     1197"TEX mov, prev, texture[0], %1;\n"
     1198"MAD other, -0.0625, mov, other;\n"
     1199+ field_calc + deint_end_bot
     1200};
     1201
     1202QString OpenGLVideo::GetProgramString(OpenGLFilterType name,
     1203                                      QString deint, FrameScanType field)
    11281204{
    11291205    QString ret =
    11301206        "!!ARBfp1.0\n"
    1131         "OPTION ARB_precision_hint_fastest;";
     1207        "OPTION ARB_precision_hint_fastest;\n";
    11321208
    11331209    switch (name)
    11341210    {
    11351211        case kGLFilterYUV2RGB:
    1136             ret += init_fast;
    1137             if (useColourControl)
    1138                 ret += colour_control_fast;
     1212        {
     1213            bool need_tex = true;
     1214            QString deint_bit = "";
     1215            if (deint != "")
     1216            {
     1217                uint tmp_field = 0;
     1218                if (field == kScan_Intr2ndField)
     1219                    tmp_field = 1;
     1220                if (deint == "openglbobdeint" ||
     1221                    deint == "openglonefield" ||
     1222                    deint == "opengldoubleratefieldorder")
     1223                {
     1224                    deint_bit = bobdeint[tmp_field];
     1225                }
     1226                else if (deint == "opengldoublerateonefield")
     1227                {
     1228                    deint_bit = doublerateonefield[tmp_field];
     1229                    if (!tmp_field) { need_tex = false; }
     1230                }
     1231                else if (deint == "opengllinearblend" ||
     1232                         deint == "opengldoubleratelinearblend")
     1233                {
     1234                    deint_bit = linearblend[tmp_field];
     1235                    if (!tmp_field) { need_tex = false; }
     1236                }
     1237                else if (deint == "openglkerneldeint" ||
     1238                         deint == "opengldoubleratekerneldeint")
     1239                {
     1240                    deint_bit = kerneldeint[tmp_field];
     1241                    if (!tmp_field) { need_tex = false; }
     1242                }
     1243                else
     1244                {
     1245                    VERBOSE(VB_PLAYBACK, LOC +
     1246                        "Unrecognised OpenGL deinterlacer");
     1247                }
     1248            }
     1249
     1250            ret += attrib_fast;
     1251            ret += useColourControl ? param_colour : "";
     1252            ret += (deint != "") ? var_deint : "";
     1253            ret += var_fast + (need_tex ? tex_fast : "");
     1254            ret += deint_bit;
     1255            ret += useColourControl ? calc_colour_fast : "";
    11391256            ret += end_fast;
     1257        }
    11401258            break;
    1141 
    11421259        case kGLFilterYUV2RGBA:
    1143             ret += init_fast + init_fast_alpha;
    1144             if (useColourControl)
    1145                 ret += colour_control_fast;
     1260
     1261            ret += attrib_fast;
     1262            ret += useColourControl ? param_colour : "";
     1263            ret += var_fast + tex_fast + calc_fast_alpha;
     1264            ret += useColourControl ? calc_colour_fast : "";
    11461265            ret += end_fast_alpha;
    1147             break;
    11481266
    1149         case kGLFilterKernelDeint:
    1150             ret +=
    1151                 "ATTRIB tex = fragment.texcoord[0];"
    1152                 "PARAM  off = program.env[0];"
    1153                 "TEMP sam, pos, cum, cur, field, mov;"
    1154                 "RCP field, off.x;"
    1155                 "MUL field, tex.yyyy, field;"
    1156                 "FRC field, field;"
    1157                 "SUB field, field, 0.5;"
    1158                 "TEX sam, tex, texture[1], %1;"
    1159                 "TEX cur, tex, texture[0], %1;"
    1160                 "SUB mov, cur, sam;"
    1161                 "MUL cum, sam, 0.125;"
    1162                 "MAD cum, cur, 0.125, cum;"
    1163                 "ABS mov, mov;"
    1164                 "SUB mov, mov, 0.12;"
    1165                 "ADD pos, tex, off.wyww;"
    1166                 "TEX sam, pos, texture[0], %1;"
    1167                 "MAD cum, sam, 0.5, cum;"
    1168                 "SUB pos, tex, off.wyww;"
    1169                 "TEX sam, pos, texture[0], %1;"
    1170                 "MAD cum, sam, 0.5, cum;"
    1171                 "MAD pos, off.wyww, 2.0, tex;"
    1172                 "TEX sam, pos, texture[0], %1;"
    1173                 "MAD cum, sam, -0.0625, cum;"
    1174                 "TEX sam, pos, texture[1], %1;"
    1175                 "MAD cum, sam, -0.0625, cum;"
    1176                 "MAD pos, off.wyww, -2.0, tex;"
    1177                 "TEX sam, pos, texture[0], %1;"
    1178                 "MAD cum, sam, -0.0625, cum;"
    1179                 "TEX sam, pos, texture[1], %1;"
    1180                 "MAD cum, sam, -0.0625, cum;"
    1181                 "CMP cum, mov, cur, cum;"
    1182                 "CMP result.color, field, cum, cur;";
    11831267            break;
    11841268
    1185         case kGLFilterLinearBlendDeintDFR:
    1186             ret +=
    1187                 "ATTRIB tex = fragment.texcoord[0];"
    1188                 "PARAM  off  = program.env[0];"
    1189                 "TEMP field, top, bot, current, previous, next, other, mov;"
    1190                 "TEX next, tex, texture[0], %1;"
    1191                 "TEX current, tex, texture[1], %1;"
    1192                 "TEX previous, tex, texture[2], %1;"
    1193                 "ADD top, tex, off.wyww;"
    1194                 "TEX other, top, texture[1], %1;"
    1195                 "SUB top, tex, off.wyww;"
    1196                 "TEX bot, top, texture[1], %1;"
    1197                 "LRP other, 0.5, other, bot;"
    1198                 "RCP field, off.x;"
    1199                 "MUL field, tex.yyyy, field;"
    1200                 "FRC field, field;"
    1201                 "SUB field, field, 0.5;"
    1202                 "SUB top, current, next;"
    1203                 "SUB bot, current, previous;"
    1204                 "CMP mov, field, bot, top;"
    1205                 "ABS mov, mov;"
    1206                 "SUB mov, mov, 0.12;"
    1207                 "CMP other, mov, current, other;"
    1208                 "CMP top, field, other, current;"
    1209                 "CMP bot, field, current, other;"
    1210                 "CMP result.color, off.y, top, bot;";
     1269        case kGLFilterNone:
     1270        case kGLFilterResize:
    12111271            break;
    12121272
    1213         case kGLFilterOneFieldDeintDFR:
    1214             ret +=
    1215                 "ATTRIB tex = fragment.texcoord[0];"
    1216                 "PARAM  off  = program.env[0];"
    1217                 "TEMP field, top, bot, current, previous, next, other, mov;"
    1218                 "TEX next, tex, texture[0], %1;"
    1219                 "TEX current, tex, texture[1], %1;"
    1220                 "TEX previous, tex, texture[2], %1;"
    1221                 "ADD top, tex, off.wyww;"
    1222                 "TEX other, top, texture[1], %1;"
    1223                 "RCP field, off.x;"
    1224                 "MUL field, tex.yyyy, field;"
    1225                 "FRC field, field;"
    1226                 "SUB field, field, 0.5;"
    1227                 "SUB top, current, next;"
    1228                 "SUB bot, current, previous;"
    1229                 "CMP mov, field, bot, top;"
    1230                 "ABS mov, mov;"
    1231                 "SUB mov, mov, 0.12;"
    1232                 "CMP other, mov, current, other;"
    1233                 "CMP top, field, other, current;"
    1234                 "CMP bot, field, current, other;"
    1235                 "CMP result.color, off.y, top, bot;";
     1273        default:
     1274            VERBOSE(VB_PLAYBACK, LOC_ERR + "Unknown fragment program.");
    12361275            break;
     1276    }
    12371277
    1238         case kGLFilterKernelDeintDFR:
    1239             ret +=
    1240                 "ATTRIB tex = fragment.texcoord[0];"
    1241                 "PARAM  off = program.env[0];"
    1242                 "TEMP sam, pos, bot, top, cur, pre, nex, field, mov;"
    1243                 "RCP field, off.x;"
    1244                 "MUL field, tex.yyyy, field;"
    1245                 "FRC field, field;"
    1246                 "SUB field, field, 0.5;"
    1247                 "TEX pre, tex, texture[2], %1;" // -1,0
    1248                 "TEX cur, tex, texture[1], %1;" //  0,0
    1249                 "TEX nex, tex, texture[0], %1;" // +1,0
    1250                 "SUB top, nex, cur;"
    1251                 "SUB bot, pre, cur;"
    1252                 "CMP mov, field, bot, top;"
    1253                 "ABS mov, mov;"
    1254                 "SUB mov, mov, 0.12;"
    1255                 "MUL bot, pre, 0.125;"          // BOT -1,0
    1256                 "MAD bot, cur, 0.125, bot;"     // BOT +1,0
    1257                 "MUL top, cur, 0.125;"          // TOP -1,0
    1258                 "MAD top, nex, 0.125, top;"     // TOP +1,0
    1259                 "ADD pos, tex, off.wyww;"
    1260                 "TEX sam, pos, texture[1], %1;" // 0,+1
    1261                 "MAD bot, sam, 0.5, bot;"       // BOT 0,+1
    1262                 "MAD top, sam, 0.5, top;"       // TOP 0,+1
    1263                 "SUB pos, tex, off.wyww;"
    1264                 "TEX sam, pos, texture[1], %1;" // 0,-1
    1265                 "MAD bot, sam, 0.5, bot;"       // BOT 0,-1
    1266                 "MAD top, sam, 0.5, top;"       // TOP 0,-1
    1267                 "MAD pos, off.wyww, 2.0, tex;"
    1268                 "TEX sam, pos, texture[1], %1;" // 0,+2
    1269                 "MAD bot, sam, -0.0625, bot;"   // BOT +1,+2
    1270                 "MAD top, sam, -0.0625, top;"   // TOP -1,+2
    1271                 "TEX sam, pos, texture[2], %1;" // -1,+2
    1272                 "MAD bot, sam, -0.0625, bot;"   // BOT -1,+2
    1273                 "TEX sam, pos, texture[0], %1;" // +1,+2
    1274                 "MAD top, sam, -0.0625, top;"   // TOP +1,+2
    1275                 "MAD pos, off.wyww, -2.0, tex;"
    1276                 "TEX sam, pos, texture[1], %1;" // +1,-2
    1277                 "MAD bot, sam, -0.0625, bot;"   // BOT +1,-2
    1278                 "MAD top, sam, -0.0625, top;"   // TOP -1,-2
    1279                 "TEX sam, pos, texture[2], %1;" // -1, -2 row
    1280                 "MAD bot, sam, -0.0625, bot;"   // BOT -1,-2
    1281                 "TEX sam, pos, texture[0], %1;" // +1,-2
    1282                 "MAD top, sam, -0.0625, top;"   // TOP +1,-2
    1283                 "CMP top, mov, cur, top;"
    1284                 "CMP bot, mov, cur, bot;"
    1285                 "CMP top, field, top, cur;"
    1286                 "CMP bot, field, cur, bot;"
    1287                 "CMP result.color, off.y, top, bot;";
    1288             break;
     1278    QString temp = textureRects ? "RECT" : "2D";
     1279    ret.replace("%1", temp);
    12891280
    1290         case kGLFilterBobDeintDFR:
    1291         case kGLFilterOneFieldDeint:
    1292             ret +=
    1293                 "ATTRIB tex = fragment.texcoord[0];"
    1294                 "PARAM  off = program.env[0];"
    1295                 "TEMP field, top, bottom, current, other;"
    1296                 "TEX current, tex, texture[0], %1;"
    1297                 "RCP field, off.x;"
    1298                 "MUL field, tex.yyyy, field;"
    1299                 "FRC field, field;"
    1300                 "SUB field, field, 0.5;"
    1301                 "ADD top, tex, off.wyww;"
    1302                 "TEX other, top, texture[0], %1;"
    1303                 "CMP top, field, other, current;"
    1304                 "CMP bottom, field, current, other;"
    1305                 "CMP result.color, off.y, top, bottom;";
    1306             break;
     1281    float lineHeight = 1.0f;
    13071282
    1308         case kGLFilterLinearBlendDeint:
    1309             ret +=
    1310                 "ATTRIB tex = fragment.texcoord[0];"
    1311                 "PARAM  off  = program.env[0];"
    1312                 "TEMP mov, field, cur, pre, pos;"
    1313                 "RCP field, off.x;"
    1314                 "MUL field, tex.yyyy, field;"
    1315                 "FRC field, field;"
    1316                 "SUB field, field, 0.5;"
    1317                 "TEX cur, tex, texture[0], %1;"
    1318                 "TEX pre, tex, texture[1], %1;"
    1319                 "SUB mov, cur, pre;"
    1320                 "ABS mov, mov;"
    1321                 "SUB mov, mov, 0.12;"
    1322                 "ADD pos, tex, off.wyww;"
    1323                 "TEX pre, pos, texture[0], %1;"
    1324                 "SUB pos, tex, off.wyww;"
    1325                 "TEX pos, pos, texture[0], %1;"
    1326                 "LRP pre, 0.5, pos, pre;"
    1327                 "CMP pre, field, pre, cur;"
    1328                 "CMP result.color, mov, cur, pre;";
    1329             break;
     1283    if (!textureRects &&
     1284       (inputTextureSize.height() > 0))
     1285    {
     1286        lineHeight /= inputTextureSize.height();
     1287    }
    13301288
    1331         case kGLFilterFieldOrderDFR:
    1332             ret +=
    1333                 "ATTRIB tex = fragment.texcoord[0];"
    1334                 "PARAM  off  = program.env[0];"
    1335                 "TEMP field, cur, pre, bot;"
    1336                 "TEX cur, tex, texture[0], %1;"
    1337                 "TEX pre, tex, texture[1], %1;"
    1338                 "RCP field, off.x;"
    1339                 "MUL field, tex.yyyy, field;"
    1340                 "FRC field, field;"
    1341                 "SUB field, field, 0.5;"
    1342                 "CMP bot, off.y, pre, cur;"
    1343                 "CMP result.color, field, bot, cur;";
     1289    float fieldSize = 1.0f / (lineHeight * 2.0);
    13441290
    1345             break;
     1291    ret.replace("%2", temp.setNum(fieldSize, 'f', 8));
     1292    ret.replace("%3", temp.setNum(lineHeight, 'f', 8));
     1293    ret.replace("%4", temp.setNum(lineHeight * 2.0, 'f', 8));
    13461294
    1347         case kGLFilterNone:
    1348         case kGLFilterResize:
    1349             break;
     1295    ret += "END";
    13501296
    1351         default:
    1352             VERBOSE(VB_PLAYBACK, LOC_ERR + "Unknown fragment program.");
    1353             break;
    1354     }
     1297    VERBOSE(VB_PLAYBACK, LOC + QString("Created %1 fragment program %2")
     1298                .arg(FilterToString(name)).arg(deint));
    13551299
    1356     return ret + "END";
     1300    return ret;
    13571301}
  • libs/libmythtv/openglvideo.h

    diff -ur -X excl mythtv-vid-18a/libs/libmythtv/openglvideo.h mythtv-vid-19/libs/libmythtv/openglvideo.h
    old new  
    1919    kGLFilterYUV2RGB,
    2020    kGLFilterYUV2RGBA,
    2121
    22     // Frame rate preserving deinterlacers
    23     kGLFilterLinearBlendDeint,
    24     kGLFilterKernelDeint,
    25     kGLFilterOneFieldDeint,
    26 
    27     // Frame rate doubling deinterlacers
    28     kGLFilterBobDeintDFR,
    29     kGLFilterLinearBlendDeintDFR,
    30     kGLFilterKernelDeintDFR,
    31     kGLFilterFieldOrderDFR,
    32     kGLFilterOneFieldDeintDFR,
    33 
    3422    // Frame scaling/resizing filters
    3523    kGLFilterResize,
    3624};
    3725
    3826enum DisplayBuffer
    3927{
    40     kNoBuffer = 0,    // disable filter
    4128    kDefaultBuffer,
    4229    kFrameBufferObject
    4330};
     
    7158    bool RemoveFilter(const QString &filter)
    7259         { return RemoveFilter(StringToFilter(filter)); }
    7360
    74     bool AddDeinterlacer(const QString &filter);
     61    bool AddDeinterlacer(const QString &deinterlacer);
    7562    void SetDeinterlacing(bool deinterlacing);
    7663    QString GetDeinterlacer(void) const
    77          { return FilterToString(GetDeintFilter()); };
     64         { return hardwareDeinterlacer; }
    7865    void SetSoftwareDeinterlacer(const QString &filter)
    7966         { softwareDeinterlacer = Q3DeepCopy<QString>(filter); };
    8067
     
    9582    bool AddFilter(OpenGLFilterType filter);
    9683    bool RemoveFilter(OpenGLFilterType filter);
    9784    bool OptimiseFilters(void);
    98     OpenGLFilterType GetDeintFilter(void) const;
    9985    bool AddFrameBuffer(uint &framebuffer, QSize fb_size,
    10086                        uint &texture, QSize vid_size);
    101     uint AddFragmentProgram(OpenGLFilterType name);
     87    uint AddFragmentProgram(OpenGLFilterType name,
     88                            QString deint = QString::null,
     89                            FrameScanType field = kScan_Progressive);
    10290    uint CreateVideoTexture(QSize size, QSize &tex_size,
    10391                            bool use_pbo = false);
    104     QString GetProgramString(OpenGLFilterType filter);
     92    QString GetProgramString(OpenGLFilterType filter,
     93                             QString deint = QString::null,
     94                             FrameScanType field = kScan_Progressive);
    10595    void CalculateResize(float &left,  float &top,
    10696                         float &right, float &bottom);
    10797    static QString FilterToString(OpenGLFilterType filter);
     
    110100    QSize GetTextureSize(const QSize &size);
    111101    void SetFiltering(void);
    112102
    113     void Rotate(vector<uint> *target);
    114     void SetTextureFilters(vector<uint> *textures, int filt, int wrap);
     103    void RotateTextures(void);
     104    void SetTextureFilters(vector<uint> *textures, int filt, int clamp);
     105    void DeleteTextures(vector<uint> *textures);
     106    void TearDownDeinterlacer(void);
    115107
    116108    OpenGLContext *gl_context;
    117109    QSize          video_dim;
     
    123115    QRect          video_rect;
    124116    QRect          frameBufferRect;
    125117    QString        softwareDeinterlacer;
     118    QString        hardwareDeinterlacer;
    126119    bool           hardwareDeinterlacing;
    127120    bool           useColourControl;
    128121    bool           viewportControl;
     122    vector<uint>   referenceTextures;
    129123    vector<uint>   inputTextures;
    130124    QSize          inputTextureSize;
    131125    glfilt_map_t   filters;