
// stats.hpp - rendering statistics for hairline

#ifndef __stats_hpp__
#define __stats_hpp__

#include <GL/glew.h>

class GLQueryObjects {
    GLuint gl_query_objects[10];
    GLuint& vertices_submitted_query;
    GLuint& primitives_generated_query;
    GLuint& tess_control_shader_patches_query;
    GLuint& tess_evaluation_shader_invocations_query;
    GLuint& geometry_shader_invocations_query;
    GLuint& geometry_primitives_emitted_query;
    GLuint& clipping_input_primitives_query;
    GLuint& clipping_output_primitives_query;

public:
    GLQueryObjects();
    void init();
    void ensureInitialized();
    void beginQueries();
    void endQueries();

    friend class GLLinkRenderStats;
};

class LinkRenderStats {
    unsigned int links_rendered;
    unsigned int links_trivially_culled;
    unsigned int quads_generated;

public:
    LinkRenderStats();
    void incrementLinksTriviallyCulled();
    void incrementLinksRendered();
    void addQuadsGenerated(unsigned int quads);
    bool operator ==(const LinkRenderStats& other) const;

    // Queries
    unsigned int LinksRendered() const;
    unsigned int LinksTriviallyCulled() const;
    unsigned int LinksEvaluated() const;
    unsigned int QuadsGenerated() const;
};

class GLLinkRenderStats {
    GLQueryObjects& gl_query_objects;

    // OpenGL ARB_pipeline_statistics_query query results
    GLuint gl_vertices_submitted;
    GLuint gl_primitives_generated;
    GLuint gl_tess_control_shader_patches;
    GLuint gl_tess_evaluation_shader_invocations;
    GLuint gl_geometry_shader_invocations;
    GLuint gl_geometry_primitives_emitted;
    GLuint gl_clipping_input_primitives;
    GLuint gl_clipping_output_primitives;

public:
    GLLinkRenderStats(GLQueryObjects& objs);

    void beginQueries();
    void endQueries();
    void queryResults();
    void printResults() const;

    inline GLuint GLVerticesSubmitted() const {
        return gl_vertices_submitted;
    }
    inline GLuint GLPrimitivesGenerated() const {
        return gl_primitives_generated;
    }
    inline GLuint GLTessControlShaderPatches() const {
        return gl_tess_control_shader_patches;
    }
    inline GLuint GLTessEvaluationShaderInvocations() const {
        return gl_tess_evaluation_shader_invocations;
    }
    inline GLuint GLGeometryShaderInvocations() const {
        return gl_geometry_shader_invocations;
    }
    inline GLuint GLGeometryPrimitivesEmitted() const {
        return gl_geometry_primitives_emitted;
    }
    inline GLuint GLClippingInputPrimitives() const {
        return gl_clipping_input_primitives;
    }
    inline GLuint GLClippingOutputPrimitives() const {
        return gl_clipping_output_primitives;
    }
};

#endif // __stats_hpp__
