/*
 * Copyright © 2010-2011 Linaro Limited
 *
 * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
 *
 * glmark2 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 3 of the License, or (at your option) any later
 * version.
 *
 * glmark2 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * glmark2.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *  Alexandros Frantzis (glmark2)
 *  Jesse Barker (glmark2)
 */
#include <cmath>
#include <cstdlib>

#include "scene.h"
#include "mat.h"
#include "stack.h"
#include "vec.h"
#include "log.h"
#include "program.h"
#include "shader-source.h"
#include "util.h"
#include "texture.h"

enum BlurDirection {
    BlurDirectionHorizontal,
    BlurDirectionVertical,
    BlurDirectionBoth
};

static void
create_blur_shaders(ShaderSource& vtx_source, ShaderSource& frg_source,
                    unsigned int radius, float sigma, BlurDirection direction)
{
    vtx_source.append_file(GLMARK_DATA_PATH"/shaders/desktop.vert");
    frg_source.append_file(GLMARK_DATA_PATH"/shaders/desktop-blur.frag");

    /* Don't let the gaussian curve become too narrow */
    if (sigma < 1.0)
        sigma = 1.0;

    unsigned int side = 2 * radius + 1;

    for (unsigned int i = 0; i < radius + 1; i++) {
        float s2 = 2.0 * sigma * sigma;
        float k = 1.0 / std::sqrt(M_PI * s2) * std::exp( - (static_cast<float>(i) * i) / s2);
        std::stringstream ss_tmp;
        ss_tmp << "Kernel" << i;
        frg_source.add_const(ss_tmp.str(), k);
    }

    std::stringstream ss;
    ss << "result = " << std::endl;

    if (direction == BlurDirectionHorizontal) {
        for (unsigned int i = 0; i < side; i++) {
            int offset = static_cast<int>(i - radius);
            ss << "texture2D(Texture0, TextureCoord + vec2(" <<
                  offset << ".0 * TextureStepX, 0.0)) * Kernel" <<
                  std::abs(offset) << " +" << std::endl;
        }
        ss << "0.0 ;" << std::endl;
    }
    else if (direction == BlurDirectionVertical) {
        for (unsigned int i = 0; i < side; i++) {
            int offset = static_cast<int>(i - radius);
            ss << "texture2D(Texture0, TextureCoord + vec2(0.0, " <<
                  offset << ".0 * TextureStepY)) * Kernel" <<
                  std::abs(offset) << " +" << std::endl;
        }
        ss << "0.0 ;" << std::endl;
    }
    else if (direction == BlurDirectionBoth) {
        for (unsigned int i = 0; i < side; i++) {
            int ioffset = static_cast<int>(i - radius);
            for (unsigned int j = 0; j < side; j++) {
                int joffset = static_cast<int>(j - radius);
                ss << "texture2D(Texture0, TextureCoord + vec2(" <<
                      ioffset << ".0 * TextureStepX, " <<
                      joffset << ".0 * TextureStepY))" <<
                      " * Kernel" << std::abs(ioffset) <<
                      " * Kernel" << std::abs(joffset) << " +" << std::endl;
            }
        }
        ss << " 0.0;" << std::endl;
    }

    frg_source.replace("$CONVOLUTION$", ss.str());
}

/**
 * A RenderObject represents a source and target of rendering
 * operations.
 */
class RenderObject
{
public:
    RenderObject() :
        texture_(0), fbo_(0), rotation_rad_(0),
        texture_contents_invalid_(true) { }

    virtual ~RenderObject() {}

    virtual void init()
    {
        /* Create a texture to draw to */
        glGenTextures(1, &texture_);
        glBindTexture(GL_TEXTURE_2D, texture_);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.x(), size_.y(), 0,
                     GL_RGBA, GL_UNSIGNED_BYTE, 0);

        /* Create a FBO */
        glGenFramebuffers(1, &fbo_);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                               GL_TEXTURE_2D, texture_, 0);

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        /* Load the shader program when this class if first used */
        if (RenderObject::use_count == 0) {
            ShaderSource vtx_source(GLMARK_DATA_PATH"/shaders/desktop.vert");
            ShaderSource frg_source(GLMARK_DATA_PATH"/shaders/desktop.frag");
            Scene::load_shaders_from_strings(main_program, vtx_source.str(),
                                             frg_source.str());
        }

        texture_contents_invalid_ = true;
        RenderObject::use_count++;
    }

    virtual void release()
    {
        /* Release resources */
        if (texture_ != 0)
        {
            glDeleteTextures(1, &texture_);
            texture_ = 0;
        }
        if (fbo_ != 0)
        {
            glDeleteFramebuffers(1, &fbo_);
            fbo_ = 0;
        }

        /*
         * Release the shader program when object of this class
         * are no longer in use.
         */
        RenderObject::use_count--;
        if (RenderObject::use_count == 0)
            RenderObject::main_program.release();
    }

    void make_current()
    {
        glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
        glViewport(0, 0, size_.x(), size_.y());
    }

    void position(const LibMatrix::vec2& pos) { pos_ = pos; }
    const LibMatrix::vec2& position() { return pos_; }


    virtual void size(const LibMatrix::vec2& size)
    {
        /* Recreate the backing texture with correct size */
        if (size_.x() != size.x() || size_.y() != size.y()) {
            size_ = size;
            glBindTexture(GL_TEXTURE_2D, texture_);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.x(), size_.y(), 0,
                         GL_RGBA, GL_UNSIGNED_BYTE, 0);
            texture_contents_invalid_ = true;
        }

        if (texture_contents_invalid_) {
            clear();
            texture_contents_invalid_ = false;
        }
    }

    const LibMatrix::vec2& size() { return size_; }

    const LibMatrix::vec2& speed() { return speed_; }
    void speed(const LibMatrix::vec2& speed) { speed_ = speed; }

    GLuint texture() { return texture_; }

    virtual void clear()
    {
        make_current();
        glClear(GL_COLOR_BUFFER_BIT);
    }

    virtual void render_to(RenderObject& target)
    {
        render_to(target, main_program);
    }

    virtual void render_to(RenderObject& target, Program& program)
    {
        LibMatrix::vec2 anchor(pos_);
        LibMatrix::vec2 ll(pos_ - anchor);
        LibMatrix::vec2 ur(pos_ + size_ - anchor);

        /* Calculate new position according to rotation value */
        GLfloat position[2 * 4] = {
            rotate_x(ll.x(), ll.y()) + anchor.x(), rotate_y(ll.x(), ll.y()) + anchor.y(),
            rotate_x(ur.x(), ll.y()) + anchor.x(), rotate_y(ur.x(), ll.y()) + anchor.y(),
            rotate_x(ll.x(), ur.y()) + anchor.x(), rotate_y(ll.x(), ur.y()) + anchor.y(),
            rotate_x(ur.x(), ur.y()) + anchor.x(), rotate_y(ur.x(), ur.y()) + anchor.y(),
        };

        /* Normalize position and write back to array */
        for (int i = 0; i < 4; i++) {
            const LibMatrix::vec2& v2(
                    target.normalize_position(
                        LibMatrix::vec2(position[2 * i], position[2 * i + 1])
                        )
                    );
            position[2 * i] = v2.x();
            position[2 * i + 1] = v2.y();
        }

        static const GLfloat texcoord[2 * 4] = {
            0.0, 0.0,
            1.0, 0.0,
            0.0, 1.0,
            1.0, 1.0,
        };

        target.make_current();

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture_);
        draw_quad_with_program(position, texcoord, program);
    }

    virtual void render_from(RenderObject& target, Program& program = main_program)
    {
        LibMatrix::vec2 final_pos(pos_ + size_);
        LibMatrix::vec2 ll_tex(target.normalize_texcoord(pos_));
        LibMatrix::vec2 ur_tex(target.normalize_texcoord(final_pos));

        static const GLfloat position_blur[2 * 4] = {
            -1.0, -1.0,
             1.0, -1.0,
            -1.0,  1.0,
             1.0,  1.0,
        };
        GLfloat texcoord_blur[2 * 4] = {
            ll_tex.x(), ll_tex.y(),
            ur_tex.x(), ll_tex.y(),
            ll_tex.x(), ur_tex.y(),
            ur_tex.x(), ur_tex.y(),
        };

        make_current();
        glBindTexture(GL_TEXTURE_2D, target.texture());
        draw_quad_with_program(position_blur, texcoord_blur, program);
    }

    /**
     * Normalizes a position from [0, size] to [-1.0, 1.0]
     */
    LibMatrix::vec2 normalize_position(const LibMatrix::vec2& pos)
    {
        return pos * 2.0 / size_ - 1.0;
    }

    /**
     * Normalizes a position from [0, size] to [0.0, 1.0]
     */
    LibMatrix::vec2 normalize_texcoord(const LibMatrix::vec2& pos)
    {
        return pos / size_;
    }

    void rotation(float degrees)
    {
        rotation_rad_ = (M_PI * degrees / 180.0);
    }

protected:
    void draw_quad_with_program(const GLfloat *position, const GLfloat *texcoord,
                                Program &program)
    {
        int pos_index = program["position"].location();
        int tex_index = program["texcoord"].location();

        program.start();

        glEnableVertexAttribArray(pos_index);
        glEnableVertexAttribArray(tex_index);
        glVertexAttribPointer(pos_index, 2,
                              GL_FLOAT, GL_FALSE, 0, position);
        glVertexAttribPointer(tex_index, 2,
                              GL_FLOAT, GL_FALSE, 0, texcoord);

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        glDisableVertexAttribArray(tex_index);
        glDisableVertexAttribArray(pos_index);

        program.stop();
    }

    static Program main_program;

    LibMatrix::vec2 pos_;
    LibMatrix::vec2 size_;
    LibMatrix::vec2 speed_;
    GLuint texture_;
    GLuint fbo_;

private:
    float rotate_x(float x, float y)
    {
        return x * cos(rotation_rad_) - y * sin(rotation_rad_);
    }

    float rotate_y(float x, float y)
    {
        return x * sin(rotation_rad_) + y * cos(rotation_rad_);
    }

    float rotation_rad_;
    bool texture_contents_invalid_;
    static int use_count;

};

int RenderObject::use_count = 0;
Program RenderObject::main_program;

/**
 * A RenderObject representing the screen.
 *
 * Rendering to this objects renders to the screen framebuffer.
 */
class RenderScreen : public RenderObject
{
public:
    RenderScreen(Canvas &canvas) { fbo_ = canvas.fbo(); }
    virtual void init() {}
    virtual void release() {}
};

/**
 * A RenderObject with a background image.
 *
 * The image is drawn to the RenderObject automatically when the
 * object is cleared, resized etc
 */
class RenderClearImage : public RenderObject
{
public:
    RenderClearImage(const std::string& texture) :
        RenderObject(), background_texture_name(texture),
        background_texture_(0) {}

    virtual void init()
    {
        RenderObject::init();

        /* Load the image into a texture */
        Texture::load(background_texture_name,
                      &background_texture_, GL_LINEAR, GL_LINEAR, 0);

    }

    virtual void release()
    {
        glDeleteTextures(1, &background_texture_);
        background_texture_ = 0;

        RenderObject::release();
    }

    virtual void clear()
    {
        static const GLfloat position[2 * 4] = {
            -1.0, -1.0,
             1.0, -1.0,
            -1.0,  1.0,
             1.0,  1.0,
        };
        static const GLfloat texcoord[2 * 4] = {
            0.0, 0.0,
            1.0, 0.0,
            0.0, 1.0,
            1.0, 1.0,
        };

        make_current();
        glClear(GL_COLOR_BUFFER_BIT);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, background_texture_);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        draw_quad_with_program(position, texcoord, main_program);
        glDisable(GL_BLEND);
    }

private:
    std::string background_texture_name;
    GLuint background_texture_;
};

/**
 * A RenderObject that blurs the target it is drawn to.
 */
class RenderWindowBlur : public RenderObject
{
public:
    RenderWindowBlur(unsigned int passes, unsigned int radius, bool separable,
                     bool draw_contents = true) :
        RenderObject(), passes_(passes), radius_(radius), separable_(separable),
        draw_contents_(draw_contents) {}

    virtual void init()
    {
        RenderObject::init();

        /* Only have one instance of the window contents data */
        if (draw_contents_ && RenderWindowBlur::use_count == 0)
            window_contents_.init();

        RenderWindowBlur::use_count++;
    }

    virtual void release()
    {
        RenderWindowBlur::use_count--;

        /* Only have one instance of the window contents data */
        if (draw_contents_ && RenderWindowBlur::use_count == 0)
            window_contents_.release();

        RenderObject::release();
    }

    virtual void size(const LibMatrix::vec2& size)
    {
        RenderObject::size(size);
        if (draw_contents_)
            window_contents_.size(size);
    }

    virtual void render_to(RenderObject& target)
    {
        if (separable_) {
            Program& blur_program_h1 = blur_program_h(target.size().x());
            Program& blur_program_v1 = blur_program_v(target.size().y());

            for (unsigned int i = 0; i < passes_; i++) {
                render_from(target, blur_program_h1);
                RenderObject::render_to(target, blur_program_v1);
            }
        }
        else {
            Program& blur_program1 = blur_program(target.size().x(), target.size().y());

            for (unsigned int i = 0; i < passes_; i++) {
                if (i % 2 == 0)
                    render_from(target, blur_program1);
                else
                    RenderObject::render_to(target, blur_program1);
            }

            if (passes_ % 2 == 1)
                RenderObject::render_to(target);
        }

        /*
         * Blend the window contents with the target texture.
         */
        if (draw_contents_) {
            glEnable(GL_BLEND);
            /*
             * Blend the colors normally, but don't change the
             * destination alpha value.
             */
            glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
                                GL_ZERO, GL_ONE);
            window_contents_.position(position());
            window_contents_.render_to(target);
            glDisable(GL_BLEND);
        }
    }

private:
    Program& blur_program(unsigned int w, unsigned int h)
    {
        /*
         * If the size of the window has changed we must recreate
         * the shader to contain the correct texture step values.
         */
        if (blur_program_dim_.x() != w || blur_program_dim_.y() != h ||
            !blur_program_.ready())
        {
            blur_program_dim_.x(w);
            blur_program_dim_.y(h);

            blur_program_.release();

            ShaderSource vtx_source;
            ShaderSource frg_source;
            create_blur_shaders(vtx_source, frg_source, radius_,
                                radius_ / 3.0, BlurDirectionBoth);
            frg_source.add_const("TextureStepX", 1.0 / w);
            frg_source.add_const("TextureStepY", 1.0 / h);
            Scene::load_shaders_from_strings(blur_program_, vtx_source.str(),
                                             frg_source.str());
        }

        return blur_program_;
    }

    Program& blur_program_h(unsigned int w)
    {
        /*
         * If the size of the window has changed we must recreate
         * the shader to contain the correct texture step values.
         */
        if (blur_program_dim_.x() != w ||
            !blur_program_h_.ready())
        {
            blur_program_dim_.x(w);

            blur_program_h_.release();

            ShaderSource vtx_source;
            ShaderSource frg_source;
            create_blur_shaders(vtx_source, frg_source, radius_,
                                radius_ / 3.0, BlurDirectionHorizontal);
            frg_source.add_const("TextureStepX", 1.0 / w);
            Scene::load_shaders_from_strings(blur_program_h_, vtx_source.str(),
                                             frg_source.str());
        }

        return blur_program_h_;
    }

    Program& blur_program_v(unsigned int h)
    {
        /*
         * If the size of the window has changed we must recreate
         * the shader to contain the correct texture step values.
         */
        if (blur_program_dim_.y() != h ||
            !blur_program_v_.ready())
        {
            blur_program_dim_.y(h);

            blur_program_v_.release();

            ShaderSource vtx_source;
            ShaderSource frg_source;
            create_blur_shaders(vtx_source, frg_source, radius_,
                                radius_ / 3.0, BlurDirectionVertical);
            frg_source.add_const("TextureStepY", 1.0 / h);
            Scene::load_shaders_from_strings(blur_program_v_, vtx_source.str(),
                                             frg_source.str());
        }

        return blur_program_v_;
    }

    LibMatrix::uvec2 blur_program_dim_;
    Program blur_program_;
    Program blur_program_h_;
    Program blur_program_v_;
    unsigned int passes_;
    unsigned int radius_;
    bool separable_;
    bool draw_contents_;

    static int use_count;
    static RenderClearImage window_contents_;

};

/**
 * A RenderObject that draws a drop shadow around the window.
 */
class RenderWindowShadow : public RenderObject
{
public:
    using RenderObject::size;

    RenderWindowShadow(unsigned int shadow_size, bool draw_contents = true) :
        RenderObject(), shadow_size_(shadow_size), draw_contents_(draw_contents) {}

    virtual void init()
    {
        RenderObject::init();

        /*
         * Only have one instance of the resources.
         * This works only if all windows have the same size, which
         * is currently the case for this scene. If this condition
         * ceases to be true we will need to create the resources per
         * object.
         */
        if (RenderWindowShadow::use_count == 0) {
            shadow_h_.init();
            shadow_v_.init();
            shadow_corner_.init();
            if (draw_contents_)
                window_contents_.init();
        }

        RenderWindowShadow::use_count++;
    }

    virtual void release()
    {
        RenderWindowShadow::use_count--;

        /* Only have one instance of the data */
        if (RenderWindowShadow::use_count == 0) {
            shadow_h_.release();
            shadow_v_.release();
            shadow_corner_.release();
            if (draw_contents_)
                window_contents_.release();
        }

        RenderObject::release();
    }

    virtual void size(const LibMatrix::vec2& size)
    {
        RenderObject::size(size);
        shadow_h_.size(LibMatrix::vec2(size.x() - shadow_size_,
                                       static_cast<double>(shadow_size_)));
        shadow_v_.size(LibMatrix::vec2(size.y() - shadow_size_,
                                       static_cast<double>(shadow_size_)));
        shadow_corner_.size(LibMatrix::vec2(static_cast<double>(shadow_size_),
                                            static_cast<double>(shadow_size_)));
        if (draw_contents_)
            window_contents_.size(size);
    }

    virtual void render_to(RenderObject& target)
    {
        glEnable(GL_BLEND);
        /*
         * Blend the colors normally, but don't change the
         * destination alpha value.
         */
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
                            GL_ZERO, GL_ONE);

        /* Bottom shadow */
        shadow_h_.rotation(0.0);
        shadow_h_.position(position() +
                           LibMatrix::vec2(shadow_size_,
                                           -shadow_h_.size().y()));
        shadow_h_.render_to(target);

        /* Right shadow */
        shadow_v_.rotation(90.0);
        shadow_v_.position(position() +
                           LibMatrix::vec2(size().x() + shadow_v_.size().y(), 0.0));
        shadow_v_.render_to(target);

        /* Bottom right shadow */
        shadow_corner_.rotation(0.0);
        shadow_corner_.position(position() +
                                LibMatrix::vec2(size().x(),
                                                -shadow_corner_.size().y()));
        shadow_corner_.render_to(target);

        /* Top right shadow */
        shadow_corner_.rotation(90.0);
        shadow_corner_.position(position() + size() +
                                LibMatrix::vec2(shadow_corner_.size().x(),
                                                -shadow_corner_.size().y()));
        shadow_corner_.render_to(target);

        /* Bottom left shadow */
        shadow_corner_.rotation(-90.0);
        shadow_corner_.position(position());
        shadow_corner_.render_to(target);

        /*
         * Blend the window contents with the target texture.
         */
        if (draw_contents_) {
            window_contents_.position(position());
            window_contents_.render_to(target);
        }

        glDisable(GL_BLEND);
    }

private:
    unsigned int shadow_size_;
    bool draw_contents_;

    static int use_count;
    static RenderClearImage window_contents_;
    static RenderClearImage shadow_h_;
    static RenderClearImage shadow_v_;
    static RenderClearImage shadow_corner_;

};

int RenderWindowBlur::use_count = 0;
RenderClearImage RenderWindowBlur::window_contents_("desktop-window");
int RenderWindowShadow::use_count = 0;
RenderClearImage RenderWindowShadow::window_contents_("desktop-window");
RenderClearImage RenderWindowShadow::shadow_h_("desktop-shadow");
RenderClearImage RenderWindowShadow::shadow_v_("desktop-shadow");
RenderClearImage RenderWindowShadow::shadow_corner_("desktop-shadow-corner");

/*******************************
 * SceneDesktop implementation *
 *******************************/

/**
 * Private structure used to avoid contaminating scene.h with all of the
 * SceneDesktop internal classes.
 */
struct SceneDesktopPrivate
{
    RenderScreen screen;
    RenderClearImage desktop;
    std::vector<RenderObject *> windows;

    SceneDesktopPrivate(Canvas &canvas) :
        screen(canvas), desktop("effect-2d") {}

    ~SceneDesktopPrivate() { Util::dispose_pointer_vector(windows); }

};


SceneDesktop::SceneDesktop(Canvas &canvas) :
    Scene(canvas, "desktop")
{
    priv_ = new SceneDesktopPrivate(canvas);
    options_["effect"] = Scene::Option("effect", "blur", "The effect to use",
                                       "blur,shadow");
    options_["windows"] = Scene::Option("windows", "4",
                                        "the number of windows");
    options_["window-size"] = Scene::Option("window-size", "0.35",
                                            "the window size as a percentage of the minimum screen dimension [0.0 - 0.5]");
    options_["passes"] = Scene::Option("passes", "1",
                                       "the number of effect passes (effect dependent)");
    options_["blur-radius"] = Scene::Option("blur-radius", "5",
                                            "the blur effect radius (in pixels)");
    options_["separable"] = Scene::Option("separable", "true",
                                          "use separable convolution for the blur effect",
                                          "false,true");
    options_["shadow-size"] = Scene::Option("shadow-size", "20",
                                            "the size of the shadow (in pixels)");
}

SceneDesktop::~SceneDesktop()
{
    delete priv_;
}

bool
SceneDesktop::load()
{
    return true;
}

void
SceneDesktop::unload()
{
}

bool
SceneDesktop::setup()
{
    if (!Scene::setup())
        return false;

    /* Parse the options */
    unsigned int windows(0);
    unsigned int passes(0);
    unsigned int blur_radius(0);
    float window_size_factor(0.0);
    unsigned int shadow_size(0);
    bool separable(options_["separable"].value == "true");

    windows = Util::fromString<unsigned int>(options_["windows"].value);
    window_size_factor = Util::fromString<float>(options_["window-size"].value);
    passes = Util::fromString<unsigned int>(options_["passes"].value);
    blur_radius = Util::fromString<unsigned int>(options_["blur-radius"].value);
    shadow_size = Util::fromString<unsigned int>(options_["shadow-size"].value);

    // Make sure the Texture object knows where to find our images.
    Texture::find_textures();

    /* Ensure we get a transparent clear color for all following operations */
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glDisable(GL_DEPTH_TEST);
    glDepthMask(GL_FALSE);

    /* Set up the screen and desktop RenderObjects */
    priv_->screen.init();
    priv_->desktop.init();
    priv_->screen.size(LibMatrix::vec2(canvas_.width(), canvas_.height()));
    priv_->desktop.size(LibMatrix::vec2(canvas_.width(), canvas_.height()));

    /* Create the windows */
    const float angular_step(2.0 * M_PI / windows);
    unsigned int min_dimension = std::min(canvas_.width(), canvas_.height());
    float window_size(min_dimension * window_size_factor);
    static const LibMatrix::vec2 corner_offset(window_size / 2.0,
                                               window_size / 2.0);

    for (unsigned int i = 0; i < windows; i++) {
        LibMatrix::vec2 center(canvas_.width() * (0.5 + 0.25 * cos(i * angular_step)),
                               canvas_.height() * (0.5 + 0.25 * sin(i * angular_step)));
        RenderObject* win;
        if (options_["effect"].value == "shadow")
            win = new RenderWindowShadow(shadow_size);
        else
            win = new RenderWindowBlur(passes, blur_radius, separable);

        win->init();
        win->position(center - corner_offset);
        win->size(LibMatrix::vec2(window_size, window_size));
        /*
         * Set the speed in increments of about 30 degrees (but not exactly,
         * so we don't get windows moving just on the X axis or Y axis).
         */
        win->speed(LibMatrix::vec2(cos(0.1 + i * M_PI / 6.0) * canvas_.width() / 3,
                                   sin(0.1 + i * M_PI / 6.0) * canvas_.height() / 3));
        /*
         * Perform a dummy rendering to ensure internal shaders are initialized
         * now, in order not to affect the benchmarking.
         */
        win->render_to(priv_->desktop);
        priv_->windows.push_back(win);
    }

    /*
     * Ensure the screen is the current rendering target (it might have changed
     * to a FBO in the previous steps).
     */
    priv_->screen.make_current();

    currentFrame_ = 0;
    running_ = true;
    startTime_ = Util::get_timestamp_us() / 1000000.0;
    lastUpdateTime_ = startTime_;

    return true;
}

void
SceneDesktop::teardown()
{
    for (std::vector<RenderObject*>::iterator winIt = priv_->windows.begin();
         winIt != priv_->windows.end();
         winIt++)
    {
        RenderObject* curObj = *winIt;
        curObj->release();
        delete curObj;
    }
    priv_->windows.clear();
    priv_->screen.make_current();

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    priv_->desktop.release();
    priv_->screen.release();

    Scene::teardown();
}

void
SceneDesktop::update()
{
    double current_time = Util::get_timestamp_us() / 1000000.0;
    double dt = current_time - lastUpdateTime_;

    Scene::update();

    std::vector<RenderObject *>& windows(priv_->windows);

    /*
     * Move the windows around the screen, bouncing them back when
     * they reach the edge.
     */
    for (std::vector<RenderObject *>::const_iterator iter = windows.begin();
         iter != windows.end();
         iter++)
    {
        bool should_update = true;
        RenderObject *win = *iter;
        LibMatrix::vec2 new_pos(
                win->position().x() + win->speed().x() * dt,
                win->position().y() + win->speed().y() * dt);

        if (new_pos.x() < 0.0 ||
            new_pos.x() + win->size().x() > static_cast<float>(canvas_.width()))
        {
            win->speed(LibMatrix::vec2(-win->speed().x(), win->speed().y()));
            should_update = false;
        }

        if (new_pos.y() < 0.0 ||
            new_pos.y() + win->size().y() > static_cast<float>(canvas_.height()))
        {
            win->speed(LibMatrix::vec2(win->speed().x(), -win->speed().y()));
            should_update = false;
        }

        if (should_update)
            win->position(new_pos);
    }
}

void
SceneDesktop::draw()
{
    std::vector<RenderObject *>& windows(priv_->windows);

    /* Ensure we get a transparent clear color for all following operations */
    glClearColor(0.0, 0.0, 0.0, 0.0);

    priv_->desktop.clear();

    for (std::vector<RenderObject *>::const_iterator iter = windows.begin();
         iter != windows.end();
         iter++)
    {
        RenderObject *win = *iter;
        win->render_to(priv_->desktop);
    }

    priv_->desktop.render_to(priv_->screen);

}

Scene::ValidationResult
SceneDesktop::validate()
{
    static const double radius_3d(std::sqrt(3.0 * 2.0 * 2.0));

    Canvas::Pixel ref;

    /* Parse the options */
    unsigned int windows(0);
    unsigned int passes(0);
    unsigned int blur_radius(0);
    float window_size_factor(0.0);
    unsigned int shadow_size(0);

    windows = Util::fromString<unsigned int>(options_["windows"].value);
    window_size_factor = Util::fromString<float>(options_["window-size"].value);
    passes = Util::fromString<unsigned int>(options_["passes"].value);
    blur_radius = Util::fromString<unsigned int>(options_["blur-radius"].value);
    shadow_size = Util::fromString<unsigned int>(options_["shadow-size"].value);

    if (options_["effect"].value == "blur")
    {
        if (windows == 4 && passes == 1 && blur_radius == 5)
            ref = Canvas::Pixel(0x89, 0xa3, 0x53, 0xff);
        else
            return Scene::ValidationUnknown;
    }
    else if (options_["effect"].value == "shadow")
    {
        if (windows == 4 && fabs(window_size_factor - 0.35) < 0.0001 &&
            shadow_size == 20)
        {
            ref = Canvas::Pixel(0x1f, 0x27, 0x0d, 0xff);
        }
        else
        {
            return Scene::ValidationUnknown;
        }
    }

    Canvas::Pixel pixel = canvas_.read_pixel(512, 209);

    double dist = pixel.distance_rgb(ref);
    if (dist < radius_3d + 0.01) {
        return Scene::ValidationSuccess;
    }
    else {
        Log::debug("Validation failed! Expected: 0x%x Actual: 0x%x Distance: %f\n",
                    ref.to_le32(), pixel.to_le32(), dist);
        return Scene::ValidationFailure;
    }

    return Scene::ValidationUnknown;
}
