/*
    SPDX-FileCopyrightText: 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
    SPDX-FileCopyrightText: 2011-2012 Collabora Ltd. <info@collabora.com>

    SPDX-License-Identifier: LGPL-2.1-only
*/
#ifndef OPENGLSURFACEPAINTER_H
#define OPENGLSURFACEPAINTER_H

#include "abstractsurfacepainter.h"
#include <QOpenGLShaderProgram>

#ifndef Q_WS_MAC
# ifndef APIENTRYP
#   ifdef APIENTRY
#     define APIENTRYP APIENTRY *
#   else
#     define APIENTRY
#     define APIENTRYP *
#   endif
# endif
#else
# define APIENTRY
# define APIENTRYP *
#endif

class OpenGLSurfacePainter : public AbstractSurfacePainter
{
public:
    OpenGLSurfacePainter();

    static QSet<GstVideoFormat> supportedPixelFormats();

    virtual bool supportsFormat(GstVideoFormat format) const {
        return supportedPixelFormats().contains(format);
    }

    virtual void updateColors(int brightness, int contrast, int hue, int saturation);
    virtual void paint(quint8 *data, const BufferFormat & frameFormat,
                       QPainter *painter, const PaintAreas & areas);

protected:
    void initRgbTextureInfo(GLenum internalFormat, GLuint format, GLenum type, const QSize &size);
    void initYuv420PTextureInfo(const QSize &size);
    void initYv12TextureInfo(const QSize &size);

    virtual void paintImpl(const QPainter *painter,
                           const GLfloat *vertexCoordArray,
                           const GLfloat *textureCoordArray) = 0;

#ifndef QT_OPENGL_ES
    typedef void (APIENTRY *_glActiveTexture) (GLenum);
    _glActiveTexture glActiveTexture;
#endif

    GLenum m_textureFormat;
    GLuint m_textureInternalFormat;
    GLenum m_textureType;
    int m_textureCount;
    GLuint m_textureIds[3];
    int m_textureWidths[3];
    int m_textureHeights[3];
    int m_textureOffsets[3];

    QMatrix4x4 m_colorMatrix;
    GstVideoColorMatrix m_videoColorMatrix;
};

#ifndef QT_OPENGL_ES

class ArbFpSurfacePainter : public OpenGLSurfacePainter
{
public:
    ArbFpSurfacePainter();

    virtual void init(const BufferFormat & format);
    virtual void cleanup();

protected:
    virtual void paintImpl(const QPainter *painter,
                           const GLfloat *vertexCoordArray,
                           const GLfloat *textureCoordArray);

private:
    typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *);
    typedef void (APIENTRY *_glBindProgramARB) (GLenum, GLuint);
    typedef void (APIENTRY *_glDeleteProgramsARB) (GLsizei, const GLuint *);
    typedef void (APIENTRY *_glGenProgramsARB) (GLsizei, GLuint *);
    typedef void (APIENTRY *_glProgramLocalParameter4fARB) (
            GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
    typedef void (APIENTRY *_glActiveTexture) (GLenum);

    _glProgramStringARB glProgramStringARB;
    _glBindProgramARB glBindProgramARB;
    _glDeleteProgramsARB glDeleteProgramsARB;
    _glGenProgramsARB glGenProgramsARB;
    _glProgramLocalParameter4fARB glProgramLocalParameter4fARB;

    GLuint m_programId;
};

#endif

class GlslSurfacePainter : public OpenGLSurfacePainter
{
public:
    GlslSurfacePainter();

    virtual void init(const BufferFormat & format);
    virtual void cleanup();

protected:
    virtual void paintImpl(const QPainter *painter,
                           const GLfloat *vertexCoordArray,
                           const GLfloat *textureCoordArray);

private:
    QOpenGLShaderProgram m_program;
};

#endif // OPENGLSURFACEPAINTER_H
