/*
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "config.h"
#include "libavutil/attributes.h"
#include "libavutil/cpu.h"
#include "libavutil/x86/cpu.h"
#include "libavcodec/avcodec.h"
#include "libavcodec/idctdsp.h"
#include "idctdsp.h"
#include "simple_idct.h"

/* Input permutation for the simple_idct_mmx */
static const uint8_t simple_mmx_permutation[64] = {
    0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D,
    0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D,
    0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D,
    0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F,
    0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F,
    0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D,
    0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F,
    0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F,
};

static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 };

av_cold int ff_init_scantable_permutation_x86(uint8_t *idct_permutation,
                                              enum idct_permutation_type perm_type)
{
    int i;

    switch (perm_type) {
    case FF_IDCT_PERM_SIMPLE:
        for (i = 0; i < 64; i++)
            idct_permutation[i] = simple_mmx_permutation[i];
        return 1;
    case FF_IDCT_PERM_SSE2:
        for (i = 0; i < 64; i++)
            idct_permutation[i] = (i & 0x38) | idct_sse2_row_perm[i & 7];
        return 1;
    }

    return 0;
}

av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx,
                                 unsigned high_bit_depth)
{
    int cpu_flags = av_get_cpu_flags();

    if (EXTERNAL_MMX(cpu_flags)) {
        c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmx;
        c->put_pixels_clamped        = ff_put_pixels_clamped_mmx;
        c->add_pixels_clamped        = ff_add_pixels_clamped_mmx;

        if (!high_bit_depth &&
            avctx->lowres == 0 &&
            (avctx->idct_algo == FF_IDCT_AUTO ||
                avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
                avctx->idct_algo == FF_IDCT_SIMPLEMMX)) {
                c->idct_put  = ff_simple_idct_put_mmx;
                c->idct_add  = ff_simple_idct_add_mmx;
                c->idct      = ff_simple_idct_mmx;
                c->perm_type = FF_IDCT_PERM_SIMPLE;
        }
    }

    if (EXTERNAL_SSE2(cpu_flags)) {
        c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_sse2;
        c->put_pixels_clamped        = ff_put_pixels_clamped_sse2;
        c->add_pixels_clamped        = ff_add_pixels_clamped_sse2;

        if (!high_bit_depth &&
            avctx->lowres == 0 &&
            (avctx->idct_algo == FF_IDCT_AUTO ||
                avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
                avctx->idct_algo == FF_IDCT_SIMPLEMMX)) {
                c->idct_put  = ff_simple_idct_put_sse2;
                c->idct_add  = ff_simple_idct_add_sse2;
                c->perm_type = FF_IDCT_PERM_SIMPLE;
        }

        if (ARCH_X86_64 &&
            !high_bit_depth &&
            avctx->lowres == 0 &&
            (avctx->idct_algo == FF_IDCT_AUTO ||
                avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
                avctx->idct_algo == FF_IDCT_SIMPLEMMX ||
                avctx->idct_algo == FF_IDCT_SIMPLE)) {
                c->idct      = ff_simple_idct8_sse2;
                c->idct_put  = ff_simple_idct8_put_sse2;
                c->idct_add  = ff_simple_idct8_add_sse2;
                c->perm_type = FF_IDCT_PERM_TRANSPOSE;
        }
    }

    if (ARCH_X86_64 && avctx->lowres == 0) {
        if (EXTERNAL_AVX(cpu_flags) &&
            !high_bit_depth &&
            (avctx->idct_algo == FF_IDCT_AUTO ||
                avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
                avctx->idct_algo == FF_IDCT_SIMPLEMMX ||
                avctx->idct_algo == FF_IDCT_SIMPLE)) {
                c->idct      = ff_simple_idct8_avx;
                c->idct_put  = ff_simple_idct8_put_avx;
                c->idct_add  = ff_simple_idct8_add_avx;
                c->perm_type = FF_IDCT_PERM_TRANSPOSE;
        }

        if (avctx->bits_per_raw_sample == 10 &&
            avctx->codec_id != AV_CODEC_ID_MPEG4 &&
            (avctx->idct_algo == FF_IDCT_AUTO ||
             avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
             avctx->idct_algo == FF_IDCT_SIMPLE)) {
            if (EXTERNAL_SSE2(cpu_flags)) {
                c->idct_put  = ff_simple_idct10_put_sse2;
                c->idct_add  = NULL;
                c->idct      = ff_simple_idct10_sse2;
                c->perm_type = FF_IDCT_PERM_TRANSPOSE;

            }
            if (EXTERNAL_AVX(cpu_flags)) {
                c->idct_put  = ff_simple_idct10_put_avx;
                c->idct_add  = NULL;
                c->idct      = ff_simple_idct10_avx;
                c->perm_type = FF_IDCT_PERM_TRANSPOSE;
            }
        }

        if (avctx->bits_per_raw_sample == 12 &&
            (avctx->idct_algo == FF_IDCT_AUTO ||
             avctx->idct_algo == FF_IDCT_SIMPLEMMX)) {
            if (EXTERNAL_SSE2(cpu_flags)) {
                c->idct_put  = ff_simple_idct12_put_sse2;
                c->idct_add  = NULL;
                c->idct      = ff_simple_idct12_sse2;
                c->perm_type = FF_IDCT_PERM_TRANSPOSE;
            }
            if (EXTERNAL_AVX(cpu_flags)) {
                c->idct_put  = ff_simple_idct12_put_avx;
                c->idct_add  = NULL;
                c->idct      = ff_simple_idct12_avx;
                c->perm_type = FF_IDCT_PERM_TRANSPOSE;
            }
        }
    }
}
