/***************************************************************************
                           sharpness.cpp
                           -------------
    begin                : Sat Jul 31 2004
    copyright            : (C) 2004 by Dirk Ziegelmeier
    email                : dziegel@gmx.de
 ***************************************************************************/

/*
 * Sharpness algorithm taken from DScaler.
 * Copyright (c) 2001 Tom Barry. All rights reserved.
 *
 * Ported by: Dirk Ziegelmeier
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 */

#include <stdlib.h>

#include <kdebug.h>
#include <klocale.h>
#include <kconfig.h>

#include <qspinbox.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qpushbutton.h>

#include "sharpness.h"
#include "kdetvimagefilter.h"
#include "kdetvimagefiltercontext.h"
#include "kdetvcpudetection.h"
#include "x86-64_macros.inc"

#define USEPREFETCH_DEFAULT true
#define SHARPNESS_DEFAULT   128

class SharpnessImageFilter : public KdetvImageFilter
{
public:
    SharpnessImageFilter()
        : KdetvImageFilter(i18n("Sharpness")),
          UsePrefetch(USEPREFETCH_DEFAULT),
          Sharpness(SHARPNESS_DEFAULT)
    {
    }

    virtual ~SharpnessImageFilter()
    {
    }

    virtual KdetvImage::ImageFormat inputFormats()
    {
        return KdetvImage::FORMAT_YUYV;
    };

    virtual KdetvImageFilterContext* operator<< (KdetvImageFilterContext* ctx)
    {
        KdetvCpuDetection::Capabilities cap = KdetvCpuDetection::capabilities();
        if(cap & KdetvCpuDetection::Cap_SSE) {
            if(UsePrefetch) {
                filterSSE_P(ctx);
            } else {
                filterSSE(ctx);
            }
        } else if(cap & KdetvCpuDetection::Cap_3DNOW) {
            if(UsePrefetch) {
                filter3DNOW_P(ctx);
            } else {
                filter3DNOW(ctx);
            }
        } else if(cap & KdetvCpuDetection::Cap_MMX) {
            filterMMX(ctx);
        }

        return ctx;
    }

protected:
    friend class SharpnessPlugin;

#define USE_PREFETCH

#define IS_SSE
#include "sharpness.asm"
#undef  IS_SSE

#define IS_3DNOW
#include "sharpness.asm"
#undef  IS_3DNOW

#undef USE_PREFETCH

#define IS_SSE
#include "sharpness.asm"
#undef  IS_SSE

#define IS_3DNOW
#include "sharpness.asm"
#undef  IS_3DNOW

#define IS_MMXEXT
#include "sharpness.asm"
#undef  IS_MMXEXT

    bool UsePrefetch;
    long Sharpness;
};

// -----------------------------------------------------------------------

SharpnessPlugin::SharpnessPlugin(Kdetv *ktv, const QString& cfgkey, QObject *parent, const char* name)
    : KdetvFilterPlugin(ktv, cfgkey, parent, name)
{
    SharpnessImageFilter* f = new SharpnessImageFilter();
    _filter = f;

    f->Sharpness   = _cfg->readNumEntry("Sharpness",     SHARPNESS_DEFAULT);
    f->UsePrefetch = _cfg->readBoolEntry("Use Prefetch", USEPREFETCH_DEFAULT);
}

SharpnessPlugin::~SharpnessPlugin()
{
    delete _filter;
}

QWidget* SharpnessPlugin::configWidget(QWidget* parent, const char* name)
{
    SharpnessImageFilter* f = static_cast<SharpnessImageFilter*>(_filter);

    QFrame *w = new QFrame(parent, name);
    w->setMargin(4);
    QGridLayout *g = new QGridLayout(w, 3, 2);

    g->addWidget(new QLabel(i18n("Sharpness:"), w), 0, 0);
    _spSharpness = new QSpinBox(1, 255, 1, w, "SharpnessSpin");
    _spSharpness->setValue(f->Sharpness);
    g->addWidget(_spSharpness, 0, 1);

    _cbPrefetch = new QCheckBox(i18n("Use prefetch"), w, "PrefetchCB");
    _cbPrefetch->setChecked(f->UsePrefetch);
    g->addWidget(_cbPrefetch, 1, 0);

    QButton* b = new QPushButton(i18n("Defaults"), w, "Defaults");
    connect(b, SIGNAL( clicked() ),
            this, SLOT( defaults() ));
    g->addWidget(b, 2, 1);

    return w;
}

void SharpnessPlugin::defaults()
{
    SharpnessImageFilter* f = static_cast<SharpnessImageFilter*>(_filter);

    f->Sharpness   = SHARPNESS_DEFAULT;
    f->UsePrefetch = USEPREFETCH_DEFAULT;

    _spSharpness->setValue(f->Sharpness);
    _cbPrefetch->setChecked(f->UsePrefetch);
}

void SharpnessPlugin::saveConfig()
{
    SharpnessImageFilter* f = static_cast<SharpnessImageFilter*>(_filter);

    f->Sharpness   = _spSharpness->value();
    f->UsePrefetch = _cbPrefetch->isChecked();

    _cfg->writeEntry("Sharpness",    f->Sharpness);
    _cfg->writeEntry("Use Prefetch", f->UsePrefetch);
    _cfg->sync();
}

extern "C" {
    KDETV_EXPORT SharpnessPlugin* create_sharpness(Kdetv* ktv)
    {
        return new SharpnessPlugin(ktv, "sharpness", 0, "Sharpness");
    }
}

#include "sharpness.moc"
