/*
 * 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]");
    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");
    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()
{
}

void
SceneDesktop::setup()
{
    Scene::setup();

    /* 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_;
}

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;
}
