diff options
Diffstat (limited to 'kms++')
-rw-r--r-- | kms++/CMakeLists.txt | 13 | ||||
-rw-r--r-- | kms++/inc/kms++/atomicreq.h | 3 | ||||
-rw-r--r-- | kms++/inc/kms++/connector.h | 2 | ||||
-rw-r--r-- | kms++/inc/kms++/modedb.h | 4 | ||||
-rw-r--r-- | kms++/inc/kms++/videomode.h | 3 | ||||
-rw-r--r-- | kms++/src/atomicreq.cpp | 25 | ||||
-rw-r--r-- | kms++/src/connector.cpp | 11 | ||||
-rw-r--r-- | kms++/src/modedb.cpp | 15 | ||||
-rw-r--r-- | kms++/src/modedb_cea.cpp | 3 | ||||
-rw-r--r-- | kms++/src/modedb_dmt.cpp | 4 | ||||
-rw-r--r-- | kms++/src/videomode.cpp | 10 |
11 files changed, 73 insertions, 20 deletions
diff --git a/kms++/CMakeLists.txt b/kms++/CMakeLists.txt index d983964..51ccc65 100644 --- a/kms++/CMakeLists.txt +++ b/kms++/CMakeLists.txt @@ -1,8 +1,9 @@ include_directories(${LIBDRM_INCLUDE_DIRS}) link_directories(${LIBDRM_LIBRARY_DIRS}) -file(GLOB SRCS "src/*.cpp" "src/*.h" "inc/kms++/*.h") -add_library(kms++ ${SRCS}) +file(GLOB SRCS "src/*.cpp" "src/*.h") +file(GLOB PUB_HDRS "inc/kms++/*.h") +add_library(kms++ ${SRCS} ${PUB_HDRS}) target_include_directories(kms++ PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc> @@ -10,3 +11,11 @@ target_include_directories(kms++ PUBLIC PRIVATE src) target_link_libraries(kms++ ${LIBDRM_LIBRARIES}) + +set_target_properties(kms++ PROPERTIES + PUBLIC_HEADER "${PUB_HDRS}") + +install(TARGETS kms++ + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + PUBLIC_HEADER DESTINATION include/kms++) diff --git a/kms++/inc/kms++/atomicreq.h b/kms++/inc/kms++/atomicreq.h index a9f779d..a678b54 100644 --- a/kms++/inc/kms++/atomicreq.h +++ b/kms++/inc/kms++/atomicreq.h @@ -24,6 +24,9 @@ public: void add(DrmPropObject *ob, const std::string& prop, uint64_t value); void add(DrmPropObject *ob, const std::map<std::string, uint64_t>& values); + void add_display(Connector* conn, Crtc* crtc, Blob* videomode, + Plane* primary, Framebuffer* fb); + int test(bool allow_modeset = false); int commit(void* data, bool allow_modeset = false); int commit_sync(bool allow_modeset = false); diff --git a/kms++/inc/kms++/connector.h b/kms++/inc/kms++/connector.h index 6ccc959..ccd7728 100644 --- a/kms++/inc/kms++/connector.h +++ b/kms++/inc/kms++/connector.h @@ -17,7 +17,7 @@ public: Videomode get_default_mode() const; Videomode get_mode(const std::string& mode) const; - Videomode get_mode(unsigned xres, unsigned yres, unsigned refresh, bool ilace) const; + Videomode get_mode(unsigned xres, unsigned yres, float vrefresh, bool ilace) const; Crtc* get_current_crtc() const; std::vector<Crtc*> get_possible_crtcs() const; diff --git a/kms++/inc/kms++/modedb.h b/kms++/inc/kms++/modedb.h index 43c7afc..b6447c6 100644 --- a/kms++/inc/kms++/modedb.h +++ b/kms++/inc/kms++/modedb.h @@ -10,7 +10,7 @@ struct Videomode; extern const Videomode dmt_modes[]; extern const Videomode cea_modes[]; -const Videomode& find_dmt(uint32_t width, uint32_t height, uint32_t vrefresh, bool ilace); -const Videomode& find_cea(uint32_t width, uint32_t height, uint32_t refresh, bool ilace); +const Videomode& find_dmt(uint32_t width, uint32_t height, float vrefresh, bool ilace); +const Videomode& find_cea(uint32_t width, uint32_t height, float vrefresh, bool ilace); } diff --git a/kms++/inc/kms++/videomode.h b/kms++/inc/kms++/videomode.h index f9abaf9..ec16969 100644 --- a/kms++/inc/kms++/videomode.h +++ b/kms++/inc/kms++/videomode.h @@ -31,6 +31,9 @@ struct Videomode uint16_t vfp() const { return vsync_start - vdisplay; } uint16_t vsw() const { return vsync_end - vsync_start; } uint16_t vbp() const { return vtotal - vsync_end; } + + bool interlace() const; + float calculated_vrefresh() const; }; } diff --git a/kms++/src/atomicreq.cpp b/kms++/src/atomicreq.cpp index f2809af..28128f2 100644 --- a/kms++/src/atomicreq.cpp +++ b/kms++/src/atomicreq.cpp @@ -60,6 +60,31 @@ void AtomicReq::add(kms::DrmPropObject* ob, const map<string, uint64_t>& values) add(ob, kvp.first, kvp.second); } +void AtomicReq::add_display(Connector* conn, Crtc* crtc, Blob* videomode, Plane* primary, Framebuffer* fb) +{ + add(conn, { + { "CRTC_ID", crtc->id() }, + }); + + add(crtc, { + { "ACTIVE", 1 }, + { "MODE_ID", videomode->id() }, + }); + + add(primary, { + { "FB_ID", fb->id() }, + { "CRTC_ID", crtc->id() }, + { "SRC_X", 0 << 16 }, + { "SRC_Y", 0 << 16 }, + { "SRC_W", fb->width() << 16 }, + { "SRC_H", fb->height() << 16 }, + { "CRTC_X", 0 }, + { "CRTC_Y", 0 }, + { "CRTC_W", fb->width() }, + { "CRTC_H", fb->height() }, + }); +} + int AtomicReq::test(bool allow_modeset) { uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY; diff --git a/kms++/src/connector.cpp b/kms++/src/connector.cpp index ec37d5d..92700af 100644 --- a/kms++/src/connector.cpp +++ b/kms++/src/connector.cpp @@ -3,6 +3,7 @@ #include <unistd.h> #include <fcntl.h> #include <cassert> +#include <cmath> #include <kms++/kms++.h> #include "helpers.h" @@ -118,23 +119,23 @@ Videomode Connector::get_mode(const string& mode) const throw invalid_argument(mode + ": mode not found"); } -Videomode Connector::get_mode(unsigned xres, unsigned yres, unsigned refresh, bool ilace) const +Videomode Connector::get_mode(unsigned xres, unsigned yres, float vrefresh, bool ilace) const { auto c = m_priv->drm_connector; for (int i = 0; i < c->count_modes; i++) { - drmModeModeInfo& m = c->modes[i]; + Videomode m = drm_mode_to_video_mode(c->modes[i]); if (m.hdisplay != xres || m.vdisplay != yres) continue; - if (refresh && m.vrefresh != refresh) + if (ilace != m.interlace()) continue; - if (ilace != !!(m.flags & DRM_MODE_FLAG_INTERLACE)) + if (vrefresh && std::abs(m.calculated_vrefresh() - vrefresh) >= 0.001) continue; - return drm_mode_to_video_mode(c->modes[i]); + return m; } throw invalid_argument("mode not found"); diff --git a/kms++/src/modedb.cpp b/kms++/src/modedb.cpp index 24d6f63..858c3d0 100644 --- a/kms++/src/modedb.cpp +++ b/kms++/src/modedb.cpp @@ -1,5 +1,6 @@ #include <xf86drm.h> #include <stdexcept> +#include <cmath> #include <kms++/modedb.h> @@ -8,7 +9,7 @@ using namespace std; namespace kms { -static const Videomode& find_from_table(const Videomode* modes, uint32_t width, uint32_t height, uint32_t refresh, bool ilace) +static const Videomode& find_from_table(const Videomode* modes, uint32_t width, uint32_t height, float vrefresh, bool ilace) { for (unsigned i = 0; modes[i].clock; ++i) { const Videomode& m = modes[i]; @@ -16,10 +17,10 @@ static const Videomode& find_from_table(const Videomode* modes, uint32_t width, if (m.hdisplay != width || m.vdisplay != height) continue; - if (refresh && m.vrefresh != refresh) + if (ilace != m.interlace()) continue; - if (ilace != !!(m.flags & DRM_MODE_FLAG_INTERLACE)) + if (vrefresh && std::abs(m.calculated_vrefresh() - vrefresh) >= 0.001) continue; return m; @@ -28,14 +29,14 @@ static const Videomode& find_from_table(const Videomode* modes, uint32_t width, throw invalid_argument("mode not found"); } -const Videomode& find_dmt(uint32_t width, uint32_t height, uint32_t refresh, bool ilace) +const Videomode& find_dmt(uint32_t width, uint32_t height, float vrefresh, bool ilace) { - return find_from_table(dmt_modes, width, height, refresh, ilace); + return find_from_table(dmt_modes, width, height, vrefresh, ilace); } -const Videomode& find_cea(uint32_t width, uint32_t height, uint32_t refresh, bool ilace) +const Videomode& find_cea(uint32_t width, uint32_t height, float vrefresh, bool ilace) { - return find_from_table(cea_modes, width, height, refresh, ilace); + return find_from_table(cea_modes, width, height, vrefresh, ilace); } } diff --git a/kms++/src/modedb_cea.cpp b/kms++/src/modedb_cea.cpp index a105dd8..a99a612 100644 --- a/kms++/src/modedb_cea.cpp +++ b/kms++/src/modedb_cea.cpp @@ -42,7 +42,8 @@ namespace kms .name = nm, .clock = (c), \ .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), .htotal = (ht), .hskew = (hsk), \ .vdisplay = (vd), .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), .vscan = (vs), \ - .vrefresh = DIV_ROUND(c * 1000, ht * vt), .flags = (f), .type = 0 + .vrefresh = DIV_ROUND(c * 1000, ht * vt) * (((f) & DRM_MODE_FLAG_INTERLACE) ? 2 : 1), \ + .flags = (f), .type = 0 /* * Probably taken from CEA-861 spec. diff --git a/kms++/src/modedb_dmt.cpp b/kms++/src/modedb_dmt.cpp index e3f2ad5..c3d5426 100644 --- a/kms++/src/modedb_dmt.cpp +++ b/kms++/src/modedb_dmt.cpp @@ -42,8 +42,8 @@ namespace kms .name = nm, .clock = (c), \ .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), .htotal = (ht), .hskew = (hsk), \ .vdisplay = (vd), .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), .vscan = (vs), \ - .vrefresh = DIV_ROUND(c * 1000, ht * vt), .flags = (f), .type = 0 - + .vrefresh = DIV_ROUND(c * 1000, ht * vt) * (((f) & DRM_MODE_FLAG_INTERLACE) ? 2 : 1), \ + .flags = (f), .type = 0 /* * Autogenerated from the DMT spec. diff --git a/kms++/src/videomode.cpp b/kms++/src/videomode.cpp index 30d47f8..16330bb 100644 --- a/kms++/src/videomode.cpp +++ b/kms++/src/videomode.cpp @@ -16,4 +16,14 @@ unique_ptr<Blob> Videomode::to_blob(Card& card) const return unique_ptr<Blob>(new Blob(card, &drm_mode, sizeof(drm_mode))); } +bool Videomode::interlace() const +{ + return flags & DRM_MODE_FLAG_INTERLACE; +} + +float Videomode::calculated_vrefresh() const +{ + return (clock * 1000.0) / (htotal * vtotal) * (interlace() ? 2 : 1); +} + } |