From 9916712a62169606d845510028a3ea6f84bd442f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Sat, 11 Jun 2016 21:46:24 +0300 Subject: kms++: organize into subdirs --- kms++/CMakeLists.txt | 8 +- kms++/atomicreq.cpp | 94 --------- kms++/atomicreq.h | 36 ---- kms++/blob.cpp | 51 ----- kms++/blob.h | 22 -- kms++/card.cpp | 239 ---------------------- kms++/card.h | 71 ------- kms++/connector.cpp | 224 --------------------- kms++/connector.h | 51 ----- kms++/crtc.cpp | 140 ------------- kms++/crtc.h | 50 ----- kms++/decls.h | 19 -- kms++/drmobject.cpp | 34 ---- kms++/drmobject.h | 40 ---- kms++/drmpropobject.cpp | 86 -------- kms++/drmpropobject.h | 35 ---- kms++/dumbframebuffer.cpp | 137 ------------- kms++/dumbframebuffer.h | 46 ----- kms++/encoder.cpp | 77 ------- kms++/encoder.h | 25 --- kms++/extframebuffer.cpp | 68 ------- kms++/extframebuffer.h | 21 -- kms++/framebuffer.cpp | 42 ---- kms++/framebuffer.h | 40 ---- kms++/helpers.cpp | 72 ------- kms++/helpers.h | 12 -- kms++/inc/kms++/atomicreq.h | 36 ++++ kms++/inc/kms++/blob.h | 22 ++ kms++/inc/kms++/card.h | 71 +++++++ kms++/inc/kms++/connector.h | 51 +++++ kms++/inc/kms++/crtc.h | 50 +++++ kms++/inc/kms++/decls.h | 19 ++ kms++/inc/kms++/drmobject.h | 40 ++++ kms++/inc/kms++/drmpropobject.h | 35 ++++ kms++/inc/kms++/dumbframebuffer.h | 46 +++++ kms++/inc/kms++/encoder.h | 25 +++ kms++/inc/kms++/extframebuffer.h | 21 ++ kms++/inc/kms++/framebuffer.h | 40 ++++ kms++/inc/kms++/kms++.h | 15 ++ kms++/inc/kms++/modedb.h | 16 ++ kms++/inc/kms++/pagefliphandler.h | 11 + kms++/inc/kms++/pipeline.h | 11 + kms++/inc/kms++/pixelformats.h | 63 ++++++ kms++/inc/kms++/plane.h | 41 ++++ kms++/inc/kms++/property.h | 44 ++++ kms++/inc/kms++/videomode.h | 36 ++++ kms++/kms++.h | 15 -- kms++/modedb.cpp | 42 ---- kms++/modedb.h | 16 -- kms++/modedb_cea.cpp | 401 ------------------------------------- kms++/modedb_dmt.cpp | 410 -------------------------------------- kms++/pagefliphandler.h | 11 - kms++/pipeline.h | 11 - kms++/pixelformats.cpp | 32 --- kms++/pixelformats.h | 63 ------ kms++/plane.cpp | 105 ---------- kms++/plane.h | 41 ---- kms++/property.cpp | 87 -------- kms++/property.h | 44 ---- kms++/src/atomicreq.cpp | 92 +++++++++ kms++/src/blob.cpp | 51 +++++ kms++/src/card.cpp | 239 ++++++++++++++++++++++ kms++/src/connector.cpp | 224 +++++++++++++++++++++ kms++/src/crtc.cpp | 140 +++++++++++++ kms++/src/drmobject.cpp | 34 ++++ kms++/src/drmpropobject.cpp | 86 ++++++++ kms++/src/dumbframebuffer.cpp | 137 +++++++++++++ kms++/src/encoder.cpp | 77 +++++++ kms++/src/extframebuffer.cpp | 68 +++++++ kms++/src/framebuffer.cpp | 42 ++++ kms++/src/helpers.cpp | 72 +++++++ kms++/src/helpers.h | 12 ++ kms++/src/modedb.cpp | 41 ++++ kms++/src/modedb_cea.cpp | 401 +++++++++++++++++++++++++++++++++++++ kms++/src/modedb_dmt.cpp | 410 ++++++++++++++++++++++++++++++++++++++ kms++/src/pixelformats.cpp | 32 +++ kms++/src/plane.cpp | 105 ++++++++++ kms++/src/property.cpp | 87 ++++++++ kms++/src/videomode.cpp | 19 ++ kms++/videomode.cpp | 19 -- kms++/videomode.h | 36 ---- kms++util/colorbar.cpp | 2 +- kms++util/cpuframebuffer.h | 2 +- kms++util/drawing.cpp | 2 +- kms++util/extcpuframebuffer.h | 2 +- kms++util/kms++util.h | 2 +- kms++util/testpat.cpp | 2 +- kmscube/cube-gbm.cpp | 2 +- py/pykms.cpp | 2 +- py/pykmsbase.cpp | 2 +- py/pykmsutil.cpp | 2 +- utils/kmsblank.cpp | 2 +- utils/kmscapture.cpp | 2 +- utils/kmsprint.cpp | 2 +- utils/kmsview.cpp | 2 +- utils/testpat.cpp | 4 +- 96 files changed, 3084 insertions(+), 3083 deletions(-) delete mode 100644 kms++/atomicreq.cpp delete mode 100644 kms++/atomicreq.h delete mode 100644 kms++/blob.cpp delete mode 100644 kms++/blob.h delete mode 100644 kms++/card.cpp delete mode 100644 kms++/card.h delete mode 100644 kms++/connector.cpp delete mode 100644 kms++/connector.h delete mode 100644 kms++/crtc.cpp delete mode 100644 kms++/crtc.h delete mode 100644 kms++/decls.h delete mode 100644 kms++/drmobject.cpp delete mode 100644 kms++/drmobject.h delete mode 100644 kms++/drmpropobject.cpp delete mode 100644 kms++/drmpropobject.h delete mode 100644 kms++/dumbframebuffer.cpp delete mode 100644 kms++/dumbframebuffer.h delete mode 100644 kms++/encoder.cpp delete mode 100644 kms++/encoder.h delete mode 100644 kms++/extframebuffer.cpp delete mode 100644 kms++/extframebuffer.h delete mode 100644 kms++/framebuffer.cpp delete mode 100644 kms++/framebuffer.h delete mode 100644 kms++/helpers.cpp delete mode 100644 kms++/helpers.h create mode 100644 kms++/inc/kms++/atomicreq.h create mode 100644 kms++/inc/kms++/blob.h create mode 100644 kms++/inc/kms++/card.h create mode 100644 kms++/inc/kms++/connector.h create mode 100644 kms++/inc/kms++/crtc.h create mode 100644 kms++/inc/kms++/decls.h create mode 100644 kms++/inc/kms++/drmobject.h create mode 100644 kms++/inc/kms++/drmpropobject.h create mode 100644 kms++/inc/kms++/dumbframebuffer.h create mode 100644 kms++/inc/kms++/encoder.h create mode 100644 kms++/inc/kms++/extframebuffer.h create mode 100644 kms++/inc/kms++/framebuffer.h create mode 100644 kms++/inc/kms++/kms++.h create mode 100644 kms++/inc/kms++/modedb.h create mode 100644 kms++/inc/kms++/pagefliphandler.h create mode 100644 kms++/inc/kms++/pipeline.h create mode 100644 kms++/inc/kms++/pixelformats.h create mode 100644 kms++/inc/kms++/plane.h create mode 100644 kms++/inc/kms++/property.h create mode 100644 kms++/inc/kms++/videomode.h delete mode 100644 kms++/kms++.h delete mode 100644 kms++/modedb.cpp delete mode 100644 kms++/modedb.h delete mode 100644 kms++/modedb_cea.cpp delete mode 100644 kms++/modedb_dmt.cpp delete mode 100644 kms++/pagefliphandler.h delete mode 100644 kms++/pipeline.h delete mode 100644 kms++/pixelformats.cpp delete mode 100644 kms++/pixelformats.h delete mode 100644 kms++/plane.cpp delete mode 100644 kms++/plane.h delete mode 100644 kms++/property.cpp delete mode 100644 kms++/property.h create mode 100644 kms++/src/atomicreq.cpp create mode 100644 kms++/src/blob.cpp create mode 100644 kms++/src/card.cpp create mode 100644 kms++/src/connector.cpp create mode 100644 kms++/src/crtc.cpp create mode 100644 kms++/src/drmobject.cpp create mode 100644 kms++/src/drmpropobject.cpp create mode 100644 kms++/src/dumbframebuffer.cpp create mode 100644 kms++/src/encoder.cpp create mode 100644 kms++/src/extframebuffer.cpp create mode 100644 kms++/src/framebuffer.cpp create mode 100644 kms++/src/helpers.cpp create mode 100644 kms++/src/helpers.h create mode 100644 kms++/src/modedb.cpp create mode 100644 kms++/src/modedb_cea.cpp create mode 100644 kms++/src/modedb_dmt.cpp create mode 100644 kms++/src/pixelformats.cpp create mode 100644 kms++/src/plane.cpp create mode 100644 kms++/src/property.cpp create mode 100644 kms++/src/videomode.cpp delete mode 100644 kms++/videomode.cpp delete mode 100644 kms++/videomode.h diff --git a/kms++/CMakeLists.txt b/kms++/CMakeLists.txt index 4409b8b..d983964 100644 --- a/kms++/CMakeLists.txt +++ b/kms++/CMakeLists.txt @@ -1,8 +1,12 @@ include_directories(${LIBDRM_INCLUDE_DIRS}) link_directories(${LIBDRM_LIBRARY_DIRS}) -file(GLOB SRCS "*.cpp" "*.h") +file(GLOB SRCS "src/*.cpp" "src/*.h" "inc/kms++/*.h") add_library(kms++ ${SRCS}) +target_include_directories(kms++ PUBLIC + $ + $ + PRIVATE src) + target_link_libraries(kms++ ${LIBDRM_LIBRARIES}) -target_include_directories(kms++ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/kms++/atomicreq.cpp b/kms++/atomicreq.cpp deleted file mode 100644 index 3aa2ff6..0000000 --- a/kms++/atomicreq.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include - -#include -#include - -#include "atomicreq.h" -#include "property.h" -#include "card.h" - -#ifndef DRM_CLIENT_CAP_ATOMIC - -#define DRM_MODE_ATOMIC_TEST_ONLY 0 -#define DRM_MODE_ATOMIC_NONBLOCK 0 - -struct _drmModeAtomicReq; -typedef struct _drmModeAtomicReq* drmModeAtomicReqPtr; - -static inline drmModeAtomicReqPtr drmModeAtomicAlloc() { return 0; } -static inline void drmModeAtomicFree(drmModeAtomicReqPtr) { } -static inline int drmModeAtomicAddProperty(drmModeAtomicReqPtr, uint32_t, uint32_t, uint64_t) { return 0; } -static inline int drmModeAtomicCommit(int, drmModeAtomicReqPtr, int, void*) { return 0; } - -#endif // DRM_CLIENT_CAP_ATOMIC - -using namespace std; - -namespace kms -{ -AtomicReq::AtomicReq(Card& card) - : m_card(card) -{ - assert(card.has_atomic()); - m_req = drmModeAtomicAlloc(); -} - -AtomicReq::~AtomicReq() -{ - drmModeAtomicFree(m_req); -} - -void AtomicReq::add(uint32_t ob_id, uint32_t prop_id, uint64_t value) -{ - int r = drmModeAtomicAddProperty(m_req, ob_id, prop_id, value); - if (r <= 0) - throw std::invalid_argument("foo"); -} - -void AtomicReq::add(DrmObject *ob, Property *prop, uint64_t value) -{ - add(ob->id(), prop->id(), value); -} - -void AtomicReq::add(DrmObject* ob, const string& prop, uint64_t value) -{ - add(ob, m_card.get_prop(prop), value); -} - -void AtomicReq::add(DrmObject* ob, const map& values) -{ - for(const auto& kvp : values) - add(ob, kvp.first, kvp.second); -} - -int AtomicReq::test(bool allow_modeset) -{ - uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY; - - if (allow_modeset) - flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; - - return drmModeAtomicCommit(m_card.fd(), m_req, flags, 0); -} - -int AtomicReq::commit(void* data, bool allow_modeset) -{ - uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; - - if (allow_modeset) - flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; - - return drmModeAtomicCommit(m_card.fd(), m_req, flags, data); -} - -int AtomicReq::commit_sync(bool allow_modeset) -{ - uint32_t flags = 0; - - if (allow_modeset) - flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; - - return drmModeAtomicCommit(m_card.fd(), m_req, flags, 0); -} -} diff --git a/kms++/atomicreq.h b/kms++/atomicreq.h deleted file mode 100644 index 6ebdbf8..0000000 --- a/kms++/atomicreq.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include -#include - -struct _drmModeAtomicReq; - -#include "decls.h" - -namespace kms -{ -class AtomicReq -{ -public: - AtomicReq(Card& card); - ~AtomicReq(); - - AtomicReq(const AtomicReq& other) = delete; - AtomicReq& operator=(const AtomicReq& other) = delete; - - void add(uint32_t ob_id, uint32_t prop_id, uint64_t value); - void add(DrmObject *ob, Property *prop, uint64_t value); - void add(DrmObject *ob, const std::string& prop, uint64_t value); - void add(DrmObject *ob, const std::map& values); - - int test(bool allow_modeset = false); - int commit(void* data, bool allow_modeset = false); - int commit_sync(bool allow_modeset = false); - -private: - Card& m_card; - _drmModeAtomicReq* m_req; -}; - -} diff --git a/kms++/blob.cpp b/kms++/blob.cpp deleted file mode 100644 index 10a71c6..0000000 --- a/kms++/blob.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -Blob::Blob(Card& card, uint32_t blob_id) - : DrmObject(card, blob_id, DRM_MODE_OBJECT_BLOB), m_created(false) -{ - // XXX should we verify that the blob_id is a blob object? -} - -Blob::Blob(Card& card, void* data, size_t len) - : DrmObject(card, DRM_MODE_OBJECT_BLOB), m_created(true) -{ - uint32_t id; - - int r = drmModeCreatePropertyBlob(card.fd(), data, len, &id); - if (r) - throw invalid_argument("FAILED TO CREATE PROP\n"); - - set_id(id); -} - -Blob::~Blob() -{ - if (m_created) - drmModeDestroyPropertyBlob(card().fd(), id()); -} - -vector Blob::data() -{ - drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(card().fd(), id()); - - if (!blob) - throw invalid_argument("Blob data not available"); - - uint8_t* data = (uint8_t*)blob->data; - - auto v = vector(data, data + blob->length); - - drmModeFreePropertyBlob(blob); - - return v; -} - -} diff --git a/kms++/blob.h b/kms++/blob.h deleted file mode 100644 index fd872f1..0000000 --- a/kms++/blob.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "drmobject.h" -#include - -namespace kms -{ - -class Blob : public DrmObject -{ -public: - Blob(Card& card, uint32_t blob_id); - Blob(Card& card, void* data, size_t len); - virtual ~Blob(); - - std::vector data(); - -private: - bool m_created; -}; - -} diff --git a/kms++/card.cpp b/kms++/card.cpp deleted file mode 100644 index 918c825..0000000 --- a/kms++/card.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -Card::Card() - : Card("/dev/dri/card0") -{ -} - - -Card::Card(const std::string& device) -{ - int fd = open(device.c_str(), O_RDWR | O_CLOEXEC); - if (fd < 0) - throw invalid_argument(string(strerror(errno)) + " opening " + device); - m_fd = fd; - - int r; - - r = drmSetMaster(fd); - m_master = r == 0; - - if (getenv("KMSXX_DISABLE_UNIVERSAL_PLANES") == 0) { - r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); - m_has_universal_planes = r == 0; - } else { - m_has_universal_planes = false; - } - -#ifdef DRM_CLIENT_CAP_ATOMIC - if (getenv("KMSXX_DISABLE_ATOMIC") == 0) { - r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1); - m_has_atomic = r == 0; - } else { - m_has_atomic = false; - } -#else - m_has_atomic = false; -#endif - - uint64_t has_dumb; - r = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb); - if (r || !has_dumb) - throw invalid_argument("Dumb buffers not available"); - - auto res = drmModeGetResources(m_fd); - if (!res) - throw invalid_argument("Can't get card resources"); - - for (int i = 0; i < res->count_connectors; ++i) { - uint32_t id = res->connectors[i]; - auto ob = new Connector(*this, id, i); - m_obmap[id] = ob; - m_connectors.push_back(ob); - } - - for (int i = 0; i < res->count_crtcs; ++i) { - uint32_t id = res->crtcs[i]; - auto ob = new Crtc(*this, id, i); - m_obmap[id] = ob; - m_crtcs.push_back(ob); - } - - for (int i = 0; i < res->count_encoders; ++i) { - uint32_t id = res->encoders[i]; - auto ob = new Encoder(*this, id, i); - m_obmap[id] = ob; - m_encoders.push_back(ob); - } - - drmModeFreeResources(res); - - auto planeRes = drmModeGetPlaneResources(m_fd); - - for (uint i = 0; i < planeRes->count_planes; ++i) { - uint32_t id = planeRes->planes[i]; - auto ob = new Plane(*this, id, i); - m_obmap[id] = ob; - m_planes.push_back(ob); - } - - drmModeFreePlaneResources(planeRes); - - // collect all possible props - for (auto ob : get_objects()) { - auto props = drmModeObjectGetProperties(m_fd, ob->id(), ob->object_type()); - - if (props == nullptr) - continue; - - for (unsigned i = 0; i < props->count_props; ++i) { - uint32_t prop_id = props->props[i]; - - if (m_obmap.find(prop_id) == m_obmap.end()) { - auto ob = new Property(*this, prop_id); - m_obmap[prop_id] = ob; - m_properties.push_back(ob); - } - } - - drmModeFreeObjectProperties(props); - } - - for (auto pair : m_obmap) - pair.second->setup(); -} - -Card::~Card() -{ - restore_modes(); - - while (m_framebuffers.size() > 0) - delete m_framebuffers.back(); - - for (auto pair : m_obmap) - delete pair.second; - - close(m_fd); -} - -void Card::drop_master() -{ - drmDropMaster(fd()); -} - -void Card::restore_modes() -{ - for (auto conn : get_connectors()) - conn->restore_mode(); -} - -Property* Card::get_prop(const string& name) const -{ - for (auto prop : m_properties) { - if (name == prop->name()) - return prop; - } - - throw invalid_argument(string("Card property ") + name + " not found"); -} - -Connector* Card::get_first_connected_connector() const -{ - for(auto c : m_connectors) { - if (c->connected()) - return c; - } - - throw invalid_argument("no connected connectors"); -} - -DrmObject* Card::get_object(uint32_t id) const -{ - auto iter = m_obmap.find(id); - if (iter != m_obmap.end()) - return iter->second; - return nullptr; -} - -const vector Card::get_objects() const -{ - vector v; - for(auto pair : m_obmap) - v.push_back(pair.second); - return v; -} - -Connector* Card::get_connector(uint32_t id) const { return dynamic_cast(get_object(id)); } -Crtc* Card::get_crtc(uint32_t id) const { return dynamic_cast(get_object(id)); } -Encoder* Card::get_encoder(uint32_t id) const { return dynamic_cast(get_object(id)); } -Property* Card::get_prop(uint32_t id) const { return dynamic_cast(get_object(id)); } -Plane* Card::get_plane(uint32_t id) const { return dynamic_cast(get_object(id)); } - -std::vector Card::get_connected_pipelines() -{ - vector outputs; - - for (auto conn : get_connectors()) - { - if (conn->connected() == false) - continue; - - Crtc* crtc = conn->get_current_crtc(); - - if (!crtc) { - for (auto possible : conn->get_possible_crtcs()) { - if (find_if(outputs.begin(), outputs.end(), [possible](Pipeline out) { return out.crtc == possible; }) == outputs.end()) { - crtc = possible; - break; - } - } - } - - if (!crtc) - throw invalid_argument(string("Connector #") + - to_string(conn->idx()) + - " has no possible crtcs"); - - outputs.push_back(Pipeline { crtc, conn }); - } - - return outputs; -} - -static void page_flip_handler(int fd, unsigned int frame, - unsigned int sec, unsigned int usec, - void *data) -{ - auto handler = (PageFlipHandlerBase*)data; - double time = sec + usec / 1000000.0; - handler->handle_page_flip(frame, time); -} - -void Card::call_page_flip_handlers() -{ - drmEventContext ev = { - .version = DRM_EVENT_CONTEXT_VERSION, - .vblank_handler = 0, - .page_flip_handler = page_flip_handler, - }; - - drmHandleEvent(fd(), &ev); -} - -} diff --git a/kms++/card.h b/kms++/card.h deleted file mode 100644 index 5ecaecf..0000000 --- a/kms++/card.h +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "decls.h" -#include "pipeline.h" - -namespace kms -{ -class Card -{ - friend class Framebuffer; -public: - Card(); - Card(const std::string& device); - ~Card(); - - Card(const Card& other) = delete; - Card& operator=(const Card& other) = delete; - - int fd() const { return m_fd; } - - void drop_master(); - - Connector* get_first_connected_connector() const; - - DrmObject* get_object(uint32_t id) const; - Connector* get_connector(uint32_t id) const; - Crtc* get_crtc(uint32_t id) const; - Encoder* get_encoder(uint32_t id) const; - Plane* get_plane(uint32_t id) const; - Property* get_prop(uint32_t id) const; - Property* get_prop(const std::string& name) const; - - bool master() const { return m_master; } - bool has_atomic() const { return m_has_atomic; } - bool has_has_universal_planes() const { return m_has_universal_planes; } - - const std::vector get_connectors() const { return m_connectors; } - const std::vector get_encoders() const { return m_encoders; } - const std::vector get_crtcs() const { return m_crtcs; } - const std::vector get_planes() const { return m_planes; } - const std::vector get_properties() const { return m_properties; } - - const std::vector get_objects() const; - - std::vector get_connected_pipelines(); - - void call_page_flip_handlers(); - -private: - void restore_modes(); - - std::map m_obmap; - - std::vector m_connectors; - std::vector m_encoders; - std::vector m_crtcs; - std::vector m_planes; - std::vector m_properties; - std::vector m_framebuffers; - - int m_fd; - bool m_master; - - bool m_has_atomic; - bool m_has_universal_planes; -}; -} diff --git a/kms++/connector.cpp b/kms++/connector.cpp deleted file mode 100644 index 0f471e1..0000000 --- a/kms++/connector.cpp +++ /dev/null @@ -1,224 +0,0 @@ -#include -#include -#include -#include -#include - -#include "kms++.h" -#include "helpers.h" - -using namespace std; - -namespace kms -{ - - -static const map connector_names = { - { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "Composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "S-Video" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "Component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-Pin-DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, - { DRM_MODE_CONNECTOR_TV, "TV" }, - { DRM_MODE_CONNECTOR_eDP, "eDP" }, - { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, - { DRM_MODE_CONNECTOR_DSI, "DSI" }, -}; - -static const map connection_str = { - { 0, "" }, - { DRM_MODE_CONNECTED, "Connected" }, - { DRM_MODE_DISCONNECTED, "Disconnected" }, - { DRM_MODE_UNKNOWNCONNECTION, "Unknown" }, -}; - -static const map subpix_str = { -#define DEF_SUBPIX(c) { DRM_MODE_SUBPIXEL_##c, #c } - DEF_SUBPIX(UNKNOWN), - DEF_SUBPIX(HORIZONTAL_RGB), - DEF_SUBPIX(HORIZONTAL_BGR), - DEF_SUBPIX(VERTICAL_RGB), - DEF_SUBPIX(VERTICAL_BGR), - DEF_SUBPIX(NONE), -#undef DEF_SUBPIX -}; - -struct ConnectorPriv -{ - drmModeConnectorPtr drm_connector; -}; - -Connector::Connector(Card &card, uint32_t id, uint32_t idx) - :DrmPropObject(card, id, DRM_MODE_OBJECT_CONNECTOR, idx) -{ - m_priv = new ConnectorPriv(); - - m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id()); - assert(m_priv->drm_connector); - - // XXX drmModeGetConnector() does forced probe, which seems to change (at least) EDID blob id. - // XXX So refresh the props again here. - refresh_props(); - - const auto& name = connector_names.at(m_priv->drm_connector->connector_type); - m_fullname = name + "-" + to_string(m_priv->drm_connector->connector_type_id); -} - - -Connector::~Connector() -{ - drmModeFreeConnector(m_priv->drm_connector); - delete m_priv; -} - -void Connector::setup() -{ - if (m_priv->drm_connector->encoder_id != 0) - m_current_encoder = card().get_encoder(m_priv->drm_connector->encoder_id); - else - m_current_encoder = 0; - - if (m_current_encoder) - m_saved_crtc = m_current_encoder->get_crtc(); - else - m_saved_crtc = 0; -} - -void Connector::restore_mode() -{ - if (m_saved_crtc) - m_saved_crtc->restore_mode(this); -} - -Videomode Connector::get_default_mode() const -{ - if (m_priv->drm_connector->count_modes == 0) - throw invalid_argument("no modes available\n"); - drmModeModeInfo drmmode = m_priv->drm_connector->modes[0]; - - return drm_mode_to_video_mode(drmmode); -} - -Videomode Connector::get_mode(const string& mode) const -{ - auto c = m_priv->drm_connector; - - for (int i = 0; i < c->count_modes; i++) - if (mode == c->modes[i].name) - return drm_mode_to_video_mode(c->modes[i]); - - throw invalid_argument(mode + ": mode not found"); -} - -Videomode Connector::get_mode(unsigned xres, unsigned yres, unsigned refresh, bool ilace) const -{ - auto c = m_priv->drm_connector; - - for (int i = 0; i < c->count_modes; i++) { - drmModeModeInfo& m = c->modes[i]; - - if (m.hdisplay != xres || m.vdisplay != yres) - continue; - - if (refresh && m.vrefresh != refresh) - continue; - - if (ilace != !!(m.flags & DRM_MODE_FLAG_INTERLACE)) - continue; - - return drm_mode_to_video_mode(c->modes[i]); - } - - throw invalid_argument("mode not found"); -} - -bool Connector::connected() const -{ - return m_priv->drm_connector->connection == DRM_MODE_CONNECTED || - m_priv->drm_connector->connection == DRM_MODE_UNKNOWNCONNECTION; -} - -vector Connector::get_possible_crtcs() const -{ - vector crtcs; - - for (int i = 0; i < m_priv->drm_connector->count_encoders; ++i) { - auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]); - - auto l = enc->get_possible_crtcs(); - - crtcs.insert(crtcs.end(), l.begin(), l.end()); - } - - return crtcs; -} - -Crtc* Connector::get_current_crtc() const -{ - if (m_current_encoder) - return m_current_encoder->get_crtc(); - else - return 0; -} - -uint32_t Connector::connector_type() const -{ - return m_priv->drm_connector->connector_type; -} - -uint32_t Connector::connector_type_id() const -{ - return m_priv->drm_connector->connector_type_id; -} - -uint32_t Connector::mmWidth() const -{ - return m_priv->drm_connector->mmWidth; -} - -uint32_t Connector::mmHeight() const -{ - return m_priv->drm_connector->mmHeight; -} - -uint32_t Connector::subpixel() const -{ - return m_priv->drm_connector->subpixel; -} - -const string& Connector::subpixel_str() const -{ - return subpix_str.at(subpixel()); -} - -std::vector Connector::get_modes() const -{ - vector modes; - - for (int i = 0; i < m_priv->drm_connector->count_modes; i++) - modes.push_back(drm_mode_to_video_mode( - m_priv->drm_connector->modes[i])); - - return modes; -} - -std::vector Connector::get_encoders() const -{ - vector encoders; - - for (int i = 0; i < m_priv->drm_connector->count_encoders; i++) { - auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]); - encoders.push_back(enc); - } - return encoders; -} - -} diff --git a/kms++/connector.h b/kms++/connector.h deleted file mode 100644 index 6ccc959..0000000 --- a/kms++/connector.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include - -#include "drmpropobject.h" -#include "videomode.h" - -namespace kms -{ - -struct ConnectorPriv; - -class Connector : public DrmPropObject -{ - friend class Card; -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; - - Crtc* get_current_crtc() const; - std::vector get_possible_crtcs() const; - - bool connected() const; - - const std::string& fullname() const { return m_fullname; } - uint32_t connector_type() const; - uint32_t connector_type_id() const; - uint32_t mmWidth() const; - uint32_t mmHeight() const; - uint32_t subpixel() const; - const std::string& subpixel_str() const; - std::vector get_modes() const; - std::vector get_encoders() const; -private: - Connector(Card& card, uint32_t id, uint32_t idx); - ~Connector(); - - void setup(); - void restore_mode(); - - ConnectorPriv* m_priv; - - std::string m_fullname; - - Encoder* m_current_encoder; - - Crtc* m_saved_crtc; -}; -} diff --git a/kms++/crtc.cpp b/kms++/crtc.cpp deleted file mode 100644 index 6cbdf0c..0000000 --- a/kms++/crtc.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include -#include -#include -#include -#include - -#include "kms++.h" -#include "helpers.h" - -using namespace std; - -namespace kms -{ - -struct CrtcPriv -{ - drmModeCrtcPtr drm_crtc; -}; - -Crtc::Crtc(Card &card, uint32_t id, uint32_t idx) - :DrmPropObject(card, id, DRM_MODE_OBJECT_CRTC, idx) -{ - m_priv = new CrtcPriv(); - m_priv->drm_crtc = drmModeGetCrtc(this->card().fd(), this->id()); - assert(m_priv->drm_crtc); -} - -Crtc::~Crtc() -{ - drmModeFreeCrtc(m_priv->drm_crtc); - delete m_priv; -} - -void Crtc::setup() -{ - for (Plane* plane : card().get_planes()) { - if (plane->supports_crtc(this)) - m_possible_planes.push_back(plane); - } -} - -void Crtc::restore_mode(Connector* conn) -{ - auto c = m_priv->drm_crtc; - - uint32_t conns[] = { conn->id() }; - - drmModeSetCrtc(card().fd(), id(), c->buffer_id, - c->x, c->y, - conns, 1, &c->mode); -} - -int Crtc::set_mode(Connector* conn, Framebuffer& fb, const Videomode& mode) -{ - uint32_t conns[] = { conn->id() }; - drmModeModeInfo drmmode = video_mode_to_drm_mode(mode); - - return drmModeSetCrtc(card().fd(), id(), fb.id(), - 0, 0, - conns, 1, &drmmode); -} - -static inline uint32_t conv(float x) -{ - // XXX fix the conversion for fractional part - return ((uint32_t)x) << 16; -} - -int Crtc::set_plane(Plane* plane, Framebuffer& fb, - int32_t dst_x, int32_t dst_y, uint32_t dst_w, uint32_t dst_h, - float src_x, float src_y, float src_w, float src_h) -{ - return drmModeSetPlane(card().fd(), plane->id(), id(), fb.id(), 0, - dst_x, dst_y, dst_w, dst_h, - conv(src_x), conv(src_y), conv(src_w), conv(src_h)); -} - -int Crtc::disable_plane(Plane* plane) -{ - return drmModeSetPlane(card().fd(), plane->id(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); -} - -Plane* Crtc::get_primary_plane() -{ - for (Plane* p : get_possible_planes()) { - if (p->plane_type() != PlaneType::Primary) - continue; - - return p; - } - - throw invalid_argument(string("No primary plane for crtc ") + to_string(id())); -} - -int Crtc::page_flip(Framebuffer& fb, void *data) -{ - return drmModePageFlip(card().fd(), id(), fb.id(), DRM_MODE_PAGE_FLIP_EVENT, data); -} - -uint32_t Crtc::buffer_id() const -{ - return m_priv->drm_crtc->buffer_id; -} - -uint32_t Crtc::x() const -{ - return m_priv->drm_crtc->x; -} - -uint32_t Crtc::y() const -{ - return m_priv->drm_crtc->y; -} - -uint32_t Crtc::width() const -{ - return m_priv->drm_crtc->width; -} - -uint32_t Crtc::height() const -{ - return m_priv->drm_crtc->height; -} - -int Crtc::mode_valid() const -{ - return m_priv->drm_crtc->mode_valid; -} - -Videomode Crtc::mode() const -{ - return drm_mode_to_video_mode(m_priv->drm_crtc->mode); -} - -int Crtc::gamma_size() const -{ - return m_priv->drm_crtc->gamma_size; -} - -} diff --git a/kms++/crtc.h b/kms++/crtc.h deleted file mode 100644 index f3b525a..0000000 --- a/kms++/crtc.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include - -#include "drmpropobject.h" - -namespace kms -{ - -struct CrtcPriv; - -class Crtc : public DrmPropObject -{ - friend class Card; - friend class Connector; -public: - const std::vector& get_possible_planes() const { return m_possible_planes; } - - int set_mode(Connector* conn, Framebuffer& fb, const Videomode& mode); - - int set_plane(Plane *plane, Framebuffer &fb, - int32_t dst_x, int32_t dst_y, uint32_t dst_w, uint32_t dst_h, - float src_x, float src_y, float src_w, float src_h); - - int disable_plane(Plane* plane); - - Plane* get_primary_plane(); - - int page_flip(Framebuffer& fb, void *data); - - uint32_t buffer_id() const; - uint32_t x() const; - uint32_t y() const; - uint32_t width() const; - uint32_t height() const; - int mode_valid() const; - Videomode mode() const; - int gamma_size() const; -private: - Crtc(Card& card, uint32_t id, uint32_t idx); - ~Crtc(); - - void setup(); - void restore_mode(Connector *conn); - - CrtcPriv* m_priv; - - std::vector m_possible_planes; -}; -} diff --git a/kms++/decls.h b/kms++/decls.h deleted file mode 100644 index e84b29a..0000000 --- a/kms++/decls.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -namespace kms -{ -class AtomicReq; -class Card; -class Connector; -class Crtc; -class Encoder; -class Framebuffer; -class DumbFramebuffer; -class ExtFramebuffer; -class DrmObject; -class PageFlipHandlerBase; -class Plane; -class Property; -class Blob; -struct Videomode; -} diff --git a/kms++/drmobject.cpp b/kms++/drmobject.cpp deleted file mode 100644 index 8abecc7..0000000 --- a/kms++/drmobject.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include - -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -DrmObject::DrmObject(Card& card, uint32_t object_type) - :m_card(card), m_id(-1), m_object_type(object_type), m_idx(0) -{ -} - -DrmObject::DrmObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx) - :m_card(card), m_id(id), m_object_type(object_type), m_idx(idx) -{ -} - -DrmObject::~DrmObject() -{ - -} - -void DrmObject::set_id(uint32_t id) -{ - m_id = id; -} -} diff --git a/kms++/drmobject.h b/kms++/drmobject.h deleted file mode 100644 index a939aa7..0000000 --- a/kms++/drmobject.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include - -#include "decls.h" - -namespace kms -{ - -class DrmObject -{ - friend class Card; -public: - DrmObject(const DrmObject& other) = delete; - DrmObject& operator=(const DrmObject& other) = delete; - - uint32_t id() const { return m_id; } - Card& card() const { return m_card; } - - uint32_t object_type() const { return m_object_type; } - uint32_t idx() const { return m_idx; } - -protected: - DrmObject(Card& card, uint32_t object_type); - DrmObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx = 0); - - virtual ~DrmObject(); - - virtual void setup() { } - - virtual void set_id(uint32_t id); - -private: - Card& m_card; - - uint32_t m_id; - uint32_t m_object_type; - uint32_t m_idx; -}; -} diff --git a/kms++/drmpropobject.cpp b/kms++/drmpropobject.cpp deleted file mode 100644 index 50f87a7..0000000 --- a/kms++/drmpropobject.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -DrmPropObject::DrmPropObject(Card& card, uint32_t object_type) - : DrmObject(card, object_type) -{ -} - -DrmPropObject::DrmPropObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx) - : DrmObject(card, id, object_type, idx) -{ - refresh_props(); -} - -DrmPropObject::~DrmPropObject() -{ - -} - -void DrmPropObject::refresh_props() -{ - auto props = drmModeObjectGetProperties(card().fd(), this->id(), this->object_type()); - - if (props == nullptr) - return; - - for (unsigned i = 0; i < props->count_props; ++i) { - uint32_t prop_id = props->props[i]; - uint64_t prop_value = props->prop_values[i]; - - m_prop_values[prop_id] = prop_value; - } - - drmModeFreeObjectProperties(props); -} - -uint64_t DrmPropObject::get_prop_value(uint32_t id) const -{ - return m_prop_values.at(id); -} - -uint64_t DrmPropObject::get_prop_value(const string& name) const -{ - for (auto pair : m_prop_values) { - auto prop = card().get_prop(pair.first); - if (name == prop->name()) - return m_prop_values.at(prop->id()); - } - - throw invalid_argument("property not found: " + name); -} - -unique_ptr DrmPropObject::get_prop_value_as_blob(const string& name) const -{ - uint32_t blob_id = (uint32_t)get_prop_value(name); - - return unique_ptr(new Blob(card(), blob_id)); -} - -int DrmPropObject::set_prop_value(uint32_t id, uint64_t value) -{ - return drmModeObjectSetProperty(card().fd(), this->id(), this->object_type(), id, value); -} - -int DrmPropObject::set_prop_value(const string &name, uint64_t value) -{ - Property* prop = card().get_prop(name); - - if (prop == nullptr) - throw invalid_argument("property not found: " + name); - - return set_prop_value(prop->id(), value); -} - -} diff --git a/kms++/drmpropobject.h b/kms++/drmpropobject.h deleted file mode 100644 index ec28d45..0000000 --- a/kms++/drmpropobject.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include - -#include "drmobject.h" -#include "decls.h" - -namespace kms -{ - -class DrmPropObject : public DrmObject -{ - friend class Card; -public: - void refresh_props(); - uint64_t get_prop_value(uint32_t id) const; - uint64_t get_prop_value(const std::string& name) const; - std::unique_ptr get_prop_value_as_blob(const std::string& name) const; - - const std::map& get_prop_map() const { return m_prop_values; } - - int set_prop_value(uint32_t id, uint64_t value); - int set_prop_value(const std::string& name, uint64_t value); - -protected: - DrmPropObject(Card& card, uint32_t object_type); - DrmPropObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx = 0); - - virtual ~DrmPropObject(); - -private: - std::map m_prop_values; -}; -} diff --git a/kms++/dumbframebuffer.cpp b/kms++/dumbframebuffer.cpp deleted file mode 100644 index fcd01d0..0000000 --- a/kms++/dumbframebuffer.cpp +++ /dev/null @@ -1,137 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "kms++.h" - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -using namespace std; - -namespace kms -{ - -DumbFramebuffer::DumbFramebuffer(Card &card, uint32_t width, uint32_t height, const string& fourcc) - :DumbFramebuffer(card, width, height, FourCCToPixelFormat(fourcc)) -{ -} - -DumbFramebuffer::DumbFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format) - :Framebuffer(card, width, height), m_format(format) -{ - Create(); -} - -DumbFramebuffer::~DumbFramebuffer() -{ - Destroy(); -} - -void DumbFramebuffer::Create() -{ - int r; - - const PixelFormatInfo& format_info = get_pixel_format_info(m_format); - - m_num_planes = format_info.num_planes; - - for (int i = 0; i < format_info.num_planes; ++i) { - const PixelFormatPlaneInfo& pi = format_info.planes[i]; - FramebufferPlane& plane = m_planes[i]; - - /* create dumb buffer */ - struct drm_mode_create_dumb creq = drm_mode_create_dumb(); - creq.width = width(); - creq.height = height() / pi.ysub; - creq.bpp = pi.bitspp; - r = drmIoctl(card().fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq); - if (r) - throw invalid_argument(string("DRM_IOCTL_MODE_CREATE_DUMB failed") + strerror(errno)); - - plane.handle = creq.handle; - plane.stride = creq.pitch; - plane.size = creq.height * creq.pitch; - plane.offset = 0; - plane.map = 0; - plane.prime_fd = -1; - } - - /* create framebuffer object for the dumb-buffer */ - uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle }; - uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride }; - uint32_t offsets[4] = { m_planes[0].offset, m_planes[1].offset }; - uint32_t id; - r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(), - bo_handles, pitches, offsets, &id, 0); - if (r) - throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); - - set_id(id); -} - -void DumbFramebuffer::Destroy() -{ - /* delete framebuffer */ - drmModeRmFB(card().fd(), id()); - - for (uint i = 0; i < m_num_planes; ++i) { - FramebufferPlane& plane = m_planes[i]; - - /* unmap buffer */ - if (plane.map) - munmap(plane.map, plane.size); - - /* delete dumb buffer */ - struct drm_mode_destroy_dumb dreq = drm_mode_destroy_dumb(); - dreq.handle = plane.handle; - drmIoctl(card().fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); - if (plane.prime_fd >= 0) - ::close(plane.prime_fd); - } -} - -uint8_t* DumbFramebuffer::map(unsigned plane) -{ - FramebufferPlane& p = m_planes[plane]; - - if (p.map) - return p.map; - - /* prepare buffer for memory mapping */ - struct drm_mode_map_dumb mreq = drm_mode_map_dumb(); - mreq.handle = p.handle; - int r = drmIoctl(card().fd(), DRM_IOCTL_MODE_MAP_DUMB, &mreq); - if (r) - throw invalid_argument(string("DRM_IOCTL_MODE_MAP_DUMB failed") + strerror(errno)); - - /* perform actual memory mapping */ - p.map = (uint8_t *)mmap(0, p.size, PROT_READ | PROT_WRITE, MAP_SHARED, - card().fd(), mreq.offset); - if (p.map == MAP_FAILED) - throw invalid_argument(string("mmap failed: ") + strerror(errno)); - - return p.map; -} - -int DumbFramebuffer::prime_fd(unsigned int plane) -{ - if (m_planes[plane].prime_fd >= 0) - return m_planes[plane].prime_fd; - - int r = drmPrimeHandleToFD(card().fd(), m_planes[plane].handle, - DRM_CLOEXEC, &m_planes[plane].prime_fd); - if (r) - throw std::runtime_error("drmPrimeHandleToFD failed"); - - return m_planes[plane].prime_fd; -} - -} diff --git a/kms++/dumbframebuffer.h b/kms++/dumbframebuffer.h deleted file mode 100644 index 6b3ee64..0000000 --- a/kms++/dumbframebuffer.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "framebuffer.h" -#include "pixelformats.h" - -namespace kms -{ -class DumbFramebuffer : public Framebuffer, public IMappedFramebuffer -{ -public: - DumbFramebuffer(Card& card, uint32_t width, uint32_t height, const std::string& fourcc); - DumbFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format); - virtual ~DumbFramebuffer(); - - uint32_t width() const { return Framebuffer::width(); } - uint32_t height() const { return Framebuffer::height(); } - - PixelFormat format() const { return m_format; } - unsigned num_planes() const { return m_num_planes; } - - uint32_t handle(unsigned plane) const { return m_planes[plane].handle; } - uint32_t stride(unsigned plane) const { return m_planes[plane].stride; } - uint32_t size(unsigned plane) const { return m_planes[plane].size; } - uint32_t offset(unsigned plane) const { return m_planes[plane].offset; } - uint8_t* map(unsigned plane); - int prime_fd(unsigned plane); - -private: - struct FramebufferPlane { - uint32_t handle; - int prime_fd; - uint32_t size; - uint32_t stride; - uint32_t offset; - uint8_t *map; - }; - - void Create(); - void Destroy(); - - unsigned m_num_planes; - struct FramebufferPlane m_planes[4]; - - PixelFormat m_format; -}; -} diff --git a/kms++/encoder.cpp b/kms++/encoder.cpp deleted file mode 100644 index 1ed2d5c..0000000 --- a/kms++/encoder.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -struct EncoderPriv -{ - drmModeEncoderPtr drm_encoder; -}; - -static const map encoder_types = { -#define DEF_ENC(c) { DRM_MODE_ENCODER_##c, #c } - DEF_ENC(NONE), - DEF_ENC(DAC), - DEF_ENC(TMDS), - DEF_ENC(LVDS), - DEF_ENC(TVDAC), - DEF_ENC(VIRTUAL), - DEF_ENC(DSI), - { 7, "DPMST" }, -#undef DEF_ENC -}; - -Encoder::Encoder(Card &card, uint32_t id, uint32_t idx) - :DrmPropObject(card, id, DRM_MODE_OBJECT_ENCODER, idx) -{ - m_priv = new EncoderPriv(); - m_priv->drm_encoder = drmModeGetEncoder(this->card().fd(), this->id()); - assert(m_priv->drm_encoder); -} - -Encoder::~Encoder() -{ - drmModeFreeEncoder(m_priv->drm_encoder); - delete m_priv; -} - -Crtc* Encoder::get_crtc() const -{ - if (m_priv->drm_encoder->crtc_id) - return card().get_crtc(m_priv->drm_encoder->crtc_id); - else - return 0; -} - -vector Encoder::get_possible_crtcs() const -{ - unsigned bits = m_priv->drm_encoder->possible_crtcs; - vector crtcs; - - for (int idx = 0; bits; idx++, bits >>= 1) { - if ((bits & 1) == 0) - continue; - - auto crtc = card().get_crtcs()[idx]; - crtcs.push_back(crtc); - } - - return crtcs; -} - -const string& Encoder::get_encoder_type() const -{ - return encoder_types.at(m_priv->drm_encoder->encoder_type); -} - -} diff --git a/kms++/encoder.h b/kms++/encoder.h deleted file mode 100644 index b5aac70..0000000 --- a/kms++/encoder.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include "drmpropobject.h" - -namespace kms -{ - -struct EncoderPriv; - -class Encoder : public DrmPropObject -{ - friend class Card; -public: - Crtc* get_crtc() const; - std::vector get_possible_crtcs() const; - - const std::string& get_encoder_type() const; -private: - Encoder(Card& card, uint32_t id, uint32_t idx); - ~Encoder(); - - EncoderPriv* m_priv; -}; -} diff --git a/kms++/extframebuffer.cpp b/kms++/extframebuffer.cpp deleted file mode 100644 index 352c1a7..0000000 --- a/kms++/extframebuffer.cpp +++ /dev/null @@ -1,68 +0,0 @@ - -#include -#include -#include -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t stride, uint32_t handle) - :Framebuffer(card, width, height) -{ - uint32_t id; - int r = drmModeAddFB(card.fd(), width, height, depth, bpp, stride, handle, &id); - if (r) - throw invalid_argument("fob"); - - set_id(id); -} - -ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, - uint32_t handles[], uint32_t pitches[], uint32_t offsets[]) - : Framebuffer(card, width, height) -{ - uint32_t id; - int r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, handles, pitches, offsets, &id, 0); - if (r) - throw std::invalid_argument(string("Failed to create ExtFramebuffer: ") + strerror(r)); - - set_id(id); -} - -ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, - int fds[4], uint32_t pitches[4], uint32_t offsets[4]) - : Framebuffer(card, width, height) -{ - int r; - - const PixelFormatInfo& format_info = get_pixel_format_info(format); - - uint32_t handles[4] = { 0 }; - - for (int i = 0; i < format_info.num_planes; ++i) { - r = drmPrimeFDToHandle(card.fd(), fds[i], &handles[i]); - if (r) - throw invalid_argument(string("drmPrimeFDToHandle: ") + strerror(errno)); - } - - uint32_t id; - r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, - handles, pitches, offsets, &id, 0); - if (r) - throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); - - set_id(id); -} - -ExtFramebuffer::~ExtFramebuffer() -{ - drmModeRmFB(card().fd(), id()); -} - -} diff --git a/kms++/extframebuffer.h b/kms++/extframebuffer.h deleted file mode 100644 index eab7e3c..0000000 --- a/kms++/extframebuffer.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "framebuffer.h" -#include "pixelformats.h" - -namespace kms -{ - -class ExtFramebuffer : public Framebuffer -{ -public: - ExtFramebuffer(Card& card, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t stride, uint32_t handle); - ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, - uint32_t handles[4], uint32_t pitches[4], uint32_t offsets[4]); - ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, - int fds[4], uint32_t pitches[4], uint32_t offsets[4]); - virtual ~ExtFramebuffer(); - -private: -}; -} diff --git a/kms++/framebuffer.cpp b/kms++/framebuffer.cpp deleted file mode 100644 index bf9ab01..0000000 --- a/kms++/framebuffer.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -Framebuffer::Framebuffer(Card& card, uint32_t width, uint32_t height) - : DrmObject(card, DRM_MODE_OBJECT_FB), m_width(width), m_height(height) -{ - card.m_framebuffers.push_back(this); -} - -Framebuffer::Framebuffer(Card& card, uint32_t id) - : DrmObject(card, id, DRM_MODE_OBJECT_FB) -{ - auto fb = drmModeGetFB(card.fd(), id); - - m_width = fb->width; - m_height = fb->height; - - drmModeFreeFB(fb); - - card.m_framebuffers.push_back(this); -} - -Framebuffer::~Framebuffer() -{ - auto& fbs = card().m_framebuffers; - auto iter = find(fbs.begin(), fbs.end(), this); - card().m_framebuffers.erase(iter); -} - - -} diff --git a/kms++/framebuffer.h b/kms++/framebuffer.h deleted file mode 100644 index cbf705d..0000000 --- a/kms++/framebuffer.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "drmobject.h" -#include "pixelformats.h" - -namespace kms -{ -class Framebuffer : public DrmObject -{ -public: - Framebuffer(Card& card, uint32_t id); - virtual ~Framebuffer(); - - uint32_t width() const { return m_width; } - uint32_t height() const { return m_height; } -protected: - Framebuffer(Card& card, uint32_t width, uint32_t height); - -private: - uint32_t m_width; - uint32_t m_height; -}; - -class IMappedFramebuffer { -public: - virtual ~IMappedFramebuffer() { } - - virtual uint32_t width() const = 0; - virtual uint32_t height() const = 0; - - virtual PixelFormat format() const = 0; - virtual unsigned num_planes() const = 0; - - virtual uint32_t stride(unsigned plane) const = 0; - virtual uint32_t size(unsigned plane) const = 0; - virtual uint32_t offset(unsigned plane) const = 0; - virtual uint8_t* map(unsigned plane) = 0; -}; - -} diff --git a/kms++/helpers.cpp b/kms++/helpers.cpp deleted file mode 100644 index 715e757..0000000 --- a/kms++/helpers.cpp +++ /dev/null @@ -1,72 +0,0 @@ - -#include "connector.h" -#include "helpers.h" -#include - -#define CPY(field) dst.field = src.field - -namespace kms -{ -Videomode drm_mode_to_video_mode(const drmModeModeInfo& drmmode) -{ - Videomode mode = { }; - - auto& src = drmmode; - auto& dst = mode; - - CPY(clock); - - CPY(hdisplay); - CPY(hsync_start); - CPY(hsync_end); - CPY(htotal); - CPY(hskew); - - CPY(vdisplay); - CPY(vsync_start); - CPY(vsync_end); - CPY(vtotal); - CPY(vscan); - - CPY(vrefresh); - - CPY(flags); - CPY(type); - - mode.name = drmmode.name; - - return mode; -} - -drmModeModeInfo video_mode_to_drm_mode(const Videomode& mode) -{ - drmModeModeInfo drmmode = { }; - - auto& src = mode; - auto& dst = drmmode; - - CPY(clock); - - CPY(hdisplay); - CPY(hsync_start); - CPY(hsync_end); - CPY(htotal); - CPY(hskew); - - CPY(vdisplay); - CPY(vsync_start); - CPY(vsync_end); - CPY(vtotal); - CPY(vscan); - - CPY(vrefresh); - - CPY(flags); - CPY(type); - - strncpy(drmmode.name, mode.name.c_str(), sizeof(drmmode.name)); - drmmode.name[sizeof(drmmode.name) - 1] = 0; - - return drmmode; -} -} diff --git a/kms++/helpers.h b/kms++/helpers.h deleted file mode 100644 index 4eb597c..0000000 --- a/kms++/helpers.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include - -namespace kms -{ -struct Videomode; - -Videomode drm_mode_to_video_mode(const drmModeModeInfo& drmmode); -drmModeModeInfo video_mode_to_drm_mode(const Videomode& mode); -} diff --git a/kms++/inc/kms++/atomicreq.h b/kms++/inc/kms++/atomicreq.h new file mode 100644 index 0000000..6ebdbf8 --- /dev/null +++ b/kms++/inc/kms++/atomicreq.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + +struct _drmModeAtomicReq; + +#include "decls.h" + +namespace kms +{ +class AtomicReq +{ +public: + AtomicReq(Card& card); + ~AtomicReq(); + + AtomicReq(const AtomicReq& other) = delete; + AtomicReq& operator=(const AtomicReq& other) = delete; + + void add(uint32_t ob_id, uint32_t prop_id, uint64_t value); + void add(DrmObject *ob, Property *prop, uint64_t value); + void add(DrmObject *ob, const std::string& prop, uint64_t value); + void add(DrmObject *ob, const std::map& values); + + int test(bool allow_modeset = false); + int commit(void* data, bool allow_modeset = false); + int commit_sync(bool allow_modeset = false); + +private: + Card& m_card; + _drmModeAtomicReq* m_req; +}; + +} diff --git a/kms++/inc/kms++/blob.h b/kms++/inc/kms++/blob.h new file mode 100644 index 0000000..fd872f1 --- /dev/null +++ b/kms++/inc/kms++/blob.h @@ -0,0 +1,22 @@ +#pragma once + +#include "drmobject.h" +#include + +namespace kms +{ + +class Blob : public DrmObject +{ +public: + Blob(Card& card, uint32_t blob_id); + Blob(Card& card, void* data, size_t len); + virtual ~Blob(); + + std::vector data(); + +private: + bool m_created; +}; + +} diff --git a/kms++/inc/kms++/card.h b/kms++/inc/kms++/card.h new file mode 100644 index 0000000..5ecaecf --- /dev/null +++ b/kms++/inc/kms++/card.h @@ -0,0 +1,71 @@ +#pragma once + +#include +#include +#include + +#include "decls.h" +#include "pipeline.h" + +namespace kms +{ +class Card +{ + friend class Framebuffer; +public: + Card(); + Card(const std::string& device); + ~Card(); + + Card(const Card& other) = delete; + Card& operator=(const Card& other) = delete; + + int fd() const { return m_fd; } + + void drop_master(); + + Connector* get_first_connected_connector() const; + + DrmObject* get_object(uint32_t id) const; + Connector* get_connector(uint32_t id) const; + Crtc* get_crtc(uint32_t id) const; + Encoder* get_encoder(uint32_t id) const; + Plane* get_plane(uint32_t id) const; + Property* get_prop(uint32_t id) const; + Property* get_prop(const std::string& name) const; + + bool master() const { return m_master; } + bool has_atomic() const { return m_has_atomic; } + bool has_has_universal_planes() const { return m_has_universal_planes; } + + const std::vector get_connectors() const { return m_connectors; } + const std::vector get_encoders() const { return m_encoders; } + const std::vector get_crtcs() const { return m_crtcs; } + const std::vector get_planes() const { return m_planes; } + const std::vector get_properties() const { return m_properties; } + + const std::vector get_objects() const; + + std::vector get_connected_pipelines(); + + void call_page_flip_handlers(); + +private: + void restore_modes(); + + std::map m_obmap; + + std::vector m_connectors; + std::vector m_encoders; + std::vector m_crtcs; + std::vector m_planes; + std::vector m_properties; + std::vector m_framebuffers; + + int m_fd; + bool m_master; + + bool m_has_atomic; + bool m_has_universal_planes; +}; +} diff --git a/kms++/inc/kms++/connector.h b/kms++/inc/kms++/connector.h new file mode 100644 index 0000000..6ccc959 --- /dev/null +++ b/kms++/inc/kms++/connector.h @@ -0,0 +1,51 @@ +#pragma once + +#include + +#include "drmpropobject.h" +#include "videomode.h" + +namespace kms +{ + +struct ConnectorPriv; + +class Connector : public DrmPropObject +{ + friend class Card; +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; + + Crtc* get_current_crtc() const; + std::vector get_possible_crtcs() const; + + bool connected() const; + + const std::string& fullname() const { return m_fullname; } + uint32_t connector_type() const; + uint32_t connector_type_id() const; + uint32_t mmWidth() const; + uint32_t mmHeight() const; + uint32_t subpixel() const; + const std::string& subpixel_str() const; + std::vector get_modes() const; + std::vector get_encoders() const; +private: + Connector(Card& card, uint32_t id, uint32_t idx); + ~Connector(); + + void setup(); + void restore_mode(); + + ConnectorPriv* m_priv; + + std::string m_fullname; + + Encoder* m_current_encoder; + + Crtc* m_saved_crtc; +}; +} diff --git a/kms++/inc/kms++/crtc.h b/kms++/inc/kms++/crtc.h new file mode 100644 index 0000000..f3b525a --- /dev/null +++ b/kms++/inc/kms++/crtc.h @@ -0,0 +1,50 @@ +#pragma once + +#include + +#include "drmpropobject.h" + +namespace kms +{ + +struct CrtcPriv; + +class Crtc : public DrmPropObject +{ + friend class Card; + friend class Connector; +public: + const std::vector& get_possible_planes() const { return m_possible_planes; } + + int set_mode(Connector* conn, Framebuffer& fb, const Videomode& mode); + + int set_plane(Plane *plane, Framebuffer &fb, + int32_t dst_x, int32_t dst_y, uint32_t dst_w, uint32_t dst_h, + float src_x, float src_y, float src_w, float src_h); + + int disable_plane(Plane* plane); + + Plane* get_primary_plane(); + + int page_flip(Framebuffer& fb, void *data); + + uint32_t buffer_id() const; + uint32_t x() const; + uint32_t y() const; + uint32_t width() const; + uint32_t height() const; + int mode_valid() const; + Videomode mode() const; + int gamma_size() const; +private: + Crtc(Card& card, uint32_t id, uint32_t idx); + ~Crtc(); + + void setup(); + void restore_mode(Connector *conn); + + CrtcPriv* m_priv; + + std::vector m_possible_planes; +}; +} diff --git a/kms++/inc/kms++/decls.h b/kms++/inc/kms++/decls.h new file mode 100644 index 0000000..e84b29a --- /dev/null +++ b/kms++/inc/kms++/decls.h @@ -0,0 +1,19 @@ +#pragma once + +namespace kms +{ +class AtomicReq; +class Card; +class Connector; +class Crtc; +class Encoder; +class Framebuffer; +class DumbFramebuffer; +class ExtFramebuffer; +class DrmObject; +class PageFlipHandlerBase; +class Plane; +class Property; +class Blob; +struct Videomode; +} diff --git a/kms++/inc/kms++/drmobject.h b/kms++/inc/kms++/drmobject.h new file mode 100644 index 0000000..a939aa7 --- /dev/null +++ b/kms++/inc/kms++/drmobject.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "decls.h" + +namespace kms +{ + +class DrmObject +{ + friend class Card; +public: + DrmObject(const DrmObject& other) = delete; + DrmObject& operator=(const DrmObject& other) = delete; + + uint32_t id() const { return m_id; } + Card& card() const { return m_card; } + + uint32_t object_type() const { return m_object_type; } + uint32_t idx() const { return m_idx; } + +protected: + DrmObject(Card& card, uint32_t object_type); + DrmObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx = 0); + + virtual ~DrmObject(); + + virtual void setup() { } + + virtual void set_id(uint32_t id); + +private: + Card& m_card; + + uint32_t m_id; + uint32_t m_object_type; + uint32_t m_idx; +}; +} diff --git a/kms++/inc/kms++/drmpropobject.h b/kms++/inc/kms++/drmpropobject.h new file mode 100644 index 0000000..ec28d45 --- /dev/null +++ b/kms++/inc/kms++/drmpropobject.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include "drmobject.h" +#include "decls.h" + +namespace kms +{ + +class DrmPropObject : public DrmObject +{ + friend class Card; +public: + void refresh_props(); + uint64_t get_prop_value(uint32_t id) const; + uint64_t get_prop_value(const std::string& name) const; + std::unique_ptr get_prop_value_as_blob(const std::string& name) const; + + const std::map& get_prop_map() const { return m_prop_values; } + + int set_prop_value(uint32_t id, uint64_t value); + int set_prop_value(const std::string& name, uint64_t value); + +protected: + DrmPropObject(Card& card, uint32_t object_type); + DrmPropObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx = 0); + + virtual ~DrmPropObject(); + +private: + std::map m_prop_values; +}; +} diff --git a/kms++/inc/kms++/dumbframebuffer.h b/kms++/inc/kms++/dumbframebuffer.h new file mode 100644 index 0000000..6b3ee64 --- /dev/null +++ b/kms++/inc/kms++/dumbframebuffer.h @@ -0,0 +1,46 @@ +#pragma once + +#include "framebuffer.h" +#include "pixelformats.h" + +namespace kms +{ +class DumbFramebuffer : public Framebuffer, public IMappedFramebuffer +{ +public: + DumbFramebuffer(Card& card, uint32_t width, uint32_t height, const std::string& fourcc); + DumbFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format); + virtual ~DumbFramebuffer(); + + uint32_t width() const { return Framebuffer::width(); } + uint32_t height() const { return Framebuffer::height(); } + + PixelFormat format() const { return m_format; } + unsigned num_planes() const { return m_num_planes; } + + uint32_t handle(unsigned plane) const { return m_planes[plane].handle; } + uint32_t stride(unsigned plane) const { return m_planes[plane].stride; } + uint32_t size(unsigned plane) const { return m_planes[plane].size; } + uint32_t offset(unsigned plane) const { return m_planes[plane].offset; } + uint8_t* map(unsigned plane); + int prime_fd(unsigned plane); + +private: + struct FramebufferPlane { + uint32_t handle; + int prime_fd; + uint32_t size; + uint32_t stride; + uint32_t offset; + uint8_t *map; + }; + + void Create(); + void Destroy(); + + unsigned m_num_planes; + struct FramebufferPlane m_planes[4]; + + PixelFormat m_format; +}; +} diff --git a/kms++/inc/kms++/encoder.h b/kms++/inc/kms++/encoder.h new file mode 100644 index 0000000..b5aac70 --- /dev/null +++ b/kms++/inc/kms++/encoder.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include "drmpropobject.h" + +namespace kms +{ + +struct EncoderPriv; + +class Encoder : public DrmPropObject +{ + friend class Card; +public: + Crtc* get_crtc() const; + std::vector get_possible_crtcs() const; + + const std::string& get_encoder_type() const; +private: + Encoder(Card& card, uint32_t id, uint32_t idx); + ~Encoder(); + + EncoderPriv* m_priv; +}; +} diff --git a/kms++/inc/kms++/extframebuffer.h b/kms++/inc/kms++/extframebuffer.h new file mode 100644 index 0000000..eab7e3c --- /dev/null +++ b/kms++/inc/kms++/extframebuffer.h @@ -0,0 +1,21 @@ +#pragma once + +#include "framebuffer.h" +#include "pixelformats.h" + +namespace kms +{ + +class ExtFramebuffer : public Framebuffer +{ +public: + ExtFramebuffer(Card& card, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t stride, uint32_t handle); + ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, + uint32_t handles[4], uint32_t pitches[4], uint32_t offsets[4]); + ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, + int fds[4], uint32_t pitches[4], uint32_t offsets[4]); + virtual ~ExtFramebuffer(); + +private: +}; +} diff --git a/kms++/inc/kms++/framebuffer.h b/kms++/inc/kms++/framebuffer.h new file mode 100644 index 0000000..cbf705d --- /dev/null +++ b/kms++/inc/kms++/framebuffer.h @@ -0,0 +1,40 @@ +#pragma once + +#include "drmobject.h" +#include "pixelformats.h" + +namespace kms +{ +class Framebuffer : public DrmObject +{ +public: + Framebuffer(Card& card, uint32_t id); + virtual ~Framebuffer(); + + uint32_t width() const { return m_width; } + uint32_t height() const { return m_height; } +protected: + Framebuffer(Card& card, uint32_t width, uint32_t height); + +private: + uint32_t m_width; + uint32_t m_height; +}; + +class IMappedFramebuffer { +public: + virtual ~IMappedFramebuffer() { } + + virtual uint32_t width() const = 0; + virtual uint32_t height() const = 0; + + virtual PixelFormat format() const = 0; + virtual unsigned num_planes() const = 0; + + virtual uint32_t stride(unsigned plane) const = 0; + virtual uint32_t size(unsigned plane) const = 0; + virtual uint32_t offset(unsigned plane) const = 0; + virtual uint8_t* map(unsigned plane) = 0; +}; + +} diff --git a/kms++/inc/kms++/kms++.h b/kms++/inc/kms++/kms++.h new file mode 100644 index 0000000..3365ef7 --- /dev/null +++ b/kms++/inc/kms++/kms++.h @@ -0,0 +1,15 @@ +#pragma once + +#include "atomicreq.h" +#include "card.h" +#include "connector.h" +#include "crtc.h" +#include "encoder.h" +#include "framebuffer.h" +#include "dumbframebuffer.h" +#include "extframebuffer.h" +#include "plane.h" +#include "property.h" +#include "blob.h" +#include "pipeline.h" +#include "pagefliphandler.h" diff --git a/kms++/inc/kms++/modedb.h b/kms++/inc/kms++/modedb.h new file mode 100644 index 0000000..43c7afc --- /dev/null +++ b/kms++/inc/kms++/modedb.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include "videomode.h" + +namespace kms +{ +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); + +} diff --git a/kms++/inc/kms++/pagefliphandler.h b/kms++/inc/kms++/pagefliphandler.h new file mode 100644 index 0000000..79cda0d --- /dev/null +++ b/kms++/inc/kms++/pagefliphandler.h @@ -0,0 +1,11 @@ +#pragma once + +namespace kms { +class PageFlipHandlerBase +{ +public: + PageFlipHandlerBase() { } + virtual ~PageFlipHandlerBase() { } + virtual void handle_page_flip(uint32_t frame, double time) = 0; +}; +} diff --git a/kms++/inc/kms++/pipeline.h b/kms++/inc/kms++/pipeline.h new file mode 100644 index 0000000..ef04ec1 --- /dev/null +++ b/kms++/inc/kms++/pipeline.h @@ -0,0 +1,11 @@ +#pragma once + +#include "decls.h" + +namespace kms +{ +struct Pipeline { + Crtc* crtc; + Connector* connector; +}; +} diff --git a/kms++/inc/kms++/pixelformats.h b/kms++/inc/kms++/pixelformats.h new file mode 100644 index 0000000..813eaef --- /dev/null +++ b/kms++/inc/kms++/pixelformats.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include + +namespace kms +{ +constexpr uint32_t MakeFourCC(const char *fourcc) +{ + return fourcc[0] | (fourcc[1] << 8) | (fourcc[2] << 16) | (fourcc[3] << 24); +} + +enum class PixelFormat : uint32_t +{ + Undefined = 0, + + NV12 = MakeFourCC("NV12"), + NV21 = MakeFourCC("NV21"), + + UYVY = MakeFourCC("UYVY"), + YUYV = MakeFourCC("YUYV"), + YVYU = MakeFourCC("YVYU"), + VYUY = MakeFourCC("VYUY"), + + XRGB8888 = MakeFourCC("XR24"), + XBGR8888 = MakeFourCC("XB24"), + ARGB8888 = MakeFourCC("AR24"), + ABGR8888 = MakeFourCC("AB24"), + + RGB565 = MakeFourCC("RG16"), +}; + +static inline PixelFormat FourCCToPixelFormat(const std::string& fourcc) +{ + return (PixelFormat)MakeFourCC(fourcc.c_str()); +} + +static inline std::string PixelFormatToFourCC(PixelFormat f) +{ + char buf[5] = { (char)(((int)f >> 0) & 0xff), + (char)(((int)f >> 8) & 0xff), + (char)(((int)f >> 16) & 0xff), + (char)(((int)f >> 24) & 0xff), + 0 }; + return std::string(buf); +} + +struct PixelFormatPlaneInfo +{ + uint8_t bitspp; + uint8_t xsub; + uint8_t ysub; +}; + +struct PixelFormatInfo +{ + uint8_t num_planes; + struct PixelFormatPlaneInfo planes[4]; +}; + +const struct PixelFormatInfo& get_pixel_format_info(PixelFormat format); + +} diff --git a/kms++/inc/kms++/plane.h b/kms++/inc/kms++/plane.h new file mode 100644 index 0000000..d50e539 --- /dev/null +++ b/kms++/inc/kms++/plane.h @@ -0,0 +1,41 @@ +#pragma once + +#include "drmpropobject.h" + +namespace kms +{ + +enum class PlaneType +{ + Overlay = 0, + Primary = 1, + Cursor = 2, +}; + +struct PlanePriv; + +class Plane : public DrmPropObject +{ + friend class Card; +public: + bool supports_crtc(Crtc* crtc) const; + bool supports_format(PixelFormat fmt) const; + + PlaneType plane_type() const; + + std::vector get_formats() const; + uint32_t crtc_id() const; + uint32_t fb_id() const; + + uint32_t crtc_x() const; + uint32_t crtc_y() const; + uint32_t x() const; + uint32_t y() const; + uint32_t gamma_size() const; +private: + Plane(Card& card, uint32_t id, uint32_t idx); + ~Plane(); + + PlanePriv* m_priv; +}; +} diff --git a/kms++/inc/kms++/property.h b/kms++/inc/kms++/property.h new file mode 100644 index 0000000..b9097ff --- /dev/null +++ b/kms++/inc/kms++/property.h @@ -0,0 +1,44 @@ +#pragma once + +#include "drmobject.h" +#include +#include + +namespace kms +{ + +struct PropertyPriv; + +enum class PropertyType +{ + Range, + Enum, + Blob, + Bitmask, + Object, + SignedRange, +}; + +class Property : public DrmObject +{ + friend class Card; +public: + const std::string& name() const; + + bool is_immutable() const; + bool is_pending() const; + + PropertyType type() const { return m_type; } + std::map get_enums() const; + std::vector get_values() const; + std::vector get_blob_ids() const; +private: + Property(Card& card, uint32_t id); + ~Property(); + + PropertyType m_type; + + PropertyPriv* m_priv; + std::string m_name; +}; +} diff --git a/kms++/inc/kms++/videomode.h b/kms++/inc/kms++/videomode.h new file mode 100644 index 0000000..f9abaf9 --- /dev/null +++ b/kms++/inc/kms++/videomode.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + +#include "blob.h" + +namespace kms +{ + +struct Videomode +{ + std::string name; + + uint32_t clock; + uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; + uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; + + uint32_t vrefresh; + + uint32_t flags; // DRM_MODE_FLAG_* + uint32_t type; // DRM_MODE_TYPE_* + + std::unique_ptr to_blob(Card& card) const; + + uint16_t hfp() const { return hsync_start - hdisplay; } + uint16_t hsw() const { return hsync_end - hsync_start; } + uint16_t hbp() const { return htotal - hsync_end; } + + 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; } +}; + +} diff --git a/kms++/kms++.h b/kms++/kms++.h deleted file mode 100644 index 3365ef7..0000000 --- a/kms++/kms++.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "atomicreq.h" -#include "card.h" -#include "connector.h" -#include "crtc.h" -#include "encoder.h" -#include "framebuffer.h" -#include "dumbframebuffer.h" -#include "extframebuffer.h" -#include "plane.h" -#include "property.h" -#include "blob.h" -#include "pipeline.h" -#include "pagefliphandler.h" diff --git a/kms++/modedb.cpp b/kms++/modedb.cpp deleted file mode 100644 index 53dcfcf..0000000 --- a/kms++/modedb.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - -#include "modedb.h" -#include "videomode.h" - -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) -{ - for (unsigned i = 0; modes[i].clock; ++i) { - const Videomode& m = modes[i]; - - if (m.hdisplay != width || m.vdisplay != height) - continue; - - if (refresh && m.vrefresh != refresh) - continue; - - if (ilace != !!(m.flags & DRM_MODE_FLAG_INTERLACE)) - continue; - - return m; - } - - throw invalid_argument("mode not found"); -} - -const Videomode& find_dmt(uint32_t width, uint32_t height, uint32_t refresh, bool ilace) -{ - return find_from_table(dmt_modes, width, height, refresh, ilace); -} - -const Videomode& find_cea(uint32_t width, uint32_t height, uint32_t refresh, bool ilace) -{ - return find_from_table(cea_modes, width, height, refresh, ilace); -} - -} diff --git a/kms++/modedb.h b/kms++/modedb.h deleted file mode 100644 index 43c7afc..0000000 --- a/kms++/modedb.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include "videomode.h" - -namespace kms -{ -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); - -} diff --git a/kms++/modedb_cea.cpp b/kms++/modedb_cea.cpp deleted file mode 100644 index a1f4ab9..0000000 --- a/kms++/modedb_cea.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* From Linux kernel: drm_edid.c */ -/* - * Copyright (c) 2006 Luc Verhaegen (quirks list) - * Copyright (c) 2007-2008 Intel Corporation - * Jesse Barnes - * Copyright 2010 Red Hat, Inc. - * - * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from - * FB layer. - * Copyright (C) 2006 Dennis Munsie - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "modedb.h" - -#include - -namespace kms -{ - -#define DIV_ROUND(n, d) (((n) + (d) / 2) / (d)) - -#define DRM_MODE(nm, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ - .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 - -/* - * Probably taken from CEA-861 spec. - * This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c. - */ -const Videomode cea_modes[] = { - /* 1 - 640x480@60Hz */ - { DRM_MODE("640x480", 25175, 640, 656, - 752, 800, 0, 480, 490, 492, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 2 - 720x480@60Hz */ - { DRM_MODE("720x480", 27000, 720, 736, - 798, 858, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 3 - 720x480@60Hz */ - { DRM_MODE("720x480", 27000, 720, 736, - 798, 858, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 4 - 1280x720@60Hz */ - { DRM_MODE("1280x720", 74250, 1280, 1390, - 1430, 1650, 0, 720, 725, 730, 750, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 5 - 1920x1080i@60Hz */ - { DRM_MODE("1920x1080i", 74250, 1920, 2008, - 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 6 - 720(1440)x480i@60Hz */ - { DRM_MODE("720x480i", 13500, 720, 739, - 801, 858, 0, 480, 488, 494, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 7 - 720(1440)x480i@60Hz */ - { DRM_MODE("720x480i", 13500, 720, 739, - 801, 858, 0, 480, 488, 494, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 8 - 720(1440)x240@60Hz */ - { DRM_MODE("720x240", 13500, 720, 739, - 801, 858, 0, 240, 244, 247, 262, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_DBLCLK), - }, - /* 9 - 720(1440)x240@60Hz */ - { DRM_MODE("720x240", 13500, 720, 739, - 801, 858, 0, 240, 244, 247, 262, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_DBLCLK), - }, - /* 10 - 2880x480i@60Hz */ - { DRM_MODE("2880x480i", 54000, 2880, 2956, - 3204, 3432, 0, 480, 488, 494, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 11 - 2880x480i@60Hz */ - { DRM_MODE("2880x480i", 54000, 2880, 2956, - 3204, 3432, 0, 480, 488, 494, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 12 - 2880x240@60Hz */ - { DRM_MODE("2880x240", 54000, 2880, 2956, - 3204, 3432, 0, 240, 244, 247, 262, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 13 - 2880x240@60Hz */ - { DRM_MODE("2880x240", 54000, 2880, 2956, - 3204, 3432, 0, 240, 244, 247, 262, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 14 - 1440x480@60Hz */ - { DRM_MODE("1440x480", 54000, 1440, 1472, - 1596, 1716, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 15 - 1440x480@60Hz */ - { DRM_MODE("1440x480", 54000, 1440, 1472, - 1596, 1716, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 16 - 1920x1080@60Hz */ - { DRM_MODE("1920x1080", 148500, 1920, 2008, - 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 17 - 720x576@50Hz */ - { DRM_MODE("720x576", 27000, 720, 732, - 796, 864, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 18 - 720x576@50Hz */ - { DRM_MODE("720x576", 27000, 720, 732, - 796, 864, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 19 - 1280x720@50Hz */ - { DRM_MODE("1280x720", 74250, 1280, 1720, - 1760, 1980, 0, 720, 725, 730, 750, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 20 - 1920x1080i@50Hz */ - { DRM_MODE("1920x1080i", 74250, 1920, 2448, - 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 21 - 720(1440)x576i@50Hz */ - { DRM_MODE("720x576i", 13500, 720, 732, - 795, 864, 0, 576, 580, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 22 - 720(1440)x576i@50Hz */ - { DRM_MODE("720x576i", 13500, 720, 732, - 795, 864, 0, 576, 580, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 23 - 720(1440)x288@50Hz */ - { DRM_MODE("720x288", 13500, 720, 732, - 795, 864, 0, 288, 290, 293, 312, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_DBLCLK), - }, - /* 24 - 720(1440)x288@50Hz */ - { DRM_MODE("720x288", 13500, 720, 732, - 795, 864, 0, 288, 290, 293, 312, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_DBLCLK), - }, - /* 25 - 2880x576i@50Hz */ - { DRM_MODE("2880x576i", 54000, 2880, 2928, - 3180, 3456, 0, 576, 580, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 26 - 2880x576i@50Hz */ - { DRM_MODE("2880x576i", 54000, 2880, 2928, - 3180, 3456, 0, 576, 580, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 27 - 2880x288@50Hz */ - { DRM_MODE("2880x288", 54000, 2880, 2928, - 3180, 3456, 0, 288, 290, 293, 312, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 28 - 2880x288@50Hz */ - { DRM_MODE("2880x288", 54000, 2880, 2928, - 3180, 3456, 0, 288, 290, 293, 312, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 29 - 1440x576@50Hz */ - { DRM_MODE("1440x576", 54000, 1440, 1464, - 1592, 1728, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 30 - 1440x576@50Hz */ - { DRM_MODE("1440x576", 54000, 1440, 1464, - 1592, 1728, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 31 - 1920x1080@50Hz */ - { DRM_MODE("1920x1080", 148500, 1920, 2448, - 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 32 - 1920x1080@24Hz */ - { DRM_MODE("1920x1080", 74250, 1920, 2558, - 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 33 - 1920x1080@25Hz */ - { DRM_MODE("1920x1080", 74250, 1920, 2448, - 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 34 - 1920x1080@30Hz */ - { DRM_MODE("1920x1080", 74250, 1920, 2008, - 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 35 - 2880x480@60Hz */ - { DRM_MODE("2880x480", 108000, 2880, 2944, - 3192, 3432, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 36 - 2880x480@60Hz */ - { DRM_MODE("2880x480", 108000, 2880, 2944, - 3192, 3432, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 37 - 2880x576@50Hz */ - { DRM_MODE("2880x576", 108000, 2880, 2928, - 3184, 3456, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 38 - 2880x576@50Hz */ - { DRM_MODE("2880x576", 108000, 2880, 2928, - 3184, 3456, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 39 - 1920x1080i@50Hz */ - { DRM_MODE("1920x1080i", 72000, 1920, 1952, - 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 40 - 1920x1080i@100Hz */ - { DRM_MODE("1920x1080i", 148500, 1920, 2448, - 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 41 - 1280x720@100Hz */ - { DRM_MODE("1280x720", 148500, 1280, 1720, - 1760, 1980, 0, 720, 725, 730, 750, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 42 - 720x576@100Hz */ - { DRM_MODE("720x576", 54000, 720, 732, - 796, 864, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 43 - 720x576@100Hz */ - { DRM_MODE("720x576", 54000, 720, 732, - 796, 864, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 44 - 720(1440)x576i@100Hz */ - { DRM_MODE("720x576i", 27000, 720, 732, - 795, 864, 0, 576, 580, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 45 - 720(1440)x576i@100Hz */ - { DRM_MODE("720x576i", 27000, 720, 732, - 795, 864, 0, 576, 580, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 46 - 1920x1080i@120Hz */ - { DRM_MODE("1920x1080i", 148500, 1920, 2008, - 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | - DRM_MODE_FLAG_INTERLACE), - }, - /* 47 - 1280x720@120Hz */ - { DRM_MODE("1280x720", 148500, 1280, 1390, - 1430, 1650, 0, 720, 725, 730, 750, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 48 - 720x480@120Hz */ - { DRM_MODE("720x480", 54000, 720, 736, - 798, 858, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 49 - 720x480@120Hz */ - { DRM_MODE("720x480", 54000, 720, 736, - 798, 858, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 50 - 720(1440)x480i@120Hz */ - { DRM_MODE("720x480i", 27000, 720, 739, - 801, 858, 0, 480, 488, 494, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 51 - 720(1440)x480i@120Hz */ - { DRM_MODE("720x480i", 27000, 720, 739, - 801, 858, 0, 480, 488, 494, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 52 - 720x576@200Hz */ - { DRM_MODE("720x576", 108000, 720, 732, - 796, 864, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 53 - 720x576@200Hz */ - { DRM_MODE("720x576", 108000, 720, 732, - 796, 864, 0, 576, 581, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 54 - 720(1440)x576i@200Hz */ - { DRM_MODE("720x576i", 54000, 720, 732, - 795, 864, 0, 576, 580, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 55 - 720(1440)x576i@200Hz */ - { DRM_MODE("720x576i", 54000, 720, 732, - 795, 864, 0, 576, 580, 586, 625, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 56 - 720x480@240Hz */ - { DRM_MODE("720x480", 108000, 720, 736, - 798, 858, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 57 - 720x480@240Hz */ - { DRM_MODE("720x480", 108000, 720, 736, - 798, 858, 0, 480, 489, 495, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), - }, - /* 58 - 720(1440)x480i@240 */ - { DRM_MODE("720x480i", 54000, 720, 739, - 801, 858, 0, 480, 488, 494, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 59 - 720(1440)x480i@240 */ - { DRM_MODE("720x480i", 54000, 720, 739, - 801, 858, 0, 480, 488, 494, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | - DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - }, - /* 60 - 1280x720@24Hz */ - { DRM_MODE("1280x720", 59400, 1280, 3040, - 3080, 3300, 0, 720, 725, 730, 750, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 61 - 1280x720@25Hz */ - { DRM_MODE("1280x720", 74250, 1280, 3700, - 3740, 3960, 0, 720, 725, 730, 750, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 62 - 1280x720@30Hz */ - { DRM_MODE("1280x720", 74250, 1280, 3040, - 3080, 3300, 0, 720, 725, 730, 750, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 63 - 1920x1080@120Hz */ - { DRM_MODE("1920x1080", 297000, 1920, 2008, - 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* 64 - 1920x1080@100Hz */ - { DRM_MODE("1920x1080", 297000, 1920, 2448, - 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - }, - /* TERMINATOR */ - { }, -}; - -} diff --git a/kms++/modedb_dmt.cpp b/kms++/modedb_dmt.cpp deleted file mode 100644 index 6c74c5e..0000000 --- a/kms++/modedb_dmt.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* From Linux kernel: drm_edid.c */ -/* - * Copyright (c) 2006 Luc Verhaegen (quirks list) - * Copyright (c) 2007-2008 Intel Corporation - * Jesse Barnes - * Copyright 2010 Red Hat, Inc. - * - * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from - * FB layer. - * Copyright (C) 2006 Dennis Munsie - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "modedb.h" - -#include - -namespace kms -{ - -#define DIV_ROUND(n, d) (((n) + (d) / 2) / (d)) - -#define DRM_MODE(nm, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ - .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 - - -/* - * Autogenerated from the DMT spec. - * This table is copied from xfree86/modes/xf86EdidModes.c. - */ -const Videomode dmt_modes[] = { - /* 0x01 - 640x350@85Hz */ - { DRM_MODE("640x350", 31500, 640, 672, - 736, 832, 0, 350, 382, 385, 445, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x02 - 640x400@85Hz */ - { DRM_MODE("640x400", 31500, 640, 672, - 736, 832, 0, 400, 401, 404, 445, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x03 - 720x400@85Hz */ - { DRM_MODE("720x400", 35500, 720, 756, - 828, 936, 0, 400, 401, 404, 446, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x04 - 640x480@60Hz */ - { DRM_MODE("640x480", 25175, 640, 656, - 752, 800, 0, 480, 490, 492, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x05 - 640x480@72Hz */ - { DRM_MODE("640x480", 31500, 640, 664, - 704, 832, 0, 480, 489, 492, 520, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x06 - 640x480@75Hz */ - { DRM_MODE("640x480", 31500, 640, 656, - 720, 840, 0, 480, 481, 484, 500, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x07 - 640x480@85Hz */ - { DRM_MODE("640x480", 36000, 640, 696, - 752, 832, 0, 480, 481, 484, 509, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x08 - 800x600@56Hz */ - { DRM_MODE("800x600", 36000, 800, 824, - 896, 1024, 0, 600, 601, 603, 625, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x09 - 800x600@60Hz */ - { DRM_MODE("800x600", 40000, 800, 840, - 968, 1056, 0, 600, 601, 605, 628, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x0a - 800x600@72Hz */ - { DRM_MODE("800x600", 50000, 800, 856, - 976, 1040, 0, 600, 637, 643, 666, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x0b - 800x600@75Hz */ - { DRM_MODE("800x600", 49500, 800, 816, - 896, 1056, 0, 600, 601, 604, 625, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x0c - 800x600@85Hz */ - { DRM_MODE("800x600", 56250, 800, 832, - 896, 1048, 0, 600, 601, 604, 631, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x0d - 800x600@120Hz RB */ - { DRM_MODE("800x600", 73250, 800, 848, - 880, 960, 0, 600, 603, 607, 636, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x0e - 848x480@60Hz */ - { DRM_MODE("848x480", 33750, 848, 864, - 976, 1088, 0, 480, 486, 494, 517, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x0f - 1024x768@43Hz, interlace */ - { DRM_MODE("1024x768i", 44900, 1024, 1032, - 1208, 1264, 0, 768, 768, 772, 817, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | - DRM_MODE_FLAG_INTERLACE) }, - /* 0x10 - 1024x768@60Hz */ - { DRM_MODE("1024x768", 65000, 1024, 1048, - 1184, 1344, 0, 768, 771, 777, 806, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x11 - 1024x768@70Hz */ - { DRM_MODE("1024x768", 75000, 1024, 1048, - 1184, 1328, 0, 768, 771, 777, 806, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x12 - 1024x768@75Hz */ - { DRM_MODE("1024x768", 78750, 1024, 1040, - 1136, 1312, 0, 768, 769, 772, 800, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x13 - 1024x768@85Hz */ - { DRM_MODE("1024x768", 94500, 1024, 1072, - 1168, 1376, 0, 768, 769, 772, 808, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x14 - 1024x768@120Hz RB */ - { DRM_MODE("1024x768", 115500, 1024, 1072, - 1104, 1184, 0, 768, 771, 775, 813, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x15 - 1152x864@75Hz */ - { DRM_MODE("1152x864", 108000, 1152, 1216, - 1344, 1600, 0, 864, 865, 868, 900, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x55 - 1280x720@60Hz */ - { DRM_MODE("1280x720", 74250, 1280, 1390, - 1430, 1650, 0, 720, 725, 730, 750, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x16 - 1280x768@60Hz RB */ - { DRM_MODE("1280x768", 68250, 1280, 1328, - 1360, 1440, 0, 768, 771, 778, 790, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x17 - 1280x768@60Hz */ - { DRM_MODE("1280x768", 79500, 1280, 1344, - 1472, 1664, 0, 768, 771, 778, 798, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x18 - 1280x768@75Hz */ - { DRM_MODE("1280x768", 102250, 1280, 1360, - 1488, 1696, 0, 768, 771, 778, 805, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x19 - 1280x768@85Hz */ - { DRM_MODE("1280x768", 117500, 1280, 1360, - 1496, 1712, 0, 768, 771, 778, 809, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x1a - 1280x768@120Hz RB */ - { DRM_MODE("1280x768", 140250, 1280, 1328, - 1360, 1440, 0, 768, 771, 778, 813, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x1b - 1280x800@60Hz RB */ - { DRM_MODE("1280x800", 71000, 1280, 1328, - 1360, 1440, 0, 800, 803, 809, 823, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x1c - 1280x800@60Hz */ - { DRM_MODE("1280x800", 83500, 1280, 1352, - 1480, 1680, 0, 800, 803, 809, 831, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x1d - 1280x800@75Hz */ - { DRM_MODE("1280x800", 106500, 1280, 1360, - 1488, 1696, 0, 800, 803, 809, 838, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x1e - 1280x800@85Hz */ - { DRM_MODE("1280x800", 122500, 1280, 1360, - 1496, 1712, 0, 800, 803, 809, 843, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x1f - 1280x800@120Hz RB */ - { DRM_MODE("1280x800", 146250, 1280, 1328, - 1360, 1440, 0, 800, 803, 809, 847, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x20 - 1280x960@60Hz */ - { DRM_MODE("1280x960", 108000, 1280, 1376, - 1488, 1800, 0, 960, 961, 964, 1000, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x21 - 1280x960@85Hz */ - { DRM_MODE("1280x960", 148500, 1280, 1344, - 1504, 1728, 0, 960, 961, 964, 1011, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x22 - 1280x960@120Hz RB */ - { DRM_MODE("1280x960", 175500, 1280, 1328, - 1360, 1440, 0, 960, 963, 967, 1017, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x23 - 1280x1024@60Hz */ - { DRM_MODE("1280x1024", 108000, 1280, 1328, - 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x24 - 1280x1024@75Hz */ - { DRM_MODE("1280x1024", 135000, 1280, 1296, - 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x25 - 1280x1024@85Hz */ - { DRM_MODE("1280x1024", 157500, 1280, 1344, - 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x26 - 1280x1024@120Hz RB */ - { DRM_MODE("1280x1024", 187250, 1280, 1328, - 1360, 1440, 0, 1024, 1027, 1034, 1084, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x27 - 1360x768@60Hz */ - { DRM_MODE("1360x768", 85500, 1360, 1424, - 1536, 1792, 0, 768, 771, 777, 795, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x28 - 1360x768@120Hz RB */ - { DRM_MODE("1360x768", 148250, 1360, 1408, - 1440, 1520, 0, 768, 771, 776, 813, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x51 - 1366x768@60Hz */ - { DRM_MODE("1366x768", 85500, 1366, 1436, - 1579, 1792, 0, 768, 771, 774, 798, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x56 - 1366x768@60Hz */ - { DRM_MODE("1366x768", 72000, 1366, 1380, - 1436, 1500, 0, 768, 769, 772, 800, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x29 - 1400x1050@60Hz RB */ - { DRM_MODE("1400x1050", 101000, 1400, 1448, - 1480, 1560, 0, 1050, 1053, 1057, 1080, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x2a - 1400x1050@60Hz */ - { DRM_MODE("1400x1050", 121750, 1400, 1488, - 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x2b - 1400x1050@75Hz */ - { DRM_MODE("1400x1050", 156000, 1400, 1504, - 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x2c - 1400x1050@85Hz */ - { DRM_MODE("1400x1050", 179500, 1400, 1504, - 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x2d - 1400x1050@120Hz RB */ - { DRM_MODE("1400x1050", 208000, 1400, 1448, - 1480, 1560, 0, 1050, 1053, 1057, 1112, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x2e - 1440x900@60Hz RB */ - { DRM_MODE("1440x900", 88750, 1440, 1488, - 1520, 1600, 0, 900, 903, 909, 926, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x2f - 1440x900@60Hz */ - { DRM_MODE("1440x900", 106500, 1440, 1520, - 1672, 1904, 0, 900, 903, 909, 934, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x30 - 1440x900@75Hz */ - { DRM_MODE("1440x900", 136750, 1440, 1536, - 1688, 1936, 0, 900, 903, 909, 942, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x31 - 1440x900@85Hz */ - { DRM_MODE("1440x900", 157000, 1440, 1544, - 1696, 1952, 0, 900, 903, 909, 948, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x32 - 1440x900@120Hz RB */ - { DRM_MODE("1440x900", 182750, 1440, 1488, - 1520, 1600, 0, 900, 903, 909, 953, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x53 - 1600x900@60Hz */ - { DRM_MODE("1600x900", 108000, 1600, 1624, - 1704, 1800, 0, 900, 901, 904, 1000, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x33 - 1600x1200@60Hz */ - { DRM_MODE("1600x1200", 162000, 1600, 1664, - 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x34 - 1600x1200@65Hz */ - { DRM_MODE("1600x1200", 175500, 1600, 1664, - 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x35 - 1600x1200@70Hz */ - { DRM_MODE("1600x1200", 189000, 1600, 1664, - 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x36 - 1600x1200@75Hz */ - { DRM_MODE("1600x1200", 202500, 1600, 1664, - 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x37 - 1600x1200@85Hz */ - { DRM_MODE("1600x1200", 229500, 1600, 1664, - 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x38 - 1600x1200@120Hz RB */ - { DRM_MODE("1600x1200", 268250, 1600, 1648, - 1680, 1760, 0, 1200, 1203, 1207, 1271, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x39 - 1680x1050@60Hz RB */ - { DRM_MODE("1680x1050", 119000, 1680, 1728, - 1760, 1840, 0, 1050, 1053, 1059, 1080, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x3a - 1680x1050@60Hz */ - { DRM_MODE("1680x1050", 146250, 1680, 1784, - 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x3b - 1680x1050@75Hz */ - { DRM_MODE("1680x1050", 187000, 1680, 1800, - 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x3c - 1680x1050@85Hz */ - { DRM_MODE("1680x1050", 214750, 1680, 1808, - 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x3d - 1680x1050@120Hz RB */ - { DRM_MODE("1680x1050", 245500, 1680, 1728, - 1760, 1840, 0, 1050, 1053, 1059, 1112, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x3e - 1792x1344@60Hz */ - { DRM_MODE("1792x1344", 204750, 1792, 1920, - 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x3f - 1792x1344@75Hz */ - { DRM_MODE("1792x1344", 261000, 1792, 1888, - 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x40 - 1792x1344@120Hz RB */ - { DRM_MODE("1792x1344", 333250, 1792, 1840, - 1872, 1952, 0, 1344, 1347, 1351, 1423, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x41 - 1856x1392@60Hz */ - { DRM_MODE("1856x1392", 218250, 1856, 1952, - 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x42 - 1856x1392@75Hz */ - { DRM_MODE("1856x1392", 288000, 1856, 1984, - 2208, 2560, 0, 1392, 1393, 1396, 1500, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x43 - 1856x1392@120Hz RB */ - { DRM_MODE("1856x1392", 356500, 1856, 1904, - 1936, 2016, 0, 1392, 1395, 1399, 1474, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x52 - 1920x1080@60Hz */ - { DRM_MODE("1920x1080", 148500, 1920, 2008, - 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x44 - 1920x1200@60Hz RB */ - { DRM_MODE("1920x1200", 154000, 1920, 1968, - 2000, 2080, 0, 1200, 1203, 1209, 1235, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x45 - 1920x1200@60Hz */ - { DRM_MODE("1920x1200", 193250, 1920, 2056, - 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x46 - 1920x1200@75Hz */ - { DRM_MODE("1920x1200", 245250, 1920, 2056, - 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x47 - 1920x1200@85Hz */ - { DRM_MODE("1920x1200", 281250, 1920, 2064, - 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x48 - 1920x1200@120Hz RB */ - { DRM_MODE("1920x1200", 317000, 1920, 1968, - 2000, 2080, 0, 1200, 1203, 1209, 1271, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x49 - 1920x1440@60Hz */ - { DRM_MODE("1920x1440", 234000, 1920, 2048, - 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x4a - 1920x1440@75Hz */ - { DRM_MODE("1920x1440", 297000, 1920, 2064, - 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x4b - 1920x1440@120Hz RB */ - { DRM_MODE("1920x1440", 380500, 1920, 1968, - 2000, 2080, 0, 1440, 1443, 1447, 1525, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x54 - 2048x1152@60Hz */ - { DRM_MODE("2048x1152", 162000, 2048, 2074, - 2154, 2250, 0, 1152, 1153, 1156, 1200, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x4c - 2560x1600@60Hz RB */ - { DRM_MODE("2560x1600", 268500, 2560, 2608, - 2640, 2720, 0, 1600, 1603, 1609, 1646, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x4d - 2560x1600@60Hz */ - { DRM_MODE("2560x1600", 348500, 2560, 2752, - 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x4e - 2560x1600@75Hz */ - { DRM_MODE("2560x1600", 443250, 2560, 2768, - 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x4f - 2560x1600@85Hz */ - { DRM_MODE("2560x1600", 505250, 2560, 2768, - 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 0x50 - 2560x1600@120Hz RB */ - { DRM_MODE("2560x1600", 552750, 2560, 2608, - 2640, 2720, 0, 1600, 1603, 1609, 1694, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x57 - 4096x2160@60Hz RB */ - { DRM_MODE("4096x2160", 556744, 4096, 4104, - 4136, 4176, 0, 2160, 2208, 2216, 2222, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 0x58 - 4096x2160@59.94Hz RB */ - { DRM_MODE("4096x2160", 556188, 4096, 4104, - 4136, 4176, 0, 2160, 2208, 2216, 2222, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* TERMINATOR */ - { }, -}; - -} diff --git a/kms++/pagefliphandler.h b/kms++/pagefliphandler.h deleted file mode 100644 index 79cda0d..0000000 --- a/kms++/pagefliphandler.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -namespace kms { -class PageFlipHandlerBase -{ -public: - PageFlipHandlerBase() { } - virtual ~PageFlipHandlerBase() { } - virtual void handle_page_flip(uint32_t frame, double time) = 0; -}; -} diff --git a/kms++/pipeline.h b/kms++/pipeline.h deleted file mode 100644 index ef04ec1..0000000 --- a/kms++/pipeline.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "decls.h" - -namespace kms -{ -struct Pipeline { - Crtc* crtc; - Connector* connector; -}; -} diff --git a/kms++/pixelformats.cpp b/kms++/pixelformats.cpp deleted file mode 100644 index 594bd6d..0000000 --- a/kms++/pixelformats.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#include "pixelformats.h" - -using namespace std; - -namespace kms -{ -static const map format_info_array = { - /* YUV packed */ - { PixelFormat::UYVY, { 1, { { 16, 2, 1 } }, } }, - { PixelFormat::YUYV, { 1, { { 16, 2, 1 } }, } }, - { PixelFormat::YVYU, { 1, { { 16, 2, 1 } }, } }, - { PixelFormat::VYUY, { 1, { { 16, 2, 1 } }, } }, - /* YUV semi-planar */ - { PixelFormat::NV12, { 2, { { 8, 1, 1, }, { 8, 2, 2 } }, } }, - { PixelFormat::NV21, { 2, { { 8, 1, 1, }, { 8, 2, 2 } }, } }, - /* RGB16 */ - { PixelFormat::RGB565, { 1, { { 16, 1, 1 } }, } }, - /* RGB32 */ - { PixelFormat::XRGB8888, { 1, { { 32, 1, 1 } }, } }, - { PixelFormat::XBGR8888, { 1, { { 32, 1, 1 } }, } }, - { PixelFormat::ARGB8888, { 1, { { 32, 1, 1 } }, } }, - { PixelFormat::ABGR8888, { 1, { { 32, 1, 1 } }, } }, -}; - -const struct PixelFormatInfo& get_pixel_format_info(PixelFormat format) -{ - return format_info_array.at(format); -} - -} diff --git a/kms++/pixelformats.h b/kms++/pixelformats.h deleted file mode 100644 index 813eaef..0000000 --- a/kms++/pixelformats.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include -#include - -namespace kms -{ -constexpr uint32_t MakeFourCC(const char *fourcc) -{ - return fourcc[0] | (fourcc[1] << 8) | (fourcc[2] << 16) | (fourcc[3] << 24); -} - -enum class PixelFormat : uint32_t -{ - Undefined = 0, - - NV12 = MakeFourCC("NV12"), - NV21 = MakeFourCC("NV21"), - - UYVY = MakeFourCC("UYVY"), - YUYV = MakeFourCC("YUYV"), - YVYU = MakeFourCC("YVYU"), - VYUY = MakeFourCC("VYUY"), - - XRGB8888 = MakeFourCC("XR24"), - XBGR8888 = MakeFourCC("XB24"), - ARGB8888 = MakeFourCC("AR24"), - ABGR8888 = MakeFourCC("AB24"), - - RGB565 = MakeFourCC("RG16"), -}; - -static inline PixelFormat FourCCToPixelFormat(const std::string& fourcc) -{ - return (PixelFormat)MakeFourCC(fourcc.c_str()); -} - -static inline std::string PixelFormatToFourCC(PixelFormat f) -{ - char buf[5] = { (char)(((int)f >> 0) & 0xff), - (char)(((int)f >> 8) & 0xff), - (char)(((int)f >> 16) & 0xff), - (char)(((int)f >> 24) & 0xff), - 0 }; - return std::string(buf); -} - -struct PixelFormatPlaneInfo -{ - uint8_t bitspp; - uint8_t xsub; - uint8_t ysub; -}; - -struct PixelFormatInfo -{ - uint8_t num_planes; - struct PixelFormatPlaneInfo planes[4]; -}; - -const struct PixelFormatInfo& get_pixel_format_info(PixelFormat format); - -} diff --git a/kms++/plane.cpp b/kms++/plane.cpp deleted file mode 100644 index 46cd3e6..0000000 --- a/kms++/plane.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -struct PlanePriv -{ - drmModePlanePtr drm_plane; -}; - -Plane::Plane(Card &card, uint32_t id, uint32_t idx) - :DrmPropObject(card, id, DRM_MODE_OBJECT_PLANE, idx) -{ - m_priv = new PlanePriv(); - m_priv->drm_plane = drmModeGetPlane(this->card().fd(), this->id()); - assert(m_priv->drm_plane); -} - -Plane::~Plane() -{ - drmModeFreePlane(m_priv->drm_plane); - delete m_priv; -} - -bool Plane::supports_crtc(Crtc* crtc) const -{ - return m_priv->drm_plane->possible_crtcs & (1 << crtc->idx()); -} - -bool Plane::supports_format(PixelFormat fmt) const -{ - auto p = m_priv->drm_plane; - - for (unsigned i = 0; i < p->count_formats; ++i) - if ((uint32_t)fmt == p->formats[i]) - return true; - - return false; -} - -PlaneType Plane::plane_type() const -{ - if (card().has_has_universal_planes()) - return (PlaneType)get_prop_value("type"); - else - return PlaneType::Overlay; -} - -vector Plane::get_formats() const -{ - auto p = m_priv->drm_plane; - vector r; - - for (unsigned i = 0; i < p->count_formats; ++i) - r.push_back((PixelFormat) p->formats[i]); - - return r; -} - -uint32_t Plane::crtc_id() const -{ - return m_priv->drm_plane->crtc_id; -} - -uint32_t Plane::fb_id() const -{ - return m_priv->drm_plane->fb_id; -} - -uint32_t Plane::crtc_x() const -{ - return m_priv->drm_plane->crtc_x; -} - -uint32_t Plane::crtc_y() const -{ - return m_priv->drm_plane->crtc_y; -} - -uint32_t Plane::x() const -{ - return m_priv->drm_plane->x; -} - -uint32_t Plane::y() const -{ - return m_priv->drm_plane->y; -} - -uint32_t Plane::gamma_size() const -{ - return m_priv->drm_plane->gamma_size; -} - -} diff --git a/kms++/plane.h b/kms++/plane.h deleted file mode 100644 index d50e539..0000000 --- a/kms++/plane.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "drmpropobject.h" - -namespace kms -{ - -enum class PlaneType -{ - Overlay = 0, - Primary = 1, - Cursor = 2, -}; - -struct PlanePriv; - -class Plane : public DrmPropObject -{ - friend class Card; -public: - bool supports_crtc(Crtc* crtc) const; - bool supports_format(PixelFormat fmt) const; - - PlaneType plane_type() const; - - std::vector get_formats() const; - uint32_t crtc_id() const; - uint32_t fb_id() const; - - uint32_t crtc_x() const; - uint32_t crtc_y() const; - uint32_t x() const; - uint32_t y() const; - uint32_t gamma_size() const; -private: - Plane(Card& card, uint32_t id, uint32_t idx); - ~Plane(); - - PlanePriv* m_priv; -}; -} diff --git a/kms++/property.cpp b/kms++/property.cpp deleted file mode 100644 index e4390ba..0000000 --- a/kms++/property.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include - -#include "kms++.h" - -using namespace std; - -namespace kms -{ - -struct PropertyPriv -{ - drmModePropertyPtr drm_prop; -}; - -Property::Property(Card& card, uint32_t id) - : DrmObject(card, id, DRM_MODE_OBJECT_PROPERTY) -{ - m_priv = new PropertyPriv(); - m_priv->drm_prop = drmModeGetProperty(card.fd(), id); - m_name = m_priv->drm_prop->name; - - PropertyType t; - drmModePropertyPtr p = m_priv->drm_prop; - if (drm_property_type_is(p, DRM_MODE_PROP_BITMASK)) - t = PropertyType::Bitmask; - else if (drm_property_type_is(p, DRM_MODE_PROP_BLOB)) - t = PropertyType::Blob; - else if (drm_property_type_is(p, DRM_MODE_PROP_ENUM)) - t = PropertyType::Enum; - else if (drm_property_type_is(p, DRM_MODE_PROP_OBJECT)) - t = PropertyType::Object; - else if (drm_property_type_is(p, DRM_MODE_PROP_RANGE)) - t = PropertyType::Range; - else if (drm_property_type_is(p, DRM_MODE_PROP_SIGNED_RANGE)) - t = PropertyType::SignedRange; - else - throw invalid_argument("Invalid property type"); - - m_type = t; -} - -Property::~Property() -{ - drmModeFreeProperty(m_priv->drm_prop); - delete m_priv; -} - -const string& Property::name() const -{ - return m_name; -} - -bool Property::is_immutable() const -{ - return m_priv->drm_prop->flags & DRM_MODE_PROP_IMMUTABLE; -} - -bool Property::is_pending() const -{ - return m_priv->drm_prop->flags & DRM_MODE_PROP_PENDING; -} - -vector Property::get_values() const -{ - drmModePropertyPtr p = m_priv->drm_prop; - return vector(p->values, p->values + p->count_values); -} - -map Property::get_enums() const -{ - drmModePropertyPtr p = m_priv->drm_prop; - - map map; - - for (int i = 0; i < p->count_enums; ++i) - map[p->enums[i].value] = string(p->enums[i].name); - - return map; -} - -vector Property::get_blob_ids() const -{ - drmModePropertyPtr p = m_priv->drm_prop; - return vector(p->blob_ids, p->blob_ids + p->count_blobs); -} -} diff --git a/kms++/property.h b/kms++/property.h deleted file mode 100644 index b9097ff..0000000 --- a/kms++/property.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "drmobject.h" -#include -#include - -namespace kms -{ - -struct PropertyPriv; - -enum class PropertyType -{ - Range, - Enum, - Blob, - Bitmask, - Object, - SignedRange, -}; - -class Property : public DrmObject -{ - friend class Card; -public: - const std::string& name() const; - - bool is_immutable() const; - bool is_pending() const; - - PropertyType type() const { return m_type; } - std::map get_enums() const; - std::vector get_values() const; - std::vector get_blob_ids() const; -private: - Property(Card& card, uint32_t id); - ~Property(); - - PropertyType m_type; - - PropertyPriv* m_priv; - std::string m_name; -}; -} diff --git a/kms++/src/atomicreq.cpp b/kms++/src/atomicreq.cpp new file mode 100644 index 0000000..01934ae --- /dev/null +++ b/kms++/src/atomicreq.cpp @@ -0,0 +1,92 @@ +#include +#include + +#include +#include + +#include + +#ifndef DRM_CLIENT_CAP_ATOMIC + +#define DRM_MODE_ATOMIC_TEST_ONLY 0 +#define DRM_MODE_ATOMIC_NONBLOCK 0 + +struct _drmModeAtomicReq; +typedef struct _drmModeAtomicReq* drmModeAtomicReqPtr; + +static inline drmModeAtomicReqPtr drmModeAtomicAlloc() { return 0; } +static inline void drmModeAtomicFree(drmModeAtomicReqPtr) { } +static inline int drmModeAtomicAddProperty(drmModeAtomicReqPtr, uint32_t, uint32_t, uint64_t) { return 0; } +static inline int drmModeAtomicCommit(int, drmModeAtomicReqPtr, int, void*) { return 0; } + +#endif // DRM_CLIENT_CAP_ATOMIC + +using namespace std; + +namespace kms +{ +AtomicReq::AtomicReq(Card& card) + : m_card(card) +{ + assert(card.has_atomic()); + m_req = drmModeAtomicAlloc(); +} + +AtomicReq::~AtomicReq() +{ + drmModeAtomicFree(m_req); +} + +void AtomicReq::add(uint32_t ob_id, uint32_t prop_id, uint64_t value) +{ + int r = drmModeAtomicAddProperty(m_req, ob_id, prop_id, value); + if (r <= 0) + throw std::invalid_argument("foo"); +} + +void AtomicReq::add(DrmObject *ob, Property *prop, uint64_t value) +{ + add(ob->id(), prop->id(), value); +} + +void AtomicReq::add(DrmObject* ob, const string& prop, uint64_t value) +{ + add(ob, m_card.get_prop(prop), value); +} + +void AtomicReq::add(DrmObject* ob, const map& values) +{ + for(const auto& kvp : values) + add(ob, kvp.first, kvp.second); +} + +int AtomicReq::test(bool allow_modeset) +{ + uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY; + + if (allow_modeset) + flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; + + return drmModeAtomicCommit(m_card.fd(), m_req, flags, 0); +} + +int AtomicReq::commit(void* data, bool allow_modeset) +{ + uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; + + if (allow_modeset) + flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; + + return drmModeAtomicCommit(m_card.fd(), m_req, flags, data); +} + +int AtomicReq::commit_sync(bool allow_modeset) +{ + uint32_t flags = 0; + + if (allow_modeset) + flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; + + return drmModeAtomicCommit(m_card.fd(), m_req, flags, 0); +} +} diff --git a/kms++/src/blob.cpp b/kms++/src/blob.cpp new file mode 100644 index 0000000..e1cd1f8 --- /dev/null +++ b/kms++/src/blob.cpp @@ -0,0 +1,51 @@ +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +Blob::Blob(Card& card, uint32_t blob_id) + : DrmObject(card, blob_id, DRM_MODE_OBJECT_BLOB), m_created(false) +{ + // XXX should we verify that the blob_id is a blob object? +} + +Blob::Blob(Card& card, void* data, size_t len) + : DrmObject(card, DRM_MODE_OBJECT_BLOB), m_created(true) +{ + uint32_t id; + + int r = drmModeCreatePropertyBlob(card.fd(), data, len, &id); + if (r) + throw invalid_argument("FAILED TO CREATE PROP\n"); + + set_id(id); +} + +Blob::~Blob() +{ + if (m_created) + drmModeDestroyPropertyBlob(card().fd(), id()); +} + +vector Blob::data() +{ + drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(card().fd(), id()); + + if (!blob) + throw invalid_argument("Blob data not available"); + + uint8_t* data = (uint8_t*)blob->data; + + auto v = vector(data, data + blob->length); + + drmModeFreePropertyBlob(blob); + + return v; +} + +} diff --git a/kms++/src/card.cpp b/kms++/src/card.cpp new file mode 100644 index 0000000..0a34d14 --- /dev/null +++ b/kms++/src/card.cpp @@ -0,0 +1,239 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +Card::Card() + : Card("/dev/dri/card0") +{ +} + + +Card::Card(const std::string& device) +{ + int fd = open(device.c_str(), O_RDWR | O_CLOEXEC); + if (fd < 0) + throw invalid_argument(string(strerror(errno)) + " opening " + device); + m_fd = fd; + + int r; + + r = drmSetMaster(fd); + m_master = r == 0; + + if (getenv("KMSXX_DISABLE_UNIVERSAL_PLANES") == 0) { + r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + m_has_universal_planes = r == 0; + } else { + m_has_universal_planes = false; + } + +#ifdef DRM_CLIENT_CAP_ATOMIC + if (getenv("KMSXX_DISABLE_ATOMIC") == 0) { + r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1); + m_has_atomic = r == 0; + } else { + m_has_atomic = false; + } +#else + m_has_atomic = false; +#endif + + uint64_t has_dumb; + r = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb); + if (r || !has_dumb) + throw invalid_argument("Dumb buffers not available"); + + auto res = drmModeGetResources(m_fd); + if (!res) + throw invalid_argument("Can't get card resources"); + + for (int i = 0; i < res->count_connectors; ++i) { + uint32_t id = res->connectors[i]; + auto ob = new Connector(*this, id, i); + m_obmap[id] = ob; + m_connectors.push_back(ob); + } + + for (int i = 0; i < res->count_crtcs; ++i) { + uint32_t id = res->crtcs[i]; + auto ob = new Crtc(*this, id, i); + m_obmap[id] = ob; + m_crtcs.push_back(ob); + } + + for (int i = 0; i < res->count_encoders; ++i) { + uint32_t id = res->encoders[i]; + auto ob = new Encoder(*this, id, i); + m_obmap[id] = ob; + m_encoders.push_back(ob); + } + + drmModeFreeResources(res); + + auto planeRes = drmModeGetPlaneResources(m_fd); + + for (uint i = 0; i < planeRes->count_planes; ++i) { + uint32_t id = planeRes->planes[i]; + auto ob = new Plane(*this, id, i); + m_obmap[id] = ob; + m_planes.push_back(ob); + } + + drmModeFreePlaneResources(planeRes); + + // collect all possible props + for (auto ob : get_objects()) { + auto props = drmModeObjectGetProperties(m_fd, ob->id(), ob->object_type()); + + if (props == nullptr) + continue; + + for (unsigned i = 0; i < props->count_props; ++i) { + uint32_t prop_id = props->props[i]; + + if (m_obmap.find(prop_id) == m_obmap.end()) { + auto ob = new Property(*this, prop_id); + m_obmap[prop_id] = ob; + m_properties.push_back(ob); + } + } + + drmModeFreeObjectProperties(props); + } + + for (auto pair : m_obmap) + pair.second->setup(); +} + +Card::~Card() +{ + restore_modes(); + + while (m_framebuffers.size() > 0) + delete m_framebuffers.back(); + + for (auto pair : m_obmap) + delete pair.second; + + close(m_fd); +} + +void Card::drop_master() +{ + drmDropMaster(fd()); +} + +void Card::restore_modes() +{ + for (auto conn : get_connectors()) + conn->restore_mode(); +} + +Property* Card::get_prop(const string& name) const +{ + for (auto prop : m_properties) { + if (name == prop->name()) + return prop; + } + + throw invalid_argument(string("Card property ") + name + " not found"); +} + +Connector* Card::get_first_connected_connector() const +{ + for(auto c : m_connectors) { + if (c->connected()) + return c; + } + + throw invalid_argument("no connected connectors"); +} + +DrmObject* Card::get_object(uint32_t id) const +{ + auto iter = m_obmap.find(id); + if (iter != m_obmap.end()) + return iter->second; + return nullptr; +} + +const vector Card::get_objects() const +{ + vector v; + for(auto pair : m_obmap) + v.push_back(pair.second); + return v; +} + +Connector* Card::get_connector(uint32_t id) const { return dynamic_cast(get_object(id)); } +Crtc* Card::get_crtc(uint32_t id) const { return dynamic_cast(get_object(id)); } +Encoder* Card::get_encoder(uint32_t id) const { return dynamic_cast(get_object(id)); } +Property* Card::get_prop(uint32_t id) const { return dynamic_cast(get_object(id)); } +Plane* Card::get_plane(uint32_t id) const { return dynamic_cast(get_object(id)); } + +std::vector Card::get_connected_pipelines() +{ + vector outputs; + + for (auto conn : get_connectors()) + { + if (conn->connected() == false) + continue; + + Crtc* crtc = conn->get_current_crtc(); + + if (!crtc) { + for (auto possible : conn->get_possible_crtcs()) { + if (find_if(outputs.begin(), outputs.end(), [possible](Pipeline out) { return out.crtc == possible; }) == outputs.end()) { + crtc = possible; + break; + } + } + } + + if (!crtc) + throw invalid_argument(string("Connector #") + + to_string(conn->idx()) + + " has no possible crtcs"); + + outputs.push_back(Pipeline { crtc, conn }); + } + + return outputs; +} + +static void page_flip_handler(int fd, unsigned int frame, + unsigned int sec, unsigned int usec, + void *data) +{ + auto handler = (PageFlipHandlerBase*)data; + double time = sec + usec / 1000000.0; + handler->handle_page_flip(frame, time); +} + +void Card::call_page_flip_handlers() +{ + drmEventContext ev = { + .version = DRM_EVENT_CONTEXT_VERSION, + .vblank_handler = 0, + .page_flip_handler = page_flip_handler, + }; + + drmHandleEvent(fd(), &ev); +} + +} diff --git a/kms++/src/connector.cpp b/kms++/src/connector.cpp new file mode 100644 index 0000000..ec37d5d --- /dev/null +++ b/kms++/src/connector.cpp @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include + +#include +#include "helpers.h" + +using namespace std; + +namespace kms +{ + + +static const map connector_names = { + { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, + { DRM_MODE_CONNECTOR_VGA, "VGA" }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, + { DRM_MODE_CONNECTOR_Composite, "Composite" }, + { DRM_MODE_CONNECTOR_SVIDEO, "S-Video" }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, + { DRM_MODE_CONNECTOR_Component, "Component" }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-Pin-DIN" }, + { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, + { DRM_MODE_CONNECTOR_TV, "TV" }, + { DRM_MODE_CONNECTOR_eDP, "eDP" }, + { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, + { DRM_MODE_CONNECTOR_DSI, "DSI" }, +}; + +static const map connection_str = { + { 0, "" }, + { DRM_MODE_CONNECTED, "Connected" }, + { DRM_MODE_DISCONNECTED, "Disconnected" }, + { DRM_MODE_UNKNOWNCONNECTION, "Unknown" }, +}; + +static const map subpix_str = { +#define DEF_SUBPIX(c) { DRM_MODE_SUBPIXEL_##c, #c } + DEF_SUBPIX(UNKNOWN), + DEF_SUBPIX(HORIZONTAL_RGB), + DEF_SUBPIX(HORIZONTAL_BGR), + DEF_SUBPIX(VERTICAL_RGB), + DEF_SUBPIX(VERTICAL_BGR), + DEF_SUBPIX(NONE), +#undef DEF_SUBPIX +}; + +struct ConnectorPriv +{ + drmModeConnectorPtr drm_connector; +}; + +Connector::Connector(Card &card, uint32_t id, uint32_t idx) + :DrmPropObject(card, id, DRM_MODE_OBJECT_CONNECTOR, idx) +{ + m_priv = new ConnectorPriv(); + + m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id()); + assert(m_priv->drm_connector); + + // XXX drmModeGetConnector() does forced probe, which seems to change (at least) EDID blob id. + // XXX So refresh the props again here. + refresh_props(); + + const auto& name = connector_names.at(m_priv->drm_connector->connector_type); + m_fullname = name + "-" + to_string(m_priv->drm_connector->connector_type_id); +} + + +Connector::~Connector() +{ + drmModeFreeConnector(m_priv->drm_connector); + delete m_priv; +} + +void Connector::setup() +{ + if (m_priv->drm_connector->encoder_id != 0) + m_current_encoder = card().get_encoder(m_priv->drm_connector->encoder_id); + else + m_current_encoder = 0; + + if (m_current_encoder) + m_saved_crtc = m_current_encoder->get_crtc(); + else + m_saved_crtc = 0; +} + +void Connector::restore_mode() +{ + if (m_saved_crtc) + m_saved_crtc->restore_mode(this); +} + +Videomode Connector::get_default_mode() const +{ + if (m_priv->drm_connector->count_modes == 0) + throw invalid_argument("no modes available\n"); + drmModeModeInfo drmmode = m_priv->drm_connector->modes[0]; + + return drm_mode_to_video_mode(drmmode); +} + +Videomode Connector::get_mode(const string& mode) const +{ + auto c = m_priv->drm_connector; + + for (int i = 0; i < c->count_modes; i++) + if (mode == c->modes[i].name) + return drm_mode_to_video_mode(c->modes[i]); + + throw invalid_argument(mode + ": mode not found"); +} + +Videomode Connector::get_mode(unsigned xres, unsigned yres, unsigned refresh, bool ilace) const +{ + auto c = m_priv->drm_connector; + + for (int i = 0; i < c->count_modes; i++) { + drmModeModeInfo& m = c->modes[i]; + + if (m.hdisplay != xres || m.vdisplay != yres) + continue; + + if (refresh && m.vrefresh != refresh) + continue; + + if (ilace != !!(m.flags & DRM_MODE_FLAG_INTERLACE)) + continue; + + return drm_mode_to_video_mode(c->modes[i]); + } + + throw invalid_argument("mode not found"); +} + +bool Connector::connected() const +{ + return m_priv->drm_connector->connection == DRM_MODE_CONNECTED || + m_priv->drm_connector->connection == DRM_MODE_UNKNOWNCONNECTION; +} + +vector Connector::get_possible_crtcs() const +{ + vector crtcs; + + for (int i = 0; i < m_priv->drm_connector->count_encoders; ++i) { + auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]); + + auto l = enc->get_possible_crtcs(); + + crtcs.insert(crtcs.end(), l.begin(), l.end()); + } + + return crtcs; +} + +Crtc* Connector::get_current_crtc() const +{ + if (m_current_encoder) + return m_current_encoder->get_crtc(); + else + return 0; +} + +uint32_t Connector::connector_type() const +{ + return m_priv->drm_connector->connector_type; +} + +uint32_t Connector::connector_type_id() const +{ + return m_priv->drm_connector->connector_type_id; +} + +uint32_t Connector::mmWidth() const +{ + return m_priv->drm_connector->mmWidth; +} + +uint32_t Connector::mmHeight() const +{ + return m_priv->drm_connector->mmHeight; +} + +uint32_t Connector::subpixel() const +{ + return m_priv->drm_connector->subpixel; +} + +const string& Connector::subpixel_str() const +{ + return subpix_str.at(subpixel()); +} + +std::vector Connector::get_modes() const +{ + vector modes; + + for (int i = 0; i < m_priv->drm_connector->count_modes; i++) + modes.push_back(drm_mode_to_video_mode( + m_priv->drm_connector->modes[i])); + + return modes; +} + +std::vector Connector::get_encoders() const +{ + vector encoders; + + for (int i = 0; i < m_priv->drm_connector->count_encoders; i++) { + auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]); + encoders.push_back(enc); + } + return encoders; +} + +} diff --git a/kms++/src/crtc.cpp b/kms++/src/crtc.cpp new file mode 100644 index 0000000..bad7d31 --- /dev/null +++ b/kms++/src/crtc.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include + +#include +#include "helpers.h" + +using namespace std; + +namespace kms +{ + +struct CrtcPriv +{ + drmModeCrtcPtr drm_crtc; +}; + +Crtc::Crtc(Card &card, uint32_t id, uint32_t idx) + :DrmPropObject(card, id, DRM_MODE_OBJECT_CRTC, idx) +{ + m_priv = new CrtcPriv(); + m_priv->drm_crtc = drmModeGetCrtc(this->card().fd(), this->id()); + assert(m_priv->drm_crtc); +} + +Crtc::~Crtc() +{ + drmModeFreeCrtc(m_priv->drm_crtc); + delete m_priv; +} + +void Crtc::setup() +{ + for (Plane* plane : card().get_planes()) { + if (plane->supports_crtc(this)) + m_possible_planes.push_back(plane); + } +} + +void Crtc::restore_mode(Connector* conn) +{ + auto c = m_priv->drm_crtc; + + uint32_t conns[] = { conn->id() }; + + drmModeSetCrtc(card().fd(), id(), c->buffer_id, + c->x, c->y, + conns, 1, &c->mode); +} + +int Crtc::set_mode(Connector* conn, Framebuffer& fb, const Videomode& mode) +{ + uint32_t conns[] = { conn->id() }; + drmModeModeInfo drmmode = video_mode_to_drm_mode(mode); + + return drmModeSetCrtc(card().fd(), id(), fb.id(), + 0, 0, + conns, 1, &drmmode); +} + +static inline uint32_t conv(float x) +{ + // XXX fix the conversion for fractional part + return ((uint32_t)x) << 16; +} + +int Crtc::set_plane(Plane* plane, Framebuffer& fb, + int32_t dst_x, int32_t dst_y, uint32_t dst_w, uint32_t dst_h, + float src_x, float src_y, float src_w, float src_h) +{ + return drmModeSetPlane(card().fd(), plane->id(), id(), fb.id(), 0, + dst_x, dst_y, dst_w, dst_h, + conv(src_x), conv(src_y), conv(src_w), conv(src_h)); +} + +int Crtc::disable_plane(Plane* plane) +{ + return drmModeSetPlane(card().fd(), plane->id(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +} + +Plane* Crtc::get_primary_plane() +{ + for (Plane* p : get_possible_planes()) { + if (p->plane_type() != PlaneType::Primary) + continue; + + return p; + } + + throw invalid_argument(string("No primary plane for crtc ") + to_string(id())); +} + +int Crtc::page_flip(Framebuffer& fb, void *data) +{ + return drmModePageFlip(card().fd(), id(), fb.id(), DRM_MODE_PAGE_FLIP_EVENT, data); +} + +uint32_t Crtc::buffer_id() const +{ + return m_priv->drm_crtc->buffer_id; +} + +uint32_t Crtc::x() const +{ + return m_priv->drm_crtc->x; +} + +uint32_t Crtc::y() const +{ + return m_priv->drm_crtc->y; +} + +uint32_t Crtc::width() const +{ + return m_priv->drm_crtc->width; +} + +uint32_t Crtc::height() const +{ + return m_priv->drm_crtc->height; +} + +int Crtc::mode_valid() const +{ + return m_priv->drm_crtc->mode_valid; +} + +Videomode Crtc::mode() const +{ + return drm_mode_to_video_mode(m_priv->drm_crtc->mode); +} + +int Crtc::gamma_size() const +{ + return m_priv->drm_crtc->gamma_size; +} + +} diff --git a/kms++/src/drmobject.cpp b/kms++/src/drmobject.cpp new file mode 100644 index 0000000..f94fc5d --- /dev/null +++ b/kms++/src/drmobject.cpp @@ -0,0 +1,34 @@ +#include +#include +#include + +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +DrmObject::DrmObject(Card& card, uint32_t object_type) + :m_card(card), m_id(-1), m_object_type(object_type), m_idx(0) +{ +} + +DrmObject::DrmObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx) + :m_card(card), m_id(id), m_object_type(object_type), m_idx(idx) +{ +} + +DrmObject::~DrmObject() +{ + +} + +void DrmObject::set_id(uint32_t id) +{ + m_id = id; +} +} diff --git a/kms++/src/drmpropobject.cpp b/kms++/src/drmpropobject.cpp new file mode 100644 index 0000000..f2edf8b --- /dev/null +++ b/kms++/src/drmpropobject.cpp @@ -0,0 +1,86 @@ +#include +#include +#include + +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +DrmPropObject::DrmPropObject(Card& card, uint32_t object_type) + : DrmObject(card, object_type) +{ +} + +DrmPropObject::DrmPropObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx) + : DrmObject(card, id, object_type, idx) +{ + refresh_props(); +} + +DrmPropObject::~DrmPropObject() +{ + +} + +void DrmPropObject::refresh_props() +{ + auto props = drmModeObjectGetProperties(card().fd(), this->id(), this->object_type()); + + if (props == nullptr) + return; + + for (unsigned i = 0; i < props->count_props; ++i) { + uint32_t prop_id = props->props[i]; + uint64_t prop_value = props->prop_values[i]; + + m_prop_values[prop_id] = prop_value; + } + + drmModeFreeObjectProperties(props); +} + +uint64_t DrmPropObject::get_prop_value(uint32_t id) const +{ + return m_prop_values.at(id); +} + +uint64_t DrmPropObject::get_prop_value(const string& name) const +{ + for (auto pair : m_prop_values) { + auto prop = card().get_prop(pair.first); + if (name == prop->name()) + return m_prop_values.at(prop->id()); + } + + throw invalid_argument("property not found: " + name); +} + +unique_ptr DrmPropObject::get_prop_value_as_blob(const string& name) const +{ + uint32_t blob_id = (uint32_t)get_prop_value(name); + + return unique_ptr(new Blob(card(), blob_id)); +} + +int DrmPropObject::set_prop_value(uint32_t id, uint64_t value) +{ + return drmModeObjectSetProperty(card().fd(), this->id(), this->object_type(), id, value); +} + +int DrmPropObject::set_prop_value(const string &name, uint64_t value) +{ + Property* prop = card().get_prop(name); + + if (prop == nullptr) + throw invalid_argument("property not found: " + name); + + return set_prop_value(prop->id(), value); +} + +} diff --git a/kms++/src/dumbframebuffer.cpp b/kms++/src/dumbframebuffer.cpp new file mode 100644 index 0000000..d2f5db2 --- /dev/null +++ b/kms++/src/dumbframebuffer.cpp @@ -0,0 +1,137 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +using namespace std; + +namespace kms +{ + +DumbFramebuffer::DumbFramebuffer(Card &card, uint32_t width, uint32_t height, const string& fourcc) + :DumbFramebuffer(card, width, height, FourCCToPixelFormat(fourcc)) +{ +} + +DumbFramebuffer::DumbFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format) + :Framebuffer(card, width, height), m_format(format) +{ + Create(); +} + +DumbFramebuffer::~DumbFramebuffer() +{ + Destroy(); +} + +void DumbFramebuffer::Create() +{ + int r; + + const PixelFormatInfo& format_info = get_pixel_format_info(m_format); + + m_num_planes = format_info.num_planes; + + for (int i = 0; i < format_info.num_planes; ++i) { + const PixelFormatPlaneInfo& pi = format_info.planes[i]; + FramebufferPlane& plane = m_planes[i]; + + /* create dumb buffer */ + struct drm_mode_create_dumb creq = drm_mode_create_dumb(); + creq.width = width(); + creq.height = height() / pi.ysub; + creq.bpp = pi.bitspp; + r = drmIoctl(card().fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq); + if (r) + throw invalid_argument(string("DRM_IOCTL_MODE_CREATE_DUMB failed") + strerror(errno)); + + plane.handle = creq.handle; + plane.stride = creq.pitch; + plane.size = creq.height * creq.pitch; + plane.offset = 0; + plane.map = 0; + plane.prime_fd = -1; + } + + /* create framebuffer object for the dumb-buffer */ + uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle }; + uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride }; + uint32_t offsets[4] = { m_planes[0].offset, m_planes[1].offset }; + uint32_t id; + r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(), + bo_handles, pitches, offsets, &id, 0); + if (r) + throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); + + set_id(id); +} + +void DumbFramebuffer::Destroy() +{ + /* delete framebuffer */ + drmModeRmFB(card().fd(), id()); + + for (uint i = 0; i < m_num_planes; ++i) { + FramebufferPlane& plane = m_planes[i]; + + /* unmap buffer */ + if (plane.map) + munmap(plane.map, plane.size); + + /* delete dumb buffer */ + struct drm_mode_destroy_dumb dreq = drm_mode_destroy_dumb(); + dreq.handle = plane.handle; + drmIoctl(card().fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); + if (plane.prime_fd >= 0) + ::close(plane.prime_fd); + } +} + +uint8_t* DumbFramebuffer::map(unsigned plane) +{ + FramebufferPlane& p = m_planes[plane]; + + if (p.map) + return p.map; + + /* prepare buffer for memory mapping */ + struct drm_mode_map_dumb mreq = drm_mode_map_dumb(); + mreq.handle = p.handle; + int r = drmIoctl(card().fd(), DRM_IOCTL_MODE_MAP_DUMB, &mreq); + if (r) + throw invalid_argument(string("DRM_IOCTL_MODE_MAP_DUMB failed") + strerror(errno)); + + /* perform actual memory mapping */ + p.map = (uint8_t *)mmap(0, p.size, PROT_READ | PROT_WRITE, MAP_SHARED, + card().fd(), mreq.offset); + if (p.map == MAP_FAILED) + throw invalid_argument(string("mmap failed: ") + strerror(errno)); + + return p.map; +} + +int DumbFramebuffer::prime_fd(unsigned int plane) +{ + if (m_planes[plane].prime_fd >= 0) + return m_planes[plane].prime_fd; + + int r = drmPrimeHandleToFD(card().fd(), m_planes[plane].handle, + DRM_CLOEXEC, &m_planes[plane].prime_fd); + if (r) + throw std::runtime_error("drmPrimeHandleToFD failed"); + + return m_planes[plane].prime_fd; +} + +} diff --git a/kms++/src/encoder.cpp b/kms++/src/encoder.cpp new file mode 100644 index 0000000..2168f2f --- /dev/null +++ b/kms++/src/encoder.cpp @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +struct EncoderPriv +{ + drmModeEncoderPtr drm_encoder; +}; + +static const map encoder_types = { +#define DEF_ENC(c) { DRM_MODE_ENCODER_##c, #c } + DEF_ENC(NONE), + DEF_ENC(DAC), + DEF_ENC(TMDS), + DEF_ENC(LVDS), + DEF_ENC(TVDAC), + DEF_ENC(VIRTUAL), + DEF_ENC(DSI), + { 7, "DPMST" }, +#undef DEF_ENC +}; + +Encoder::Encoder(Card &card, uint32_t id, uint32_t idx) + :DrmPropObject(card, id, DRM_MODE_OBJECT_ENCODER, idx) +{ + m_priv = new EncoderPriv(); + m_priv->drm_encoder = drmModeGetEncoder(this->card().fd(), this->id()); + assert(m_priv->drm_encoder); +} + +Encoder::~Encoder() +{ + drmModeFreeEncoder(m_priv->drm_encoder); + delete m_priv; +} + +Crtc* Encoder::get_crtc() const +{ + if (m_priv->drm_encoder->crtc_id) + return card().get_crtc(m_priv->drm_encoder->crtc_id); + else + return 0; +} + +vector Encoder::get_possible_crtcs() const +{ + unsigned bits = m_priv->drm_encoder->possible_crtcs; + vector crtcs; + + for (int idx = 0; bits; idx++, bits >>= 1) { + if ((bits & 1) == 0) + continue; + + auto crtc = card().get_crtcs()[idx]; + crtcs.push_back(crtc); + } + + return crtcs; +} + +const string& Encoder::get_encoder_type() const +{ + return encoder_types.at(m_priv->drm_encoder->encoder_type); +} + +} diff --git a/kms++/src/extframebuffer.cpp b/kms++/src/extframebuffer.cpp new file mode 100644 index 0000000..0ade454 --- /dev/null +++ b/kms++/src/extframebuffer.cpp @@ -0,0 +1,68 @@ + +#include +#include +#include +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t stride, uint32_t handle) + :Framebuffer(card, width, height) +{ + uint32_t id; + int r = drmModeAddFB(card.fd(), width, height, depth, bpp, stride, handle, &id); + if (r) + throw invalid_argument("fob"); + + set_id(id); +} + +ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, + uint32_t handles[], uint32_t pitches[], uint32_t offsets[]) + : Framebuffer(card, width, height) +{ + uint32_t id; + int r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, handles, pitches, offsets, &id, 0); + if (r) + throw std::invalid_argument(string("Failed to create ExtFramebuffer: ") + strerror(r)); + + set_id(id); +} + +ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, + int fds[4], uint32_t pitches[4], uint32_t offsets[4]) + : Framebuffer(card, width, height) +{ + int r; + + const PixelFormatInfo& format_info = get_pixel_format_info(format); + + uint32_t handles[4] = { 0 }; + + for (int i = 0; i < format_info.num_planes; ++i) { + r = drmPrimeFDToHandle(card.fd(), fds[i], &handles[i]); + if (r) + throw invalid_argument(string("drmPrimeFDToHandle: ") + strerror(errno)); + } + + uint32_t id; + r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, + handles, pitches, offsets, &id, 0); + if (r) + throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); + + set_id(id); +} + +ExtFramebuffer::~ExtFramebuffer() +{ + drmModeRmFB(card().fd(), id()); +} + +} diff --git a/kms++/src/framebuffer.cpp b/kms++/src/framebuffer.cpp new file mode 100644 index 0000000..a7f589c --- /dev/null +++ b/kms++/src/framebuffer.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +Framebuffer::Framebuffer(Card& card, uint32_t width, uint32_t height) + : DrmObject(card, DRM_MODE_OBJECT_FB), m_width(width), m_height(height) +{ + card.m_framebuffers.push_back(this); +} + +Framebuffer::Framebuffer(Card& card, uint32_t id) + : DrmObject(card, id, DRM_MODE_OBJECT_FB) +{ + auto fb = drmModeGetFB(card.fd(), id); + + m_width = fb->width; + m_height = fb->height; + + drmModeFreeFB(fb); + + card.m_framebuffers.push_back(this); +} + +Framebuffer::~Framebuffer() +{ + auto& fbs = card().m_framebuffers; + auto iter = find(fbs.begin(), fbs.end(), this); + card().m_framebuffers.erase(iter); +} + + +} diff --git a/kms++/src/helpers.cpp b/kms++/src/helpers.cpp new file mode 100644 index 0000000..8bd082b --- /dev/null +++ b/kms++/src/helpers.cpp @@ -0,0 +1,72 @@ + +#include +#include "helpers.h" +#include + +#define CPY(field) dst.field = src.field + +namespace kms +{ +Videomode drm_mode_to_video_mode(const drmModeModeInfo& drmmode) +{ + Videomode mode = { }; + + auto& src = drmmode; + auto& dst = mode; + + CPY(clock); + + CPY(hdisplay); + CPY(hsync_start); + CPY(hsync_end); + CPY(htotal); + CPY(hskew); + + CPY(vdisplay); + CPY(vsync_start); + CPY(vsync_end); + CPY(vtotal); + CPY(vscan); + + CPY(vrefresh); + + CPY(flags); + CPY(type); + + mode.name = drmmode.name; + + return mode; +} + +drmModeModeInfo video_mode_to_drm_mode(const Videomode& mode) +{ + drmModeModeInfo drmmode = { }; + + auto& src = mode; + auto& dst = drmmode; + + CPY(clock); + + CPY(hdisplay); + CPY(hsync_start); + CPY(hsync_end); + CPY(htotal); + CPY(hskew); + + CPY(vdisplay); + CPY(vsync_start); + CPY(vsync_end); + CPY(vtotal); + CPY(vscan); + + CPY(vrefresh); + + CPY(flags); + CPY(type); + + strncpy(drmmode.name, mode.name.c_str(), sizeof(drmmode.name)); + drmmode.name[sizeof(drmmode.name) - 1] = 0; + + return drmmode; +} +} diff --git a/kms++/src/helpers.h b/kms++/src/helpers.h new file mode 100644 index 0000000..4eb597c --- /dev/null +++ b/kms++/src/helpers.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace kms +{ +struct Videomode; + +Videomode drm_mode_to_video_mode(const drmModeModeInfo& drmmode); +drmModeModeInfo video_mode_to_drm_mode(const Videomode& mode); +} diff --git a/kms++/src/modedb.cpp b/kms++/src/modedb.cpp new file mode 100644 index 0000000..24d6f63 --- /dev/null +++ b/kms++/src/modedb.cpp @@ -0,0 +1,41 @@ +#include +#include + +#include + +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) +{ + for (unsigned i = 0; modes[i].clock; ++i) { + const Videomode& m = modes[i]; + + if (m.hdisplay != width || m.vdisplay != height) + continue; + + if (refresh && m.vrefresh != refresh) + continue; + + if (ilace != !!(m.flags & DRM_MODE_FLAG_INTERLACE)) + continue; + + return m; + } + + throw invalid_argument("mode not found"); +} + +const Videomode& find_dmt(uint32_t width, uint32_t height, uint32_t refresh, bool ilace) +{ + return find_from_table(dmt_modes, width, height, refresh, ilace); +} + +const Videomode& find_cea(uint32_t width, uint32_t height, uint32_t refresh, bool ilace) +{ + return find_from_table(cea_modes, width, height, refresh, ilace); +} + +} diff --git a/kms++/src/modedb_cea.cpp b/kms++/src/modedb_cea.cpp new file mode 100644 index 0000000..a105dd8 --- /dev/null +++ b/kms++/src/modedb_cea.cpp @@ -0,0 +1,401 @@ +/* From Linux kernel: drm_edid.c */ +/* + * Copyright (c) 2006 Luc Verhaegen (quirks list) + * Copyright (c) 2007-2008 Intel Corporation + * Jesse Barnes + * Copyright 2010 Red Hat, Inc. + * + * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from + * FB layer. + * Copyright (C) 2006 Dennis Munsie + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include + +namespace kms +{ + +#define DIV_ROUND(n, d) (((n) + (d) / 2) / (d)) + +#define DRM_MODE(nm, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ + .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 + +/* + * Probably taken from CEA-861 spec. + * This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c. + */ +const Videomode cea_modes[] = { + /* 1 - 640x480@60Hz */ + { DRM_MODE("640x480", 25175, 640, 656, + 752, 800, 0, 480, 490, 492, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 2 - 720x480@60Hz */ + { DRM_MODE("720x480", 27000, 720, 736, + 798, 858, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 3 - 720x480@60Hz */ + { DRM_MODE("720x480", 27000, 720, 736, + 798, 858, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 4 - 1280x720@60Hz */ + { DRM_MODE("1280x720", 74250, 1280, 1390, + 1430, 1650, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 5 - 1920x1080i@60Hz */ + { DRM_MODE("1920x1080i", 74250, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 6 - 720(1440)x480i@60Hz */ + { DRM_MODE("720x480i", 13500, 720, 739, + 801, 858, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 7 - 720(1440)x480i@60Hz */ + { DRM_MODE("720x480i", 13500, 720, 739, + 801, 858, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 8 - 720(1440)x240@60Hz */ + { DRM_MODE("720x240", 13500, 720, 739, + 801, 858, 0, 240, 244, 247, 262, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_DBLCLK), + }, + /* 9 - 720(1440)x240@60Hz */ + { DRM_MODE("720x240", 13500, 720, 739, + 801, 858, 0, 240, 244, 247, 262, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_DBLCLK), + }, + /* 10 - 2880x480i@60Hz */ + { DRM_MODE("2880x480i", 54000, 2880, 2956, + 3204, 3432, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 11 - 2880x480i@60Hz */ + { DRM_MODE("2880x480i", 54000, 2880, 2956, + 3204, 3432, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 12 - 2880x240@60Hz */ + { DRM_MODE("2880x240", 54000, 2880, 2956, + 3204, 3432, 0, 240, 244, 247, 262, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 13 - 2880x240@60Hz */ + { DRM_MODE("2880x240", 54000, 2880, 2956, + 3204, 3432, 0, 240, 244, 247, 262, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 14 - 1440x480@60Hz */ + { DRM_MODE("1440x480", 54000, 1440, 1472, + 1596, 1716, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 15 - 1440x480@60Hz */ + { DRM_MODE("1440x480", 54000, 1440, 1472, + 1596, 1716, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 16 - 1920x1080@60Hz */ + { DRM_MODE("1920x1080", 148500, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 17 - 720x576@50Hz */ + { DRM_MODE("720x576", 27000, 720, 732, + 796, 864, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 18 - 720x576@50Hz */ + { DRM_MODE("720x576", 27000, 720, 732, + 796, 864, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 19 - 1280x720@50Hz */ + { DRM_MODE("1280x720", 74250, 1280, 1720, + 1760, 1980, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 20 - 1920x1080i@50Hz */ + { DRM_MODE("1920x1080i", 74250, 1920, 2448, + 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 21 - 720(1440)x576i@50Hz */ + { DRM_MODE("720x576i", 13500, 720, 732, + 795, 864, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 22 - 720(1440)x576i@50Hz */ + { DRM_MODE("720x576i", 13500, 720, 732, + 795, 864, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 23 - 720(1440)x288@50Hz */ + { DRM_MODE("720x288", 13500, 720, 732, + 795, 864, 0, 288, 290, 293, 312, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_DBLCLK), + }, + /* 24 - 720(1440)x288@50Hz */ + { DRM_MODE("720x288", 13500, 720, 732, + 795, 864, 0, 288, 290, 293, 312, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_DBLCLK), + }, + /* 25 - 2880x576i@50Hz */ + { DRM_MODE("2880x576i", 54000, 2880, 2928, + 3180, 3456, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 26 - 2880x576i@50Hz */ + { DRM_MODE("2880x576i", 54000, 2880, 2928, + 3180, 3456, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 27 - 2880x288@50Hz */ + { DRM_MODE("2880x288", 54000, 2880, 2928, + 3180, 3456, 0, 288, 290, 293, 312, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 28 - 2880x288@50Hz */ + { DRM_MODE("2880x288", 54000, 2880, 2928, + 3180, 3456, 0, 288, 290, 293, 312, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 29 - 1440x576@50Hz */ + { DRM_MODE("1440x576", 54000, 1440, 1464, + 1592, 1728, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 30 - 1440x576@50Hz */ + { DRM_MODE("1440x576", 54000, 1440, 1464, + 1592, 1728, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 31 - 1920x1080@50Hz */ + { DRM_MODE("1920x1080", 148500, 1920, 2448, + 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 32 - 1920x1080@24Hz */ + { DRM_MODE("1920x1080", 74250, 1920, 2558, + 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 33 - 1920x1080@25Hz */ + { DRM_MODE("1920x1080", 74250, 1920, 2448, + 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 34 - 1920x1080@30Hz */ + { DRM_MODE("1920x1080", 74250, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 35 - 2880x480@60Hz */ + { DRM_MODE("2880x480", 108000, 2880, 2944, + 3192, 3432, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 36 - 2880x480@60Hz */ + { DRM_MODE("2880x480", 108000, 2880, 2944, + 3192, 3432, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 37 - 2880x576@50Hz */ + { DRM_MODE("2880x576", 108000, 2880, 2928, + 3184, 3456, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 38 - 2880x576@50Hz */ + { DRM_MODE("2880x576", 108000, 2880, 2928, + 3184, 3456, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 39 - 1920x1080i@50Hz */ + { DRM_MODE("1920x1080i", 72000, 1920, 1952, + 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 40 - 1920x1080i@100Hz */ + { DRM_MODE("1920x1080i", 148500, 1920, 2448, + 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 41 - 1280x720@100Hz */ + { DRM_MODE("1280x720", 148500, 1280, 1720, + 1760, 1980, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 42 - 720x576@100Hz */ + { DRM_MODE("720x576", 54000, 720, 732, + 796, 864, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 43 - 720x576@100Hz */ + { DRM_MODE("720x576", 54000, 720, 732, + 796, 864, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 44 - 720(1440)x576i@100Hz */ + { DRM_MODE("720x576i", 27000, 720, 732, + 795, 864, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 45 - 720(1440)x576i@100Hz */ + { DRM_MODE("720x576i", 27000, 720, 732, + 795, 864, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 46 - 1920x1080i@120Hz */ + { DRM_MODE("1920x1080i", 148500, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | + DRM_MODE_FLAG_INTERLACE), + }, + /* 47 - 1280x720@120Hz */ + { DRM_MODE("1280x720", 148500, 1280, 1390, + 1430, 1650, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 48 - 720x480@120Hz */ + { DRM_MODE("720x480", 54000, 720, 736, + 798, 858, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 49 - 720x480@120Hz */ + { DRM_MODE("720x480", 54000, 720, 736, + 798, 858, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 50 - 720(1440)x480i@120Hz */ + { DRM_MODE("720x480i", 27000, 720, 739, + 801, 858, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 51 - 720(1440)x480i@120Hz */ + { DRM_MODE("720x480i", 27000, 720, 739, + 801, 858, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 52 - 720x576@200Hz */ + { DRM_MODE("720x576", 108000, 720, 732, + 796, 864, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 53 - 720x576@200Hz */ + { DRM_MODE("720x576", 108000, 720, 732, + 796, 864, 0, 576, 581, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 54 - 720(1440)x576i@200Hz */ + { DRM_MODE("720x576i", 54000, 720, 732, + 795, 864, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 55 - 720(1440)x576i@200Hz */ + { DRM_MODE("720x576i", 54000, 720, 732, + 795, 864, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 56 - 720x480@240Hz */ + { DRM_MODE("720x480", 108000, 720, 736, + 798, 858, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 57 - 720x480@240Hz */ + { DRM_MODE("720x480", 108000, 720, 736, + 798, 858, 0, 480, 489, 495, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), + }, + /* 58 - 720(1440)x480i@240 */ + { DRM_MODE("720x480i", 54000, 720, 739, + 801, 858, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 59 - 720(1440)x480i@240 */ + { DRM_MODE("720x480i", 54000, 720, 739, + 801, 858, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), + }, + /* 60 - 1280x720@24Hz */ + { DRM_MODE("1280x720", 59400, 1280, 3040, + 3080, 3300, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 61 - 1280x720@25Hz */ + { DRM_MODE("1280x720", 74250, 1280, 3700, + 3740, 3960, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 62 - 1280x720@30Hz */ + { DRM_MODE("1280x720", 74250, 1280, 3040, + 3080, 3300, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 63 - 1920x1080@120Hz */ + { DRM_MODE("1920x1080", 297000, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* 64 - 1920x1080@100Hz */ + { DRM_MODE("1920x1080", 297000, 1920, 2448, + 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + }, + /* TERMINATOR */ + { }, +}; + +} diff --git a/kms++/src/modedb_dmt.cpp b/kms++/src/modedb_dmt.cpp new file mode 100644 index 0000000..e3f2ad5 --- /dev/null +++ b/kms++/src/modedb_dmt.cpp @@ -0,0 +1,410 @@ +/* From Linux kernel: drm_edid.c */ +/* + * Copyright (c) 2006 Luc Verhaegen (quirks list) + * Copyright (c) 2007-2008 Intel Corporation + * Jesse Barnes + * Copyright 2010 Red Hat, Inc. + * + * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from + * FB layer. + * Copyright (C) 2006 Dennis Munsie + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include + +namespace kms +{ + +#define DIV_ROUND(n, d) (((n) + (d) / 2) / (d)) + +#define DRM_MODE(nm, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ + .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 + + +/* + * Autogenerated from the DMT spec. + * This table is copied from xfree86/modes/xf86EdidModes.c. + */ +const Videomode dmt_modes[] = { + /* 0x01 - 640x350@85Hz */ + { DRM_MODE("640x350", 31500, 640, 672, + 736, 832, 0, 350, 382, 385, 445, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x02 - 640x400@85Hz */ + { DRM_MODE("640x400", 31500, 640, 672, + 736, 832, 0, 400, 401, 404, 445, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x03 - 720x400@85Hz */ + { DRM_MODE("720x400", 35500, 720, 756, + 828, 936, 0, 400, 401, 404, 446, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x04 - 640x480@60Hz */ + { DRM_MODE("640x480", 25175, 640, 656, + 752, 800, 0, 480, 490, 492, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x05 - 640x480@72Hz */ + { DRM_MODE("640x480", 31500, 640, 664, + 704, 832, 0, 480, 489, 492, 520, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x06 - 640x480@75Hz */ + { DRM_MODE("640x480", 31500, 640, 656, + 720, 840, 0, 480, 481, 484, 500, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x07 - 640x480@85Hz */ + { DRM_MODE("640x480", 36000, 640, 696, + 752, 832, 0, 480, 481, 484, 509, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x08 - 800x600@56Hz */ + { DRM_MODE("800x600", 36000, 800, 824, + 896, 1024, 0, 600, 601, 603, 625, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x09 - 800x600@60Hz */ + { DRM_MODE("800x600", 40000, 800, 840, + 968, 1056, 0, 600, 601, 605, 628, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x0a - 800x600@72Hz */ + { DRM_MODE("800x600", 50000, 800, 856, + 976, 1040, 0, 600, 637, 643, 666, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x0b - 800x600@75Hz */ + { DRM_MODE("800x600", 49500, 800, 816, + 896, 1056, 0, 600, 601, 604, 625, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x0c - 800x600@85Hz */ + { DRM_MODE("800x600", 56250, 800, 832, + 896, 1048, 0, 600, 601, 604, 631, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x0d - 800x600@120Hz RB */ + { DRM_MODE("800x600", 73250, 800, 848, + 880, 960, 0, 600, 603, 607, 636, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x0e - 848x480@60Hz */ + { DRM_MODE("848x480", 33750, 848, 864, + 976, 1088, 0, 480, 486, 494, 517, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x0f - 1024x768@43Hz, interlace */ + { DRM_MODE("1024x768i", 44900, 1024, 1032, + 1208, 1264, 0, 768, 768, 772, 817, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | + DRM_MODE_FLAG_INTERLACE) }, + /* 0x10 - 1024x768@60Hz */ + { DRM_MODE("1024x768", 65000, 1024, 1048, + 1184, 1344, 0, 768, 771, 777, 806, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x11 - 1024x768@70Hz */ + { DRM_MODE("1024x768", 75000, 1024, 1048, + 1184, 1328, 0, 768, 771, 777, 806, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x12 - 1024x768@75Hz */ + { DRM_MODE("1024x768", 78750, 1024, 1040, + 1136, 1312, 0, 768, 769, 772, 800, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x13 - 1024x768@85Hz */ + { DRM_MODE("1024x768", 94500, 1024, 1072, + 1168, 1376, 0, 768, 769, 772, 808, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x14 - 1024x768@120Hz RB */ + { DRM_MODE("1024x768", 115500, 1024, 1072, + 1104, 1184, 0, 768, 771, 775, 813, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x15 - 1152x864@75Hz */ + { DRM_MODE("1152x864", 108000, 1152, 1216, + 1344, 1600, 0, 864, 865, 868, 900, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x55 - 1280x720@60Hz */ + { DRM_MODE("1280x720", 74250, 1280, 1390, + 1430, 1650, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x16 - 1280x768@60Hz RB */ + { DRM_MODE("1280x768", 68250, 1280, 1328, + 1360, 1440, 0, 768, 771, 778, 790, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x17 - 1280x768@60Hz */ + { DRM_MODE("1280x768", 79500, 1280, 1344, + 1472, 1664, 0, 768, 771, 778, 798, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x18 - 1280x768@75Hz */ + { DRM_MODE("1280x768", 102250, 1280, 1360, + 1488, 1696, 0, 768, 771, 778, 805, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x19 - 1280x768@85Hz */ + { DRM_MODE("1280x768", 117500, 1280, 1360, + 1496, 1712, 0, 768, 771, 778, 809, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x1a - 1280x768@120Hz RB */ + { DRM_MODE("1280x768", 140250, 1280, 1328, + 1360, 1440, 0, 768, 771, 778, 813, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x1b - 1280x800@60Hz RB */ + { DRM_MODE("1280x800", 71000, 1280, 1328, + 1360, 1440, 0, 800, 803, 809, 823, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x1c - 1280x800@60Hz */ + { DRM_MODE("1280x800", 83500, 1280, 1352, + 1480, 1680, 0, 800, 803, 809, 831, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x1d - 1280x800@75Hz */ + { DRM_MODE("1280x800", 106500, 1280, 1360, + 1488, 1696, 0, 800, 803, 809, 838, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x1e - 1280x800@85Hz */ + { DRM_MODE("1280x800", 122500, 1280, 1360, + 1496, 1712, 0, 800, 803, 809, 843, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x1f - 1280x800@120Hz RB */ + { DRM_MODE("1280x800", 146250, 1280, 1328, + 1360, 1440, 0, 800, 803, 809, 847, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x20 - 1280x960@60Hz */ + { DRM_MODE("1280x960", 108000, 1280, 1376, + 1488, 1800, 0, 960, 961, 964, 1000, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x21 - 1280x960@85Hz */ + { DRM_MODE("1280x960", 148500, 1280, 1344, + 1504, 1728, 0, 960, 961, 964, 1011, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x22 - 1280x960@120Hz RB */ + { DRM_MODE("1280x960", 175500, 1280, 1328, + 1360, 1440, 0, 960, 963, 967, 1017, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x23 - 1280x1024@60Hz */ + { DRM_MODE("1280x1024", 108000, 1280, 1328, + 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x24 - 1280x1024@75Hz */ + { DRM_MODE("1280x1024", 135000, 1280, 1296, + 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x25 - 1280x1024@85Hz */ + { DRM_MODE("1280x1024", 157500, 1280, 1344, + 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x26 - 1280x1024@120Hz RB */ + { DRM_MODE("1280x1024", 187250, 1280, 1328, + 1360, 1440, 0, 1024, 1027, 1034, 1084, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x27 - 1360x768@60Hz */ + { DRM_MODE("1360x768", 85500, 1360, 1424, + 1536, 1792, 0, 768, 771, 777, 795, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x28 - 1360x768@120Hz RB */ + { DRM_MODE("1360x768", 148250, 1360, 1408, + 1440, 1520, 0, 768, 771, 776, 813, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x51 - 1366x768@60Hz */ + { DRM_MODE("1366x768", 85500, 1366, 1436, + 1579, 1792, 0, 768, 771, 774, 798, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x56 - 1366x768@60Hz */ + { DRM_MODE("1366x768", 72000, 1366, 1380, + 1436, 1500, 0, 768, 769, 772, 800, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x29 - 1400x1050@60Hz RB */ + { DRM_MODE("1400x1050", 101000, 1400, 1448, + 1480, 1560, 0, 1050, 1053, 1057, 1080, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x2a - 1400x1050@60Hz */ + { DRM_MODE("1400x1050", 121750, 1400, 1488, + 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x2b - 1400x1050@75Hz */ + { DRM_MODE("1400x1050", 156000, 1400, 1504, + 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x2c - 1400x1050@85Hz */ + { DRM_MODE("1400x1050", 179500, 1400, 1504, + 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x2d - 1400x1050@120Hz RB */ + { DRM_MODE("1400x1050", 208000, 1400, 1448, + 1480, 1560, 0, 1050, 1053, 1057, 1112, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x2e - 1440x900@60Hz RB */ + { DRM_MODE("1440x900", 88750, 1440, 1488, + 1520, 1600, 0, 900, 903, 909, 926, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x2f - 1440x900@60Hz */ + { DRM_MODE("1440x900", 106500, 1440, 1520, + 1672, 1904, 0, 900, 903, 909, 934, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x30 - 1440x900@75Hz */ + { DRM_MODE("1440x900", 136750, 1440, 1536, + 1688, 1936, 0, 900, 903, 909, 942, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x31 - 1440x900@85Hz */ + { DRM_MODE("1440x900", 157000, 1440, 1544, + 1696, 1952, 0, 900, 903, 909, 948, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x32 - 1440x900@120Hz RB */ + { DRM_MODE("1440x900", 182750, 1440, 1488, + 1520, 1600, 0, 900, 903, 909, 953, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x53 - 1600x900@60Hz */ + { DRM_MODE("1600x900", 108000, 1600, 1624, + 1704, 1800, 0, 900, 901, 904, 1000, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x33 - 1600x1200@60Hz */ + { DRM_MODE("1600x1200", 162000, 1600, 1664, + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x34 - 1600x1200@65Hz */ + { DRM_MODE("1600x1200", 175500, 1600, 1664, + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x35 - 1600x1200@70Hz */ + { DRM_MODE("1600x1200", 189000, 1600, 1664, + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x36 - 1600x1200@75Hz */ + { DRM_MODE("1600x1200", 202500, 1600, 1664, + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x37 - 1600x1200@85Hz */ + { DRM_MODE("1600x1200", 229500, 1600, 1664, + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x38 - 1600x1200@120Hz RB */ + { DRM_MODE("1600x1200", 268250, 1600, 1648, + 1680, 1760, 0, 1200, 1203, 1207, 1271, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x39 - 1680x1050@60Hz RB */ + { DRM_MODE("1680x1050", 119000, 1680, 1728, + 1760, 1840, 0, 1050, 1053, 1059, 1080, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x3a - 1680x1050@60Hz */ + { DRM_MODE("1680x1050", 146250, 1680, 1784, + 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x3b - 1680x1050@75Hz */ + { DRM_MODE("1680x1050", 187000, 1680, 1800, + 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x3c - 1680x1050@85Hz */ + { DRM_MODE("1680x1050", 214750, 1680, 1808, + 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x3d - 1680x1050@120Hz RB */ + { DRM_MODE("1680x1050", 245500, 1680, 1728, + 1760, 1840, 0, 1050, 1053, 1059, 1112, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x3e - 1792x1344@60Hz */ + { DRM_MODE("1792x1344", 204750, 1792, 1920, + 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x3f - 1792x1344@75Hz */ + { DRM_MODE("1792x1344", 261000, 1792, 1888, + 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x40 - 1792x1344@120Hz RB */ + { DRM_MODE("1792x1344", 333250, 1792, 1840, + 1872, 1952, 0, 1344, 1347, 1351, 1423, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x41 - 1856x1392@60Hz */ + { DRM_MODE("1856x1392", 218250, 1856, 1952, + 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x42 - 1856x1392@75Hz */ + { DRM_MODE("1856x1392", 288000, 1856, 1984, + 2208, 2560, 0, 1392, 1393, 1396, 1500, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x43 - 1856x1392@120Hz RB */ + { DRM_MODE("1856x1392", 356500, 1856, 1904, + 1936, 2016, 0, 1392, 1395, 1399, 1474, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x52 - 1920x1080@60Hz */ + { DRM_MODE("1920x1080", 148500, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x44 - 1920x1200@60Hz RB */ + { DRM_MODE("1920x1200", 154000, 1920, 1968, + 2000, 2080, 0, 1200, 1203, 1209, 1235, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x45 - 1920x1200@60Hz */ + { DRM_MODE("1920x1200", 193250, 1920, 2056, + 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x46 - 1920x1200@75Hz */ + { DRM_MODE("1920x1200", 245250, 1920, 2056, + 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x47 - 1920x1200@85Hz */ + { DRM_MODE("1920x1200", 281250, 1920, 2064, + 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x48 - 1920x1200@120Hz RB */ + { DRM_MODE("1920x1200", 317000, 1920, 1968, + 2000, 2080, 0, 1200, 1203, 1209, 1271, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x49 - 1920x1440@60Hz */ + { DRM_MODE("1920x1440", 234000, 1920, 2048, + 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x4a - 1920x1440@75Hz */ + { DRM_MODE("1920x1440", 297000, 1920, 2064, + 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x4b - 1920x1440@120Hz RB */ + { DRM_MODE("1920x1440", 380500, 1920, 1968, + 2000, 2080, 0, 1440, 1443, 1447, 1525, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x54 - 2048x1152@60Hz */ + { DRM_MODE("2048x1152", 162000, 2048, 2074, + 2154, 2250, 0, 1152, 1153, 1156, 1200, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x4c - 2560x1600@60Hz RB */ + { DRM_MODE("2560x1600", 268500, 2560, 2608, + 2640, 2720, 0, 1600, 1603, 1609, 1646, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x4d - 2560x1600@60Hz */ + { DRM_MODE("2560x1600", 348500, 2560, 2752, + 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x4e - 2560x1600@75Hz */ + { DRM_MODE("2560x1600", 443250, 2560, 2768, + 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x4f - 2560x1600@85Hz */ + { DRM_MODE("2560x1600", 505250, 2560, 2768, + 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 0x50 - 2560x1600@120Hz RB */ + { DRM_MODE("2560x1600", 552750, 2560, 2608, + 2640, 2720, 0, 1600, 1603, 1609, 1694, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x57 - 4096x2160@60Hz RB */ + { DRM_MODE("4096x2160", 556744, 4096, 4104, + 4136, 4176, 0, 2160, 2208, 2216, 2222, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 0x58 - 4096x2160@59.94Hz RB */ + { DRM_MODE("4096x2160", 556188, 4096, 4104, + 4136, 4176, 0, 2160, 2208, 2216, 2222, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* TERMINATOR */ + { }, +}; + +} diff --git a/kms++/src/pixelformats.cpp b/kms++/src/pixelformats.cpp new file mode 100644 index 0000000..f2b1137 --- /dev/null +++ b/kms++/src/pixelformats.cpp @@ -0,0 +1,32 @@ +#include + +#include + +using namespace std; + +namespace kms +{ +static const map format_info_array = { + /* YUV packed */ + { PixelFormat::UYVY, { 1, { { 16, 2, 1 } }, } }, + { PixelFormat::YUYV, { 1, { { 16, 2, 1 } }, } }, + { PixelFormat::YVYU, { 1, { { 16, 2, 1 } }, } }, + { PixelFormat::VYUY, { 1, { { 16, 2, 1 } }, } }, + /* YUV semi-planar */ + { PixelFormat::NV12, { 2, { { 8, 1, 1, }, { 8, 2, 2 } }, } }, + { PixelFormat::NV21, { 2, { { 8, 1, 1, }, { 8, 2, 2 } }, } }, + /* RGB16 */ + { PixelFormat::RGB565, { 1, { { 16, 1, 1 } }, } }, + /* RGB32 */ + { PixelFormat::XRGB8888, { 1, { { 32, 1, 1 } }, } }, + { PixelFormat::XBGR8888, { 1, { { 32, 1, 1 } }, } }, + { PixelFormat::ARGB8888, { 1, { { 32, 1, 1 } }, } }, + { PixelFormat::ABGR8888, { 1, { { 32, 1, 1 } }, } }, +}; + +const struct PixelFormatInfo& get_pixel_format_info(PixelFormat format) +{ + return format_info_array.at(format); +} + +} diff --git a/kms++/src/plane.cpp b/kms++/src/plane.cpp new file mode 100644 index 0000000..10aaeda --- /dev/null +++ b/kms++/src/plane.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +struct PlanePriv +{ + drmModePlanePtr drm_plane; +}; + +Plane::Plane(Card &card, uint32_t id, uint32_t idx) + :DrmPropObject(card, id, DRM_MODE_OBJECT_PLANE, idx) +{ + m_priv = new PlanePriv(); + m_priv->drm_plane = drmModeGetPlane(this->card().fd(), this->id()); + assert(m_priv->drm_plane); +} + +Plane::~Plane() +{ + drmModeFreePlane(m_priv->drm_plane); + delete m_priv; +} + +bool Plane::supports_crtc(Crtc* crtc) const +{ + return m_priv->drm_plane->possible_crtcs & (1 << crtc->idx()); +} + +bool Plane::supports_format(PixelFormat fmt) const +{ + auto p = m_priv->drm_plane; + + for (unsigned i = 0; i < p->count_formats; ++i) + if ((uint32_t)fmt == p->formats[i]) + return true; + + return false; +} + +PlaneType Plane::plane_type() const +{ + if (card().has_has_universal_planes()) + return (PlaneType)get_prop_value("type"); + else + return PlaneType::Overlay; +} + +vector Plane::get_formats() const +{ + auto p = m_priv->drm_plane; + vector r; + + for (unsigned i = 0; i < p->count_formats; ++i) + r.push_back((PixelFormat) p->formats[i]); + + return r; +} + +uint32_t Plane::crtc_id() const +{ + return m_priv->drm_plane->crtc_id; +} + +uint32_t Plane::fb_id() const +{ + return m_priv->drm_plane->fb_id; +} + +uint32_t Plane::crtc_x() const +{ + return m_priv->drm_plane->crtc_x; +} + +uint32_t Plane::crtc_y() const +{ + return m_priv->drm_plane->crtc_y; +} + +uint32_t Plane::x() const +{ + return m_priv->drm_plane->x; +} + +uint32_t Plane::y() const +{ + return m_priv->drm_plane->y; +} + +uint32_t Plane::gamma_size() const +{ + return m_priv->drm_plane->gamma_size; +} + +} diff --git a/kms++/src/property.cpp b/kms++/src/property.cpp new file mode 100644 index 0000000..ee79922 --- /dev/null +++ b/kms++/src/property.cpp @@ -0,0 +1,87 @@ +#include +#include + +#include + +using namespace std; + +namespace kms +{ + +struct PropertyPriv +{ + drmModePropertyPtr drm_prop; +}; + +Property::Property(Card& card, uint32_t id) + : DrmObject(card, id, DRM_MODE_OBJECT_PROPERTY) +{ + m_priv = new PropertyPriv(); + m_priv->drm_prop = drmModeGetProperty(card.fd(), id); + m_name = m_priv->drm_prop->name; + + PropertyType t; + drmModePropertyPtr p = m_priv->drm_prop; + if (drm_property_type_is(p, DRM_MODE_PROP_BITMASK)) + t = PropertyType::Bitmask; + else if (drm_property_type_is(p, DRM_MODE_PROP_BLOB)) + t = PropertyType::Blob; + else if (drm_property_type_is(p, DRM_MODE_PROP_ENUM)) + t = PropertyType::Enum; + else if (drm_property_type_is(p, DRM_MODE_PROP_OBJECT)) + t = PropertyType::Object; + else if (drm_property_type_is(p, DRM_MODE_PROP_RANGE)) + t = PropertyType::Range; + else if (drm_property_type_is(p, DRM_MODE_PROP_SIGNED_RANGE)) + t = PropertyType::SignedRange; + else + throw invalid_argument("Invalid property type"); + + m_type = t; +} + +Property::~Property() +{ + drmModeFreeProperty(m_priv->drm_prop); + delete m_priv; +} + +const string& Property::name() const +{ + return m_name; +} + +bool Property::is_immutable() const +{ + return m_priv->drm_prop->flags & DRM_MODE_PROP_IMMUTABLE; +} + +bool Property::is_pending() const +{ + return m_priv->drm_prop->flags & DRM_MODE_PROP_PENDING; +} + +vector Property::get_values() const +{ + drmModePropertyPtr p = m_priv->drm_prop; + return vector(p->values, p->values + p->count_values); +} + +map Property::get_enums() const +{ + drmModePropertyPtr p = m_priv->drm_prop; + + map map; + + for (int i = 0; i < p->count_enums; ++i) + map[p->enums[i].value] = string(p->enums[i].name); + + return map; +} + +vector Property::get_blob_ids() const +{ + drmModePropertyPtr p = m_priv->drm_prop; + return vector(p->blob_ids, p->blob_ids + p->count_blobs); +} +} diff --git a/kms++/src/videomode.cpp b/kms++/src/videomode.cpp new file mode 100644 index 0000000..30d47f8 --- /dev/null +++ b/kms++/src/videomode.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include +#include "helpers.h" + +using namespace std; + +namespace kms +{ + +unique_ptr Videomode::to_blob(Card& card) const +{ + drmModeModeInfo drm_mode = video_mode_to_drm_mode(*this); + + return unique_ptr(new Blob(card, &drm_mode, sizeof(drm_mode))); +} + +} diff --git a/kms++/videomode.cpp b/kms++/videomode.cpp deleted file mode 100644 index 5c98c00..0000000 --- a/kms++/videomode.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -#include "videomode.h" -#include "helpers.h" - -using namespace std; - -namespace kms -{ - -unique_ptr Videomode::to_blob(Card& card) const -{ - drmModeModeInfo drm_mode = video_mode_to_drm_mode(*this); - - return unique_ptr(new Blob(card, &drm_mode, sizeof(drm_mode))); -} - -} diff --git a/kms++/videomode.h b/kms++/videomode.h deleted file mode 100644 index f9abaf9..0000000 --- a/kms++/videomode.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "blob.h" - -namespace kms -{ - -struct Videomode -{ - std::string name; - - uint32_t clock; - uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; - uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; - - uint32_t vrefresh; - - uint32_t flags; // DRM_MODE_FLAG_* - uint32_t type; // DRM_MODE_TYPE_* - - std::unique_ptr to_blob(Card& card) const; - - uint16_t hfp() const { return hsync_start - hdisplay; } - uint16_t hsw() const { return hsync_end - hsync_start; } - uint16_t hbp() const { return htotal - hsync_end; } - - 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; } -}; - -} diff --git a/kms++util/colorbar.cpp b/kms++util/colorbar.cpp index 6a5dbc4..9e6e68d 100644 --- a/kms++util/colorbar.cpp +++ b/kms++util/colorbar.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include "kms++util.h" namespace kms diff --git a/kms++util/cpuframebuffer.h b/kms++util/cpuframebuffer.h index d2073bc..1498528 100644 --- a/kms++util/cpuframebuffer.h +++ b/kms++util/cpuframebuffer.h @@ -1,6 +1,6 @@ #pragma once -#include "kms++.h" +#include namespace kms { diff --git a/kms++util/drawing.cpp b/kms++util/drawing.cpp index 9018817..2ca567c 100644 --- a/kms++util/drawing.cpp +++ b/kms++util/drawing.cpp @@ -1,5 +1,5 @@ -#include +#include #include using namespace std; diff --git a/kms++util/extcpuframebuffer.h b/kms++util/extcpuframebuffer.h index 172841f..5d3be74 100644 --- a/kms++util/extcpuframebuffer.h +++ b/kms++util/extcpuframebuffer.h @@ -1,6 +1,6 @@ #pragma once -#include "kms++.h" +#include namespace kms { diff --git a/kms++util/kms++util.h b/kms++util/kms++util.h index 6c835c8..0c07d18 100644 --- a/kms++util/kms++util.h +++ b/kms++util/kms++util.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "color.h" #include diff --git a/kms++util/testpat.cpp b/kms++util/testpat.cpp index b859180..7a2e4d3 100644 --- a/kms++util/testpat.cpp +++ b/kms++util/testpat.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include #include "stopwatch.h" diff --git a/kmscube/cube-gbm.cpp b/kmscube/cube-gbm.cpp index f6d312b..93ebece 100644 --- a/kmscube/cube-gbm.cpp +++ b/kmscube/cube-gbm.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include "cube-egl.h" #include "cube-gles2.h" diff --git a/py/pykms.cpp b/py/pykms.cpp index deb8276..57ca363 100644 --- a/py/pykms.cpp +++ b/py/pykms.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include namespace py = pybind11; diff --git a/py/pykmsbase.cpp b/py/pykmsbase.cpp index efc760a..3d1998e 100644 --- a/py/pykmsbase.cpp +++ b/py/pykmsbase.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include namespace py = pybind11; diff --git a/py/pykmsutil.cpp b/py/pykmsutil.cpp index 0d4cf89..f060bdf 100644 --- a/py/pykmsutil.cpp +++ b/py/pykmsutil.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include namespace py = pybind11; diff --git a/utils/kmsblank.cpp b/utils/kmsblank.cpp index 8b883bb..864f269 100644 --- a/utils/kmsblank.cpp +++ b/utils/kmsblank.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include "opts.h" diff --git a/utils/kmscapture.cpp b/utils/kmscapture.cpp index 7fc054e..dc65f1e 100644 --- a/utils/kmscapture.cpp +++ b/utils/kmscapture.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/utils/kmsprint.cpp b/utils/kmsprint.cpp index 3b17f5b..7c8e01f 100644 --- a/utils/kmsprint.cpp +++ b/utils/kmsprint.cpp @@ -5,7 +5,7 @@ #include #include -#include "kms++.h" +#include #include "opts.h" #include "kms++util.h" #include "strhelpers.h" diff --git a/utils/kmsview.cpp b/utils/kmsview.cpp index b59e004..8efcecd 100644 --- a/utils/kmsview.cpp +++ b/utils/kmsview.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include diff --git a/utils/testpat.cpp b/utils/testpat.cpp index 094e22a..4fe8d0b 100644 --- a/utils/testpat.cpp +++ b/utils/testpat.cpp @@ -5,8 +5,8 @@ #include #include -#include -#include +#include +#include #include #include -- cgit v1.2.3