/*
 * Copyright © Canonical Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 2 or 3,
 * as published by the Free Software Foundation.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef MIR_GRAPHICS_GBM_REAL_KMS_OUTPUT_H_
#define MIR_GRAPHICS_GBM_REAL_KMS_OUTPUT_H_

#include "kms_output.h"
#include "kms-utils/drm_mode_resources.h"

#include <memory>
#include <mutex>

namespace mir
{
namespace graphics
{
namespace gbm
{

class PageFlipper;

class RealKMSOutput : public KMSOutput
{
public:
    RealKMSOutput(
        int drm_fd,
        kms::DRMModeConnectorUPtr&& connector,
        std::shared_ptr<PageFlipper> const& page_flipper);
    ~RealKMSOutput();

    uint32_t id() const override;

    void reset() override;
    void configure(geometry::Displacement fb_offset, size_t kms_mode_index) override;
    geometry::Size size() const override;
    unsigned max_refresh_rate() const override;

    bool set_crtc(FBHandle const& fb) override;
    bool has_crtc_mismatch() override;
    void clear_crtc() override;
    bool schedule_page_flip(FBHandle const& fb) override;
    void wait_for_page_flip() override;

    bool set_cursor_image(gbm_bo* buffer) override;
    void move_cursor(geometry::Point destination) override;
    bool clear_cursor() override;
    bool has_cursor_image() const override;

    void set_power_mode(MirPowerMode mode) override;
    void set_gamma(GammaCurves const& gamma) override;

    void refresh_hardware_state() override;
    void update_from_hardware_state(DisplayConfigurationOutput& output) const override;

    int drm_fd() const override;
    bool connected() const override;

private:
    bool ensure_crtc();
    void restore_saved_crtc();

    int const drm_fd_;
    std::shared_ptr<PageFlipper> const page_flipper;

    kms::DRMModeConnectorUPtr connector;
    size_t mode_index;
    geometry::Displacement fb_offset;
    kms::DRMModeCrtcUPtr current_crtc;
    drmModeCrtc saved_crtc;
    bool using_saved_crtc;
    bool has_cursor_;

    MirPowerMode power_mode;
    int dpms_enum_id;

    std::mutex power_mutex;
};

}
}
}

#endif /* MIR_GRAPHICS_GBM_REAL_KMS_OUTPUT_H_ */
