diff options
author | Haibo Huang <hhb@google.com> | 2020-04-01 14:42:37 -0700 |
---|---|---|
committer | Haibo Huang <hhb@google.com> | 2020-04-03 22:38:58 +0000 |
commit | 57240f80a21f4f7d9c6ceedf61549e0adf2c95b2 (patch) | |
tree | d2106d3321762d3b10ad49d3b4e93d1bbec254a0 | |
parent | 6f7131a65dbe7d76eecc21643b51b50bae352c6a (diff) | |
parent | cff8b2fd797537e36d5e16c1ac8e3303321e50b2 (diff) | |
download | libkmsxx-57240f80a21f4f7d9c6ceedf61549e0adf2c95b2.tar.gz |
Upgrade libkmsxx to cff8b2fd797537e36d5e16c1ac8e3303321e50b2
Exempt-From-Owner-Approval: upgrade
Change-Id: I6c7aae30d8ba09e05d47b03b55c58ac782097742
55 files changed, 748 insertions, 416 deletions
diff --git a/.gitmodules b/.gitmodules index c6d1083..6ac367e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "ext/pybind11"] path = ext/pybind11 url = https://github.com/pybind/pybind11.git +[submodule "ext/fmt"] + path = ext/fmt + url = https://github.com/fmtlib/fmt.git diff --git a/.travis.yml b/.travis.yml index 353026a..713f0fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ -# Ubuntu 14.04 Trusty support +# Ubuntu 18.04 Trusty support sudo: required -dist: trusty +dist: bionic # Only build test master & travis branches: @@ -13,8 +13,6 @@ language: cpp addons: apt: - sources: &sources - - ubuntu-toolchain-r-test packages: &packages - libegl1-mesa-dev - libgles2-mesa-dev @@ -30,45 +28,69 @@ matrix: - compiler: gcc addons: apt: - sources: *sources packages: [*packages, 'g++-4.8'] env: MYCC=gcc-4.8 MYCXX=g++-4.8 - compiler: gcc addons: apt: - sources: *sources - packages: [*packages, 'g++-4.9'] - # g++-4.9 gives a warning, disable it - env: MYCC=gcc-4.9 MYCXX=g++-4.9 CXXFLAGS=-Wno-maybe-uninitialized - - - compiler: gcc - addons: - apt: - sources: *sources packages: [*packages, 'g++-5'] env: MYCC=gcc-5 MYCXX=g++-5 - compiler: gcc addons: apt: - sources: *sources packages: [*packages, 'g++-6'] env: MYCC=gcc-6 MYCXX=g++-6 - compiler: gcc addons: apt: - sources: *sources packages: [*packages, 'g++-7'] env: MYCC=gcc-7 MYCXX=g++-7 + - compiler: gcc + addons: + apt: + packages: [*packages, 'g++-8'] + env: MYCC=gcc-8 MYCXX=g++-8 + - compiler: clang addons: apt: - sources: [*sources, 'llvm-toolchain-precise-3.8'] - packages: [*packages, 'clang-3.8'] - env: MYCC=clang-3.8 MYCXX=clang++-3.8 + packages: [*packages, 'clang-3.9'] + env: MYCC=clang-3.9 MYCXX=clang++-3.9 + + - compiler: clang + addons: + apt: + packages: [*packages, 'clang-4.0'] + env: MYCC=clang-4.0 MYCXX=clang++-4.0 + + - compiler: clang + addons: + apt: + packages: [*packages, 'clang-5.0'] + env: MYCC=clang-5.0 MYCXX=clang++-5.0 + + - compiler: clang + addons: + apt: + packages: [*packages, 'clang-6.0'] + env: MYCC=clang-6.0 MYCXX=clang++-6.0 + + - compiler: clang + addons: + apt: + packages: [*packages, 'clang-7'] + env: MYCC=clang-7 MYCXX=clang++-7 + + - compiler: clang + addons: + apt: + packages: [*packages, 'clang-8'] + env: MYCC=clang-8 MYCXX=clang++-8 + # Build steps script: @@ -19,37 +19,20 @@ cc_library_shared { rtti: true, srcs: [ - "kms++/src/atomicreq.cpp", - "kms++/src/card.cpp", - "kms++/src/crtc.cpp", - "kms++/src/drmpropobject.cpp", - "kms++/src/encoder.cpp", - "kms++/src/framebuffer.cpp", - "kms++/src/modedb_cea.cpp", - "kms++/src/modedb_dmt.cpp", - "kms++/src/pixelformats.cpp", - "kms++/src/property.cpp", - "kms++/src/blob.cpp", - "kms++/src/connector.cpp", - "kms++/src/drmobject.cpp", - "kms++/src/dumbframebuffer.cpp", - "kms++/src/extframebuffer.cpp", - "kms++/src/helpers.cpp", - "kms++/src/mode_cvt.cpp", - "kms++/src/modedb.cpp", - "kms++/src/plane.cpp", - "kms++/src/videomode.cpp", + "kms++/src/*.cpp", ], cflags: [ - "-std=c++11", + "-DFMT_EXCEPTIONS=0", // fmtlib is not built with exception. "-Wall", "-Wextra", "-Wno-unused-parameter", "-fexceptions", + "-include array", ], shared_libs: [ + "libbase", // for fmtlib "libdrm", ], diff --git a/CMakeLists.txt b/CMakeLists.txt index f2f24fe..9e2f492 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ set(KMSXX_PYTHON_VERSION "python3;python2" CACHE STRING "Python pkgconfig packag set(KMSXX_ENABLE_KMSCUBE OFF CACHE BOOL "Enable kmscube") set(KMSXX_ENABLE_THREADING ON CACHE BOOL "Enable threading for parallelized drawing") +set(KMSXX_ENABLE_LIBDRMOMAP ON CACHE BOOL "Enable OMAP-specific extensions") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra -Wno-unused-parameter") @@ -66,9 +67,14 @@ if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) endif() find_package(PkgConfig REQUIRED) -pkg_check_modules(LIBDRM libdrm>=2.4.64 REQUIRED) +pkg_check_modules(LIBDRM libdrm>=2.4.71 REQUIRED) + +if (KMSXX_ENABLE_LIBDRMOMAP) + pkg_check_modules(LIBDRM_OMAP libdrm_omap) +else() + set(LIBDRM_OMAP_FOUND FALSE) +endif() -pkg_check_modules(LIBDRM_OMAP libdrm_omap) if(LIBDRM_OMAP_FOUND) add_definitions(-DHAS_LIBDRM_OMAP) endif() @@ -79,6 +85,8 @@ add_subdirectory(kms++) add_subdirectory(kms++util) add_subdirectory(utils) +add_subdirectory(ext/fmt) + if(KMSXX_ENABLE_KMSCUBE) add_subdirectory(kmscube) endif() @@ -9,11 +9,11 @@ third_party { type: GIT value: "https://github.com/tomba/kmsxx" } - version: "a5545df02b40414c2bf3abc60cf629c5f59d00ec" + version: "cff8b2fd797537e36d5e16c1ac8e3303321e50b2" license_type: RECIPROCAL last_upgrade_date { - year: 2019 - month: 7 - day: 30 + year: 2020 + month: 4 + day: 1 } } @@ -72,13 +72,14 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) You can use the following cmake flags to control the build. Use `-DFLAG=VALUE` to set them. -Option name | Values | Default | Notes ---------------------- | ------------- | --------------- | -------- -CMAKE_BUILD_TYPE | Release/Debug | Release | -BUILD_SHARED_LIBS | ON/OFF | OFF | -KMSXX_ENABLE_PYTHON | ON/OFF | ON | -KMSXX_ENABLE_KMSCUBE | ON/OFF | OFF | -KMSXX_PYTHON_VERSION | python3/python2 | python3;python2 | Name of the python pkgconfig file +Option name | Values | Default | Notes +------------------------ | ------------- | --------------- | -------- +CMAKE_BUILD_TYPE | Release/Debug | Release | +BUILD_SHARED_LIBS | ON/OFF | OFF | +KMSXX_ENABLE_PYTHON | ON/OFF | ON | +KMSXX_ENABLE_KMSCUBE | ON/OFF | OFF | +KMSXX_ENABLE_LIBDRMOMAP | ON/OFF | OFF | +KMSXX_PYTHON_VERSION | python3/python2 | python3;python2 | Name of the python pkgconfig file ## Env variables diff --git a/ext/fmt b/ext/fmt new file mode 160000 +Subproject 7512a55aa3ae309587ca89668ef9ec4074a51a1 diff --git a/kms++/CMakeLists.txt b/kms++/CMakeLists.txt index 10352a2..6e21fa5 100644 --- a/kms++/CMakeLists.txt +++ b/kms++/CMakeLists.txt @@ -22,12 +22,20 @@ target_include_directories(kms++ PUBLIC $<INSTALL_INTERFACE:include> PRIVATE src) -target_link_libraries(kms++ ${LIBDRM_LIBRARIES} ${LIBDRM_OMAP_LIBRARIES}) +target_link_libraries(kms++ ${LIBDRM_LIBRARIES} ${LIBDRM_OMAP_LIBRARIES} fmt::fmt-header-only) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/kms++.pc.in ${CMAKE_CURRENT_BINARY_DIR}/kms++.pc @ONLY) + +# Set a dummy SOVERSION just to avoid having a naked .so file in the filesystem. +# This version number doesn't make any promise about API/ABI stability. set_target_properties(kms++ PROPERTIES - PUBLIC_HEADER "${PUB_HDRS}") + PUBLIC_HEADER "${PUB_HDRS}" + SOVERSION 0) install(TARGETS kms++ LIBRARY DESTINATION lib ARCHIVE DESTINATION lib PUBLIC_HEADER DESTINATION include/kms++) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kms++.pc + DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig) diff --git a/kms++/inc/kms++/blob.h b/kms++/inc/kms++/blob.h index fd872f1..31e915c 100644 --- a/kms++/inc/kms++/blob.h +++ b/kms++/inc/kms++/blob.h @@ -11,7 +11,7 @@ class Blob : public DrmObject public: Blob(Card& card, uint32_t blob_id); Blob(Card& card, void* data, size_t len); - virtual ~Blob(); + ~Blob() override; std::vector<uint8_t> data(); diff --git a/kms++/inc/kms++/card.h b/kms++/inc/kms++/card.h index 099d5b5..e561ffc 100644 --- a/kms++/inc/kms++/card.h +++ b/kms++/inc/kms++/card.h @@ -10,6 +10,16 @@ namespace kms { +struct CardVersion +{ + int major; + int minor; + int patchlevel; + std::string name; + std::string date; + std::string desc; +}; + class Card { friend class Framebuffer; @@ -40,13 +50,13 @@ public: bool has_dumb_buffers() const { return m_has_dumb; } bool has_kms() const; - const std::vector<Connector*> get_connectors() const { return m_connectors; } - const std::vector<Encoder*> get_encoders() const { return m_encoders; } - const std::vector<Crtc*> get_crtcs() const { return m_crtcs; } - const std::vector<Plane*> get_planes() const { return m_planes; } - const std::vector<Property*> get_properties() const { return m_properties; } + std::vector<Connector*> get_connectors() const { return m_connectors; } + std::vector<Encoder*> get_encoders() const { return m_encoders; } + std::vector<Crtc*> get_crtcs() const { return m_crtcs; } + std::vector<Plane*> get_planes() const { return m_planes; } + std::vector<Property*> get_properties() const { return m_properties; } - const std::vector<DrmObject*> get_objects() const; + std::vector<DrmObject*> get_objects() const; std::vector<Pipeline> get_connected_pipelines(); @@ -54,7 +64,8 @@ public: int disable_all(); - const std::string& version_name() const { return m_version_name; } + const std::string& version_name() const { return m_version.name; } + const CardVersion& version() const { return m_version; } private: void setup(); @@ -76,11 +87,6 @@ private: bool m_has_universal_planes; bool m_has_dumb; - int m_version_major; - int m_version_minor; - int m_version_patchlevel; - std::string m_version_name; - std::string m_version_date; - std::string m_version_desc; + CardVersion m_version; }; } diff --git a/kms++/inc/kms++/connector.h b/kms++/inc/kms++/connector.h index 155f916..323d37d 100644 --- a/kms++/inc/kms++/connector.h +++ b/kms++/inc/kms++/connector.h @@ -46,9 +46,9 @@ public: std::vector<Encoder*> get_encoders() const; private: Connector(Card& card, uint32_t id, uint32_t idx); - ~Connector(); + ~Connector() override; - void setup(); + void setup() override; void restore_mode(); ConnectorPriv* m_priv; diff --git a/kms++/inc/kms++/crtc.h b/kms++/inc/kms++/crtc.h index ea20ef8..990fc20 100644 --- a/kms++/inc/kms++/crtc.h +++ b/kms++/inc/kms++/crtc.h @@ -42,9 +42,9 @@ public: int gamma_size() const; private: Crtc(Card& card, uint32_t id, uint32_t idx); - ~Crtc(); + ~Crtc() override; - void setup(); + void setup() override; void restore_mode(Connector *conn); CrtcPriv* m_priv; diff --git a/kms++/inc/kms++/decls.h b/kms++/inc/kms++/decls.h index 91bce13..438dad5 100644 --- a/kms++/inc/kms++/decls.h +++ b/kms++/inc/kms++/decls.h @@ -12,6 +12,7 @@ class DrmPropObject; class DumbFramebuffer; class Encoder; class ExtFramebuffer; +class DmabufFramebuffer; class Framebuffer; class PageFlipHandlerBase; class Plane; diff --git a/kms++/inc/kms++/dmabufframebuffer.h b/kms++/inc/kms++/dmabufframebuffer.h new file mode 100644 index 0000000..a17b1f1 --- /dev/null +++ b/kms++/inc/kms++/dmabufframebuffer.h @@ -0,0 +1,52 @@ +#pragma once + +#include "framebuffer.h" +#include "pixelformats.h" +#include <vector> + +namespace kms +{ + +class DmabufFramebuffer : public Framebuffer +{ +public: + DmabufFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, + std::vector<int> fds, std::vector<uint32_t> pitches, std::vector<uint32_t> offsets, std::vector<uint64_t> modifiers = {}); + ~DmabufFramebuffer() override; + + uint32_t width() const override { return Framebuffer::width(); } + uint32_t height() const override { return Framebuffer::height(); } + + PixelFormat format() const override { return m_format; } + unsigned num_planes() const override { return m_num_planes; } + + uint32_t handle(unsigned plane) const { return m_planes.at(plane).handle; } + uint32_t stride(unsigned plane) const override { return m_planes.at(plane).stride; } + uint32_t size(unsigned plane) const override { return m_planes.at(plane).size; } + uint32_t offset(unsigned plane) const override { return m_planes.at(plane).offset; } + uint8_t* map(unsigned plane) override; + int prime_fd(unsigned plane) override; + + void begin_cpu_access(CpuAccess access) override; + void end_cpu_access() override; + +private: + struct FramebufferPlane { + uint32_t handle; + int prime_fd; + uint32_t size; + uint32_t stride; + uint32_t offset; + uint64_t modifier; + uint8_t *map; + }; + + unsigned m_num_planes; + std::array<FramebufferPlane, 4> m_planes; + + PixelFormat m_format; + + uint32_t m_sync_flags = 0; +}; + +} diff --git a/kms++/inc/kms++/drmpropobject.h b/kms++/inc/kms++/drmpropobject.h index d9ba58e..809caf5 100644 --- a/kms++/inc/kms++/drmpropobject.h +++ b/kms++/inc/kms++/drmpropobject.h @@ -31,7 +31,7 @@ protected: DrmPropObject(Card& card, uint32_t object_type); DrmPropObject(Card& card, uint32_t id, uint32_t object_type, uint32_t idx = 0); - virtual ~DrmPropObject(); + ~DrmPropObject() override; private: std::map<uint32_t, uint64_t> m_prop_values; diff --git a/kms++/inc/kms++/dumbframebuffer.h b/kms++/inc/kms++/dumbframebuffer.h index fb99d0e..f450b2c 100644 --- a/kms++/inc/kms++/dumbframebuffer.h +++ b/kms++/inc/kms++/dumbframebuffer.h @@ -11,20 +11,20 @@ class DumbFramebuffer : public Framebuffer 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(); + ~DumbFramebuffer() override; - uint32_t width() const { return Framebuffer::width(); } - uint32_t height() const { return Framebuffer::height(); } + uint32_t width() const override { return Framebuffer::width(); } + uint32_t height() const override { return Framebuffer::height(); } - PixelFormat format() const { return m_format; } - unsigned num_planes() const { return m_num_planes; } + PixelFormat format() const override { return m_format; } + unsigned num_planes() const override { 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); + uint32_t handle(unsigned plane) const { return m_planes.at(plane).handle; } + uint32_t stride(unsigned plane) const override { return m_planes.at(plane).stride; } + uint32_t size(unsigned plane) const override { return m_planes.at(plane).size; } + uint32_t offset(unsigned plane) const override { return m_planes.at(plane).offset; } + uint8_t* map(unsigned plane) override; + int prime_fd(unsigned plane) override; private: struct FramebufferPlane { @@ -36,11 +36,8 @@ private: uint8_t *map; }; - void Create(); - void Destroy(); - unsigned m_num_planes; - struct FramebufferPlane m_planes[4]; + std::array<FramebufferPlane, 4> m_planes; PixelFormat m_format; }; diff --git a/kms++/inc/kms++/encoder.h b/kms++/inc/kms++/encoder.h index 1d36adc..72c0213 100644 --- a/kms++/inc/kms++/encoder.h +++ b/kms++/inc/kms++/encoder.h @@ -20,7 +20,7 @@ public: const std::string& get_encoder_type() const; private: Encoder(Card& card, uint32_t id, uint32_t idx); - ~Encoder(); + ~Encoder() override; EncoderPriv* m_priv; }; diff --git a/kms++/inc/kms++/extframebuffer.h b/kms++/inc/kms++/extframebuffer.h index 5f0660c..f906fb2 100644 --- a/kms++/inc/kms++/extframebuffer.h +++ b/kms++/inc/kms++/extframebuffer.h @@ -2,6 +2,7 @@ #include "framebuffer.h" #include "pixelformats.h" +#include <vector> namespace kms { @@ -10,36 +11,32 @@ class ExtFramebuffer : public Framebuffer { public: ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, - std::vector<uint32_t> handles, std::vector<uint32_t> pitches, std::vector<uint32_t> offsets); - ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, - std::vector<int> fds, std::vector<uint32_t> pitches, std::vector<uint32_t> offsets); - virtual ~ExtFramebuffer(); + std::vector<uint32_t> handles, std::vector<uint32_t> pitches, std::vector<uint32_t> offsets, std::vector<uint64_t> modifiers = {}); + ~ExtFramebuffer() override; - uint32_t width() const { return Framebuffer::width(); } - uint32_t height() const { return Framebuffer::height(); } + uint32_t width() const override { return Framebuffer::width(); } + uint32_t height() const override { return Framebuffer::height(); } - PixelFormat format() const { return m_format; } - unsigned num_planes() const { return m_num_planes; } + PixelFormat format() const override { return m_format; } + unsigned num_planes() const override { 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); + uint32_t handle(unsigned plane) const { return m_planes.at(plane).handle; } + uint32_t stride(unsigned plane) const override { return m_planes.at(plane).stride; } + uint32_t size(unsigned plane) const override { return m_planes.at(plane).size; } + uint32_t offset(unsigned plane) const override { return m_planes.at(plane).offset; } private: struct FramebufferPlane { uint32_t handle; - int prime_fd; uint32_t size; uint32_t stride; uint32_t offset; + uint64_t modifier; uint8_t *map; }; unsigned m_num_planes; - struct FramebufferPlane m_planes[4]; + std::array<FramebufferPlane, 4> m_planes; PixelFormat m_format; }; diff --git a/kms++/inc/kms++/framebuffer.h b/kms++/inc/kms++/framebuffer.h index 3d43d08..bcfd1f0 100644 --- a/kms++/inc/kms++/framebuffer.h +++ b/kms++/inc/kms++/framebuffer.h @@ -5,6 +5,13 @@ namespace kms { +enum class CpuAccess +{ + Read, + Write, + ReadWrite, +}; + class IFramebuffer { public: virtual ~IFramebuffer() { } @@ -20,16 +27,19 @@ public: virtual uint32_t offset(unsigned plane) const { throw std::runtime_error("not implemented"); } virtual uint8_t* map(unsigned plane) { throw std::runtime_error("not implemented"); } virtual int prime_fd(unsigned plane) { throw std::runtime_error("not implemented"); } + + virtual void begin_cpu_access(CpuAccess access) { } + virtual void end_cpu_access() { } }; class Framebuffer : public DrmObject, public IFramebuffer { public: Framebuffer(Card& card, uint32_t id); - virtual ~Framebuffer(); + ~Framebuffer() override; - uint32_t width() const { return m_width; } - uint32_t height() const { return m_height; } + uint32_t width() const override { return m_width; } + uint32_t height() const override { return m_height; } void flush(); protected: diff --git a/kms++/inc/kms++/kms++.h b/kms++/inc/kms++/kms++.h index 3365ef7..a97505a 100644 --- a/kms++/inc/kms++/kms++.h +++ b/kms++/inc/kms++/kms++.h @@ -8,6 +8,7 @@ #include "framebuffer.h" #include "dumbframebuffer.h" #include "extframebuffer.h" +#include "dmabufframebuffer.h" #include "plane.h" #include "property.h" #include "blob.h" diff --git a/kms++/inc/kms++/pixelformats.h b/kms++/inc/kms++/pixelformats.h index 15fee7f..784717d 100644 --- a/kms++/inc/kms++/pixelformats.h +++ b/kms++/inc/kms++/pixelformats.h @@ -59,10 +59,10 @@ static inline PixelFormat FourCCToPixelFormat(const std::string& fourcc) 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), + char buf[5] = { (char)(((uint32_t)f >> 0) & 0xff), + (char)(((uint32_t)f >> 8) & 0xff), + (char)(((uint32_t)f >> 16) & 0xff), + (char)(((uint32_t)f >> 24) & 0xff), 0 }; return std::string(buf); } diff --git a/kms++/inc/kms++/plane.h b/kms++/inc/kms++/plane.h index 27e819b..1d78537 100644 --- a/kms++/inc/kms++/plane.h +++ b/kms++/inc/kms++/plane.h @@ -35,7 +35,7 @@ public: uint32_t gamma_size() const; private: Plane(Card& card, uint32_t id, uint32_t idx); - ~Plane(); + ~Plane() override; PlanePriv* m_priv; }; diff --git a/kms++/inc/kms++/property.h b/kms++/inc/kms++/property.h index b9097ff..8d6088e 100644 --- a/kms++/inc/kms++/property.h +++ b/kms++/inc/kms++/property.h @@ -34,7 +34,7 @@ public: std::vector<uint32_t> get_blob_ids() const; private: Property(Card& card, uint32_t id); - ~Property(); + ~Property() override; PropertyType m_type; diff --git a/kms++/inc/kms++/videomode.h b/kms++/inc/kms++/videomode.h index d7f5258..74aa8f1 100644 --- a/kms++/inc/kms++/videomode.h +++ b/kms++/inc/kms++/videomode.h @@ -49,7 +49,9 @@ struct Videomode void set_hsync(SyncPolarity pol); void set_vsync(SyncPolarity pol); - std::string to_string() const; + std::string to_string_short() const; + std::string to_string_long() const; + std::string to_string_long_padded() const; }; struct Videomode videomode_from_timings(uint32_t clock_khz, diff --git a/kms++/kms++.pc.in b/kms++/kms++.pc.in new file mode 100644 index 0000000..60b5974 --- /dev/null +++ b/kms++/kms++.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_PREFIX@/lib +includedir=@CMAKE_INSTALL_PREFIX@/include + +Name: kms++ +Description: C++ library for Linux kernel mode setting +Version: 0.0.0 +Libs: -L${libdir} -lkms++ +Cflags: -I${includedir} diff --git a/kms++/src/card.cpp b/kms++/src/card.cpp index 8de8b82..5b3d69e 100644 --- a/kms++/src/card.cpp +++ b/kms++/src/card.cpp @@ -1,9 +1,9 @@ -#include <stdio.h> +#include <cstdio> #include <unistd.h> #include <fcntl.h> #include <utility> #include <stdexcept> -#include <string.h> +#include <cstring> #include <algorithm> #include <cerrno> #include <algorithm> @@ -151,12 +151,12 @@ Card::Card(const std::string& driver, uint32_t idx) void Card::setup() { drmVersionPtr ver = drmGetVersion(m_fd); - m_version_major = ver->version_major; - m_version_minor = ver->version_minor; - m_version_patchlevel = ver->version_patchlevel; - m_version_name = string(ver->name, ver->name_len); - m_version_date = string(ver->date, ver->date_len); - m_version_desc = string(ver->desc, ver->desc_len); + m_version.major = ver->version_major; + m_version.minor = ver->version_minor; + m_version.patchlevel = ver->version_patchlevel; + m_version.name = string(ver->name, ver->name_len); + m_version.date = string(ver->date, ver->date_len); + m_version.desc = string(ver->desc, ver->desc_len); drmFreeVersion(ver); int r; @@ -296,7 +296,7 @@ DrmObject* Card::get_object(uint32_t id) const return nullptr; } -const vector<DrmObject*> Card::get_objects() const +std::vector<kms::DrmObject*> Card::get_objects() const { vector<DrmObject*> v; for(auto pair : m_obmap) diff --git a/kms++/src/connector.cpp b/kms++/src/connector.cpp index a1807da..72f8777 100644 --- a/kms++/src/connector.cpp +++ b/kms++/src/connector.cpp @@ -1,4 +1,4 @@ -#include <stdio.h> +#include <cstdio> #include <iostream> #include <unistd.h> #include <fcntl.h> diff --git a/kms++/src/crtc.cpp b/kms++/src/crtc.cpp index f94216f..7ffaaff 100644 --- a/kms++/src/crtc.cpp +++ b/kms++/src/crtc.cpp @@ -1,4 +1,4 @@ -#include <stdio.h> +#include <cstdio> #include <iostream> #include <unistd.h> #include <fcntl.h> diff --git a/kms++/src/dmabufframebuffer.cpp b/kms++/src/dmabufframebuffer.cpp new file mode 100644 index 0000000..1e8c914 --- /dev/null +++ b/kms++/src/dmabufframebuffer.cpp @@ -0,0 +1,145 @@ + +#include <cstring> +#include <cerrno> + +#include <stdexcept> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <xf86drm.h> +#include <xf86drmMode.h> +#include <linux/dma-buf.h> + +#include <kms++/kms++.h> + +using namespace std; + +namespace kms +{ + +DmabufFramebuffer::DmabufFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, + vector<int> fds, vector<uint32_t> pitches, vector<uint32_t> offsets, vector<uint64_t> modifiers) + : Framebuffer(card, width, height) +{ + int r; + + m_format = format; + + const PixelFormatInfo& format_info = get_pixel_format_info(format); + + m_num_planes = format_info.num_planes; + + if (fds.size() != m_num_planes || pitches.size() != m_num_planes || offsets.size() != m_num_planes) + throw std::invalid_argument("the size of fds, pitches and offsets has to match number of planes"); + + for (int i = 0; i < format_info.num_planes; ++i) { + FramebufferPlane& plane = m_planes.at(i); + + plane.prime_fd = fds[i]; + + r = drmPrimeFDToHandle(card.fd(), fds[i], &plane.handle); + if (r) + throw invalid_argument(string("drmPrimeFDToHandle: ") + strerror(errno)); + + plane.stride = pitches[i]; + plane.offset = offsets[i]; + plane.modifier = modifiers.empty() ? 0 : modifiers[i]; + plane.size = plane.stride * height; + plane.map = 0; + } + + uint32_t id; + uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle, m_planes[2].handle, m_planes[3].handle }; + pitches.resize(4); + offsets.resize(4); + + if (modifiers.empty()) { + r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, + bo_handles, pitches.data(), offsets.data(), &id, 0); + if (r) + throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); + } + else { + modifiers.resize(4); + r = drmModeAddFB2WithModifiers(card.fd(), width, height, (uint32_t)format, + bo_handles, pitches.data(), offsets.data(), modifiers.data(), &id, DRM_MODE_FB_MODIFIERS); + if (r) + throw invalid_argument(string("drmModeAddFB2WithModifiers failed: ") + strerror(errno)); + } + + set_id(id); +} + +DmabufFramebuffer::~DmabufFramebuffer() +{ + drmModeRmFB(card().fd(), id()); +} + +uint8_t* DmabufFramebuffer::map(unsigned plane) +{ + FramebufferPlane& p = m_planes.at(plane); + + if (p.map) + return p.map; + + p.map = (uint8_t *)mmap(0, p.size, PROT_READ | PROT_WRITE, MAP_SHARED, + p.prime_fd, 0); + if (p.map == MAP_FAILED) + throw invalid_argument(string("mmap failed: ") + strerror(errno)); + + return p.map; +} + +int DmabufFramebuffer::prime_fd(unsigned plane) +{ + FramebufferPlane& p = m_planes.at(plane); + + return p.prime_fd; +} + +void DmabufFramebuffer::begin_cpu_access(CpuAccess access) +{ + if (m_sync_flags != 0) + throw runtime_error("begin_cpu sync already started"); + + switch (access) { + case CpuAccess::Read: + m_sync_flags = DMA_BUF_SYNC_READ; + break; + case CpuAccess::Write: + m_sync_flags = DMA_BUF_SYNC_WRITE; + break; + case CpuAccess::ReadWrite: + m_sync_flags = DMA_BUF_SYNC_RW; + break; + } + + dma_buf_sync dbs { + .flags = DMA_BUF_SYNC_START | m_sync_flags + }; + + for (uint32_t p = 0; p < m_num_planes; ++p) { + int r = ioctl(prime_fd(p), DMA_BUF_IOCTL_SYNC, &dbs); + if (r) + throw runtime_error("DMA_BUF_IOCTL_SYNC failed"); + } +} + +void DmabufFramebuffer::end_cpu_access() +{ + if (m_sync_flags == 0) + throw runtime_error("begin_cpu sync not started"); + + dma_buf_sync dbs { + .flags = DMA_BUF_SYNC_END | m_sync_flags + }; + + for (uint32_t p = 0; p < m_num_planes; ++p) { + int r = ioctl(prime_fd(p), DMA_BUF_IOCTL_SYNC, &dbs); + if (r) + throw runtime_error("DMA_BUF_IOCTL_SYNC failed"); + } + + m_sync_flags = 0; +} + +} diff --git a/kms++/src/drmobject.cpp b/kms++/src/drmobject.cpp index f94fc5d..9c0f5ae 100644 --- a/kms++/src/drmobject.cpp +++ b/kms++/src/drmobject.cpp @@ -1,4 +1,4 @@ -#include <string.h> +#include <cstring> #include <iostream> #include <stdexcept> diff --git a/kms++/src/drmpropobject.cpp b/kms++/src/drmpropobject.cpp index f91f913..74f8848 100644 --- a/kms++/src/drmpropobject.cpp +++ b/kms++/src/drmpropobject.cpp @@ -1,4 +1,4 @@ -#include <string.h> +#include <cstring> #include <iostream> #include <stdexcept> diff --git a/kms++/src/dumbframebuffer.cpp b/kms++/src/dumbframebuffer.cpp index 4419687..3448fb1 100644 --- a/kms++/src/dumbframebuffer.cpp +++ b/kms++/src/dumbframebuffer.cpp @@ -28,16 +28,6 @@ DumbFramebuffer::DumbFramebuffer(Card &card, uint32_t width, uint32_t height, co 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); @@ -46,14 +36,14 @@ void DumbFramebuffer::Create() for (int i = 0; i < format_info.num_planes; ++i) { const PixelFormatPlaneInfo& pi = format_info.planes[i]; - FramebufferPlane& plane = m_planes[i]; + FramebufferPlane& plane = m_planes.at(i); /* create dumb buffer */ struct drm_mode_create_dumb creq = drm_mode_create_dumb(); - creq.width = width(); - creq.height = height() / pi.ysub; + creq.width = width; + creq.height = height / pi.ysub; creq.bpp = pi.bitspp; - r = drmIoctl(card().fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq); + r = drmIoctl(card.fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq); if (r) throw invalid_argument(string("DRM_IOCTL_MODE_CREATE_DUMB failed: ") + strerror(errno)); @@ -70,7 +60,7 @@ void DumbFramebuffer::Create() 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(), + 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)); @@ -78,13 +68,13 @@ void DumbFramebuffer::Create() set_id(id); } -void DumbFramebuffer::Destroy() +DumbFramebuffer::~DumbFramebuffer() { /* delete framebuffer */ drmModeRmFB(card().fd(), id()); for (uint i = 0; i < m_num_planes; ++i) { - FramebufferPlane& plane = m_planes[i]; + FramebufferPlane& plane = m_planes.at(i); /* unmap buffer */ if (plane.map) @@ -101,7 +91,7 @@ void DumbFramebuffer::Destroy() uint8_t* DumbFramebuffer::map(unsigned plane) { - FramebufferPlane& p = m_planes[plane]; + FramebufferPlane& p = m_planes.at(plane); if (p.map) return p.map; @@ -124,15 +114,15 @@ uint8_t* DumbFramebuffer::map(unsigned plane) int DumbFramebuffer::prime_fd(unsigned int plane) { - if (m_planes[plane].prime_fd >= 0) - return m_planes[plane].prime_fd; + if (m_planes.at(plane).prime_fd >= 0) + return m_planes.at(plane).prime_fd; - int r = drmPrimeHandleToFD(card().fd(), m_planes[plane].handle, - DRM_CLOEXEC | O_RDWR, &m_planes[plane].prime_fd); + int r = drmPrimeHandleToFD(card().fd(), m_planes.at(plane).handle, + DRM_CLOEXEC | O_RDWR, &m_planes.at(plane).prime_fd); if (r) throw std::runtime_error("drmPrimeHandleToFD failed"); - return m_planes[plane].prime_fd; + return m_planes.at(plane).prime_fd; } } diff --git a/kms++/src/encoder.cpp b/kms++/src/encoder.cpp index bfb2ea8..30a241a 100644 --- a/kms++/src/encoder.cpp +++ b/kms++/src/encoder.cpp @@ -1,4 +1,4 @@ -#include <stdio.h> +#include <cstdio> #include <iostream> #include <unistd.h> #include <fcntl.h> diff --git a/kms++/src/extframebuffer.cpp b/kms++/src/extframebuffer.cpp index 12e59b7..4ea563c 100644 --- a/kms++/src/extframebuffer.cpp +++ b/kms++/src/extframebuffer.cpp @@ -15,7 +15,7 @@ namespace kms { ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, - vector<uint32_t> handles, vector<uint32_t> pitches, vector<uint32_t> offsets) + vector<uint32_t> handles, vector<uint32_t> pitches, vector<uint32_t> offsets, vector<uint64_t> modifiers) : Framebuffer(card, width, height) { m_format = format; @@ -24,59 +24,36 @@ ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, Pixe m_num_planes = format_info.num_planes; + if (handles.size() != m_num_planes || pitches.size() != m_num_planes || offsets.size() != m_num_planes) + throw std::invalid_argument("the size of handles, pitches and offsets has to match number of planes"); + for (int i = 0; i < format_info.num_planes; ++i) { - FramebufferPlane& plane = m_planes[i]; + FramebufferPlane& plane = m_planes.at(i); plane.handle = handles[i]; - plane.prime_fd = 0; - plane.stride = pitches[i]; plane.offset = offsets[i]; + plane.modifier = modifiers.empty() ? 0 : modifiers[i]; plane.size = plane.stride * height; plane.map = 0; } uint32_t id; - int r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, handles.data(), pitches.data(), offsets.data(), &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, - vector<int> fds, vector<uint32_t> pitches, vector<uint32_t> offsets) - : Framebuffer(card, width, height) -{ + handles.resize(4); + pitches.resize(4); + offsets.resize(4); int r; - m_format = format; - - const PixelFormatInfo& format_info = get_pixel_format_info(format); - - m_num_planes = format_info.num_planes; - - for (int i = 0; i < format_info.num_planes; ++i) { - FramebufferPlane& plane = m_planes[i]; - - plane.prime_fd = fds[i]; - - r = drmPrimeFDToHandle(card.fd(), fds[i], &plane.handle); - if (r) - throw invalid_argument(string("drmPrimeFDToHandle: ") + strerror(errno)); - - plane.stride = pitches[i]; - plane.offset = offsets[i]; - plane.size = plane.stride * height; - plane.map = 0; + if (modifiers.empty()) { + r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, handles.data(), pitches.data(), offsets.data(), &id, 0); + } + else { + modifiers.resize(4); + r = drmModeAddFB2WithModifiers(card.fd(), width, height, (uint32_t)format, handles.data(), pitches.data(), offsets.data(), modifiers.data(), &id, DRM_MODE_FB_MODIFIERS); } - uint32_t id; - uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle }; - r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, - bo_handles, pitches.data(), offsets.data(), &id, 0); if (r) - throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); + throw std::invalid_argument(string("Failed to create ExtFramebuffer: ") + strerror(r)); set_id(id); } @@ -86,32 +63,4 @@ ExtFramebuffer::~ExtFramebuffer() drmModeRmFB(card().fd(), id()); } -uint8_t* ExtFramebuffer::map(unsigned plane) -{ - FramebufferPlane& p = m_planes[plane]; - - if (!p.prime_fd) - throw invalid_argument("cannot mmap non-dmabuf fb"); - - if (p.map) - return p.map; - - p.map = (uint8_t *)mmap(0, p.size, PROT_READ | PROT_WRITE, MAP_SHARED, - p.prime_fd, 0); - if (p.map == MAP_FAILED) - throw invalid_argument(string("mmap failed: ") + strerror(errno)); - - return p.map; -} - -int ExtFramebuffer::prime_fd(unsigned plane) -{ - FramebufferPlane& p = m_planes[plane]; - - if (!p.prime_fd) - throw invalid_argument("no primefb for non-dmabuf fb"); - - return p.prime_fd; -} - } diff --git a/kms++/src/plane.cpp b/kms++/src/plane.cpp index f68c8d0..b040884 100644 --- a/kms++/src/plane.cpp +++ b/kms++/src/plane.cpp @@ -1,4 +1,4 @@ -#include <stdio.h> +#include <cstdio> #include <iostream> #include <unistd.h> #include <fcntl.h> diff --git a/kms++/src/videomode.cpp b/kms++/src/videomode.cpp index b8bd797..b53f0c0 100644 --- a/kms++/src/videomode.cpp +++ b/kms++/src/videomode.cpp @@ -1,7 +1,8 @@ #include <xf86drm.h> #include <xf86drmMode.h> -#include <math.h> +#include <cmath> #include <sstream> +#include <fmt/format.h> #include <kms++/kms++.h> #include "helpers.h" @@ -88,14 +89,53 @@ void Videomode::set_vsync(SyncPolarity pol) } } -string Videomode::to_string() const +string Videomode::to_string_short() const { - std::stringstream ss; - ss << hdisplay << "x" << vdisplay; - if (interlace()) - ss << "i"; - ss << "@" << calculated_vrefresh(); - return ss.str(); + return fmt::format("{}x{}{}@{:.2f}", hdisplay, vdisplay, interlace() ? "i" : "", calculated_vrefresh()); +} + +static char sync_to_char(SyncPolarity pol) +{ + switch (pol) { + case SyncPolarity::Positive: + return '+'; + case SyncPolarity::Negative: + return '-'; + default: + return '?'; + } +} + +string Videomode::to_string_long() const +{ + string h = fmt::format("{}/{}/{}/{}/{}", hdisplay, hfp(), hsw(), hbp(), sync_to_char(hsync())); + string v = fmt::format("{}/{}/{}/{}/{}", vdisplay, vfp(), vsw(), vbp(), sync_to_char(vsync())); + + string str = fmt::format("{} {:.3f} {} {} {} ({:.2f}) {:#x} {:#x}", + to_string_short(), + clock / 1000.0, + h, v, + vrefresh, calculated_vrefresh(), + flags, + type); + + return str; +} + +string Videomode::to_string_long_padded() const +{ + string h = fmt::format("{}/{}/{}/{}/{}", hdisplay, hfp(), hsw(), hbp(), sync_to_char(hsync())); + string v = fmt::format("{}/{}/{}/{}/{}", vdisplay, vfp(), vsw(), vbp(), sync_to_char(vsync())); + + string str = fmt::format("{:<16} {:7.3f} {:<18} {:<18} {:2} ({:.2f}) {:#10x} {:#6x}", + to_string_short(), + clock / 1000.0, + h, v, + vrefresh, calculated_vrefresh(), + flags, + type); + + return str; } Videomode videomode_from_timings(uint32_t clock_khz, diff --git a/kms++util/CMakeLists.txt b/kms++util/CMakeLists.txt index 70f3b17..0bfb56b 100644 --- a/kms++util/CMakeLists.txt +++ b/kms++util/CMakeLists.txt @@ -14,10 +14,18 @@ if (KMSXX_ENABLE_THREADING) add_definitions(-DHAS_PTHREAD) endif() +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/kms++util.pc.in ${CMAKE_CURRENT_BINARY_DIR}/kms++util.pc @ONLY) + +# Set a dummy SOVERSION just to avoid havig a naked .so file in the filesystem. +# This version number doesn't make any promise about API/ABI stability. set_target_properties(kms++util PROPERTIES - PUBLIC_HEADER "${PUB_HDRS}") + PUBLIC_HEADER "${PUB_HDRS}" + SOVERSION 0) install(TARGETS kms++util LIBRARY DESTINATION lib ARCHIVE DESTINATION lib PUBLIC_HEADER DESTINATION include/kms++util) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kms++util.pc + DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig) diff --git a/kms++util/inc/kms++util/strhelpers.h b/kms++util/inc/kms++util/strhelpers.h index 2c540f3..2d35e93 100644 --- a/kms++util/inc/kms++util/strhelpers.h +++ b/kms++util/inc/kms++util/strhelpers.h @@ -28,6 +28,3 @@ std::string join(const std::vector<T>& values, const std::string& delim, std::fu } return ss.str(); } - -std::string sformat(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); diff --git a/kms++util/kms++util.pc.in b/kms++util/kms++util.pc.in new file mode 100644 index 0000000..b90df89 --- /dev/null +++ b/kms++util/kms++util.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_PREFIX@/lib +includedir=@CMAKE_INSTALL_PREFIX@/include + +Name: kms++ +Description: C++ library for Linux kernel mode setting +Version: 0.0.0 +Requires: kms++ +Libs: -L${libdir} -lkms++util +Cflags: -I${includedir} diff --git a/kms++util/src/cpuframebuffer.cpp b/kms++util/src/cpuframebuffer.cpp index d356596..33f8f97 100644 --- a/kms++util/src/cpuframebuffer.cpp +++ b/kms++util/src/cpuframebuffer.cpp @@ -29,7 +29,7 @@ CPUFramebuffer::~CPUFramebuffer() for (unsigned i = 0; i < m_num_planes; ++i) { FramebufferPlane& plane = m_planes[i]; - delete plane.map; + delete [] plane.map; } } diff --git a/kms++util/src/strhelpers.cpp b/kms++util/src/strhelpers.cpp index f59bb6d..5eba2a9 100644 --- a/kms++util/src/strhelpers.cpp +++ b/kms++util/src/strhelpers.cpp @@ -11,17 +11,3 @@ string to_lower(const string& str) transform(data.begin(), data.end(), data.begin(), ::tolower); return data; } - -string sformat(const char *fmt, ...) -{ - static char s_format_buf[1024]; - - va_list args; - va_start(args, fmt); - - vsnprintf(s_format_buf, sizeof(s_format_buf), fmt, args); - - va_end(args); - - return string(s_format_buf); -} diff --git a/kms++util/src/videodevice.cpp b/kms++util/src/videodevice.cpp index cc11357..23f45d4 100644 --- a/kms++util/src/videodevice.cpp +++ b/kms++util/src/videodevice.cpp @@ -15,6 +15,18 @@ using namespace std; using namespace kms; +/* + * V4L2 and DRM differ in their interpretation of YUV420::NV12 + * + * V4L2 NV12 is a Y and UV co-located planes in a single plane buffer. + * DRM NV12 is a Y and UV planes presented as dual plane buffer, + * which is known as NM12 in V4L2. + * + * Since here we have hybrid DRM/V4L2 user space helper functions + * we need to translate DRM::NV12 to V4L2:NM12 pixel format back + * and forth to keep the data view consistent. + */ + /* V4L2 helper funcs */ static vector<PixelFormat> v4l2_get_formats(int fd, uint32_t buf_type) { @@ -24,7 +36,11 @@ static vector<PixelFormat> v4l2_get_formats(int fd, uint32_t buf_type) desc.type = buf_type; while (ioctl(fd, VIDIOC_ENUM_FMT, &desc) == 0) { - v.push_back((PixelFormat)desc.pixelformat); + if (desc.pixelformat == V4L2_PIX_FMT_NV12M) + v.push_back(PixelFormat::NV12); + else if (desc.pixelformat != V4L2_PIX_FMT_NV12) + v.push_back((PixelFormat)desc.pixelformat); + desc.index++; } @@ -47,8 +63,14 @@ static void v4l2_set_format(int fd, PixelFormat fmt, uint32_t width, uint32_t he if (mplane) { v4l2_pix_format_mplane& mp = v4lfmt.fmt.pix_mp; + uint32_t used_fmt; + + if (fmt == PixelFormat::NV12) + used_fmt = V4L2_PIX_FMT_NV12M; + else + used_fmt = (uint32_t)fmt; - mp.pixelformat = (uint32_t)fmt; + mp.pixelformat = used_fmt; mp.width = width; mp.height = height; @@ -65,7 +87,7 @@ static void v4l2_set_format(int fd, PixelFormat fmt, uint32_t width, uint32_t he r = ioctl(fd, VIDIOC_S_FMT, &v4lfmt); ASSERT(r == 0); - ASSERT(mp.pixelformat == (uint32_t)fmt); + ASSERT(mp.pixelformat == used_fmt); ASSERT(mp.width == width); ASSERT(mp.height == height); diff --git a/py/pykms/pykmsbase.cpp b/py/pykms/pykmsbase.cpp index 668e6e3..c039833 100644 --- a/py/pykms/pykmsbase.cpp +++ b/py/pykms/pykmsbase.cpp @@ -122,14 +122,14 @@ void init_pykmsbase(py::module &m) ; py::class_<Blob>(m, "Blob") - .def("__init__", [](Blob& instance, Card& card, py::buffer buf) { - py::buffer_info info = buf.request(); - if (info.ndim != 1) - throw std::runtime_error("Incompatible buffer dimension!"); + .def(py::init([](Card& card, py::buffer buf) { + py::buffer_info info = buf.request(); + if (info.ndim != 1) + throw std::runtime_error("Incompatible buffer dimension!"); - new (&instance) Blob(card, info.ptr, info.size * info.itemsize); - }, - py::keep_alive<1, 3>()) // Keep Card alive until this is destructed + return new Blob(card, info.ptr, info.size * info.itemsize); + }), + py::keep_alive<1, 2>()) // Keep Card alive until this is destructed .def_property_readonly("data", &Blob::data) @@ -167,7 +167,7 @@ void init_pykmsbase(py::module &m) .def("offset", &DumbFramebuffer::offset) ; - py::class_<ExtFramebuffer, Framebuffer>(m, "ExtFramebuffer") + py::class_<DmabufFramebuffer, Framebuffer>(m, "DmabufFramebuffer") .def(py::init<Card&, uint32_t, uint32_t, PixelFormat, vector<int>, vector<uint32_t>, vector<uint32_t>>(), py::keep_alive<1, 2>()) // Keep Card alive until this is destructed ; @@ -229,6 +229,9 @@ void init_pykmsbase(py::module &m) .def_property("hsync", &Videomode::hsync, &Videomode::set_hsync) .def_property("vsync", &Videomode::vsync, &Videomode::set_vsync) + + .def("to_string_short", &Videomode::to_string_short) + .def("to_string_long", &Videomode::to_string_long) ; diff --git a/py/tests/alpha-test.py b/py/tests/alpha-test.py index e329ce4..94d3836 100755 --- a/py/tests/alpha-test.py +++ b/py/tests/alpha-test.py @@ -2,24 +2,38 @@ import pykms import time +import argparse + +parser = argparse.ArgumentParser(description='Simple alpha blending test.') +parser.add_argument('--resetcrtc', action="store_true", + help='Reset legacy CRTC color properties') +parser.add_argument('--connector', '-c', dest='connector', default="", + required=False, help='connector to output') +parser.add_argument('--mode', '-m', dest='modename', + required=False, help='Video mode name to use') +args = parser.parse_args() + +max_planes = 4 card = pykms.Card() res = pykms.ResourceManager(card) -conn = res.reserve_connector() +conn = res.reserve_connector(args.connector) crtc = res.reserve_crtc(conn) -mode = conn.get_default_mode() +if args.modename == None: + mode = conn.get_default_mode() +else: + mode = conn.get_mode(args.modename) planes = [] -for i in range(3): +for i in range(max_planes): p = res.reserve_generic_plane(crtc) - if p == None: - print("Need 3 planes!") - exit(1) - + break planes.append(p) +print("Got {} planes. Test supports up to 4 planes.".format(len(planes))) + card.disable_planes() w = mode.hdisplay @@ -27,25 +41,29 @@ h = mode.vdisplay fbs=[] -for i in range(len(planes)): +for i in range(max_planes): fbs.append(pykms.DumbFramebuffer(card, w, h, "AR24")) pykms.draw_rect(fbs[0], 50, 50, 200, 200, pykms.RGB(128, 255, 0, 0)) pykms.draw_rect(fbs[1], 150, 50, 200, 200, pykms.RGB(128, 0, 255, 0)) pykms.draw_rect(fbs[2], 50, 150, 200, 200, pykms.RGB(128, 0, 0, 255)) +pykms.draw_rect(fbs[3], 150, 150, 200, 200, pykms.RGB(128, 128, 128, 128)) + +card.disable_planes() -crtc.set_props({ - "trans-key-mode": 0, - "trans-key": 0, - "background": 0, - "alpha_blender": 1, -}) +if args.resetcrtc: + crtc.set_props({ + "trans-key-mode": 0, + "trans-key": 0, + "background": 0, + "alpha_blender": 1, + }) for i in range(len(planes)): plane = planes[i] fb = fbs[i] - print("set crtc {}, plane {}, fb {}".format(crtc.id, p.id, fbs[i].id)) + print("set crtc {}, plane {}, z {}, fb {}".format(crtc.id, plane.id, i, fb.id)) plane.set_props({ "FB_ID": fb.id, diff --git a/py/tests/ctm_test.py b/py/tests/ctm_test.py index 7ceed6f..2273221 100755 --- a/py/tests/ctm_test.py +++ b/py/tests/ctm_test.py @@ -2,6 +2,7 @@ import sys import pykms +import argparse def ctm_to_blob(ctm, card): len=9 @@ -22,33 +23,38 @@ def ctm_to_blob(ctm, card): return pykms.Blob(card, arr); -if len(sys.argv) > 1: - conn_name = sys.argv[1] -else: - conn_name = "" +parser = argparse.ArgumentParser(description='Simple CRTC CTM-property test.') +parser.add_argument('--connector', '-c', dest='connector', + required=False, help='connector to output') +parser.add_argument('--mode', '-m', dest='modename', + required=False, help='Video mode name to use') +parser.add_argument('--plane', '-p', dest='plane', type=int, + required=False, help='plane number to use') +args = parser.parse_args() card = pykms.Card() res = pykms.ResourceManager(card) -conn = res.reserve_connector(conn_name) +conn = res.reserve_connector(args.connector) crtc = res.reserve_crtc(conn) -mode = conn.get_default_mode() +format = pykms.PixelFormat.ARGB8888 +if args.modename == None: + mode = conn.get_default_mode() +else: + mode = conn.get_mode(args.modename) +modeb = mode.to_blob(card) fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); pykms.draw_test_pattern(fb); -crtc.set_mode(conn, fb, mode) - -input("press enter to set normal ctm\n") - -ctm = [ 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0 ] - -ctmb = ctm_to_blob(ctm, card) +if args.plane == None: + plane = res.reserve_generic_plane(crtc, fb.format) +else: + plane = card.planes[args.plane] -crtc.set_prop("CTM", ctmb.id) +card.disable_planes() +crtc.disable_mode() -input("press enter to set new ctm\n") +input("press enter to set ctm at the same time with crtc mode\n") ctm = [ 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, @@ -56,10 +62,27 @@ ctm = [ 0.0, 1.0, 0.0, ctmb = ctm_to_blob(ctm, card) -crtc.set_prop("CTM", ctmb.id) +req = pykms.AtomicReq(card) +req.add(conn, "CRTC_ID", crtc.id) +req.add(crtc, {"ACTIVE": 1, + "MODE_ID": modeb.id, + "CTM": ctmb.id}) +req.add_plane(plane, fb, crtc) +r = req.commit_sync(allow_modeset = True) +assert r == 0, "Initial commit failed: %d" % r print("r->b g->r b->g ctm active\n") +input("press enter to set normal ctm\n") + +ctm = [ 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 ] + +ctmb = ctm_to_blob(ctm, card) + +crtc.set_prop("CTM", ctmb.id) + input("press enter to set new ctm\n") ctm = [ 0.0, 0.0, 1.0, diff --git a/py/tests/global_alpha_test.py b/py/tests/global_alpha_test.py index 6981b72..33fd12e 100755 --- a/py/tests/global_alpha_test.py +++ b/py/tests/global_alpha_test.py @@ -2,12 +2,22 @@ import pykms import time - +import argparse + +parser = argparse.ArgumentParser(description='Plane "alpha"-property test.') +parser.add_argument('--connector', '-c', dest='connector', default="", + required=False, help='connector to output') +parser.add_argument('--mode', '-m', dest='modename', + required=False, help='Video mode name to use') +args = parser.parse_args() card = pykms.Card() res = pykms.ResourceManager(card) -conn = res.reserve_connector("") +conn = res.reserve_connector(args.connector) crtc = res.reserve_crtc(conn) -mode = conn.get_default_mode() +if args.modename == None: + mode = conn.get_default_mode() +else: + mode = conn.get_mode(args.modename) modeb = mode.to_blob(card) format = pykms.PixelFormat.ARGB8888 plane1 = res.reserve_generic_plane(crtc, format) @@ -24,6 +34,8 @@ pykms.draw_test_pattern(fb2); alpha = 0 +card.disable_planes() + req = pykms.AtomicReq(card) req.add(conn, "CRTC_ID", crtc.id) req.add(crtc, {"ACTIVE": 1, @@ -34,13 +46,16 @@ req.add_plane(plane2, fb2, crtc) r = req.commit_sync(allow_modeset = True) assert r == 0, "Initial commit failed: %d" % r +input("press enter start\n") + while alpha <= 0xFFFF: print("alpha %d" % (alpha >> 8)) req = pykms.AtomicReq(card) req.add(plane2, {"alpha": alpha }) r = req.commit_sync() assert r == 0, "alpha change commit failed: %d" % r - alpha = alpha + 0xFF - time.sleep(0.1) + alpha = alpha + 0x101 + time.sleep(0.03) input("press enter exit\n") +card.disable_planes() diff --git a/py/tests/hpd.py b/py/tests/hpd.py index d26f260..185d784 100755 --- a/py/tests/hpd.py +++ b/py/tests/hpd.py @@ -4,8 +4,7 @@ import pyudev import pykms card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector("hdmi") +conns = card.connectors context = pyudev.Context() @@ -16,7 +15,8 @@ monitor.filter_by('drm') for device in iter(monitor.poll, None): if 'HOTPLUG' in device: - conn.refresh() - mode = conn.get_modes() print("HPD") - print(mode) + for conn in conns: + conn.refresh() + modes = conn.get_modes() + print(" ", conn.fullname, ["{}x{}".format(m.hdisplay, m.vdisplay) for m in modes]) diff --git a/py/tests/kmsmodeview.py b/py/tests/kmsmodeview.py index 355db02..0372d0a 100755 --- a/py/tests/kmsmodeview.py +++ b/py/tests/kmsmodeview.py @@ -293,8 +293,11 @@ def mode_to_str(mode): mode_buttons = [] card = pykms.Card() -conn = card.get_first_connected_connector() -crtc = conn.get_current_crtc() + +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) +plane = res.reserve_generic_plane(crtc) modes = conn.get_modes() i = 0 for m in modes: diff --git a/py/tests/test.py b/py/tests/test.py index 83cf16a..3f9e205 100755 --- a/py/tests/test.py +++ b/py/tests/test.py @@ -28,7 +28,7 @@ else: origfb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); if args.dmabuf: - fb = pykms.ExtFramebuffer(card, origfb.width, origfb.height, origfb.format, + fb = pykms.DmabufFramebuffer(card, origfb.width, origfb.height, origfb.format, [origfb.fd(0)], [origfb.stride(0)], [origfb.offset(0)]) else: fb = origfb diff --git a/py/tests/testmodes.py b/py/tests/testmodes.py new file mode 100755 index 0000000..0508f31 --- /dev/null +++ b/py/tests/testmodes.py @@ -0,0 +1,47 @@ +#!/usr/bin/python3 + +import sys +import pykms +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("-c", "--connector", default="") +args = parser.parse_args() + +card = pykms.Card() + +res = pykms.ResourceManager(card) +conn = res.reserve_connector(args.connector) +crtc = res.reserve_crtc(conn) +plane = res.reserve_generic_plane(crtc) + +card.disable_planes() + +modes = conn.get_modes() + +def even(i): + return i & ~1 + +for mode in modes: + long_str = mode.to_string_long() + short_str = mode.to_string_short() + + print(long_str) + + modeb = mode.to_blob(card) + + fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); + pykms.draw_test_pattern(fb); + pykms.draw_text(fb, even((fb.width // 2) - (8 * len(short_str)) // 2), 4, short_str, pykms.white) + + req = pykms.AtomicReq(card) + + req.add_connector(conn, crtc) + req.add_crtc(crtc, modeb) + req.add_plane(plane, fb, crtc, dst=(0, 0, mode.hdisplay, mode.vdisplay)) + + req.commit_sync(allow_modeset = True) + + input("press enter to show next videomode\n") + +print("done") diff --git a/utils/kmscapture.cpp b/utils/kmscapture.cpp index 01eac61..f215a65 100644 --- a/utils/kmscapture.cpp +++ b/utils/kmscapture.cpp @@ -38,7 +38,7 @@ public: int fd() const { return m_fd; } void start_streaming(); private: - ExtFramebuffer* GetExtFrameBuffer(Card& card, uint32_t i, PixelFormat pixfmt); + DmabufFramebuffer* GetDmabufFrameBuffer(Card& card, uint32_t i, PixelFormat pixfmt); int m_fd; /* camera file descriptor */ Crtc* m_crtc; Plane* m_plane; @@ -68,7 +68,7 @@ static int buffer_export(int v4lfd, enum v4l2_buf_type bt, uint32_t index, int * return 0; } -ExtFramebuffer* CameraPipeline::GetExtFrameBuffer(Card& card, uint32_t i, PixelFormat pixfmt) +DmabufFramebuffer* CameraPipeline::GetDmabufFrameBuffer(Card& card, uint32_t i, PixelFormat pixfmt) { int r, dmafd; @@ -82,7 +82,7 @@ ExtFramebuffer* CameraPipeline::GetExtFrameBuffer(Card& card, uint32_t i, PixelF vector<uint32_t> pitches { m_in_width * (format_info.planes[0].bitspp / 8) }; vector<uint32_t> offsets { 0 }; - return new ExtFramebuffer(card, m_in_width, m_in_height, pixfmt, + return new DmabufFramebuffer(card, m_in_width, m_in_height, pixfmt, fds, pitches, offsets); } @@ -173,7 +173,7 @@ CameraPipeline::CameraPipeline(int cam_fd, Card& card, Crtc *crtc, Plane* plane, Framebuffer *fb; if (m_buffer_provider == BufferProvider::V4L2) - fb = GetExtFrameBuffer(card, i, pixfmt); + fb = GetDmabufFrameBuffer(card, i, pixfmt); else fb = new DumbFramebuffer(card, m_in_width, m_in_height, pixfmt); diff --git a/utils/kmsprint.cpp b/utils/kmsprint.cpp index 116fead..61baec0 100644 --- a/utils/kmsprint.cpp +++ b/utils/kmsprint.cpp @@ -4,6 +4,7 @@ #include <iostream> #include <string> #include <unistd.h> +#include <fmt/format.h> #include <kms++/kms++.h> #include <kms++util/kms++util.h> @@ -22,11 +23,11 @@ static string format_mode(const Videomode& m, unsigned idx) { string str; - str = sformat(" %2u ", idx); + str = fmt::format(" {:2} ", idx); if (s_opts.x_modeline) { - str += sformat("%12s %6u %4u %4u %4u %4u %4u %4u %4u %4u %2u %#x %#x", - m.name.c_str(), + str += fmt::format("{:12} {:6} {:4} {:4} {:4} {:4} {:4} {:4} {:4} {:4} {:3} {:#x} {:#x}", + m.name, m.clock, m.hdisplay, m.hsync_start, m.hsync_end, m.htotal, m.vdisplay, m.vsync_start, m.vsync_end, m.vtotal, @@ -34,16 +35,7 @@ static string format_mode(const Videomode& m, unsigned idx) m.flags, m.type); } else { - string h = sformat("%u/%u/%u/%u", m.hdisplay, m.hfp(), m.hsw(), m.hbp()); - string v = sformat("%u/%u/%u/%u", m.vdisplay, m.vfp(), m.vsw(), m.vbp()); - - str += sformat("%-12s %7.3f %-16s %-16s %2u (%.2f) %#10x %#6x", - m.name.c_str(), - m.clock / 1000.0, - h.c_str(), v.c_str(), - m.vrefresh, m.calculated_vrefresh(), - m.flags, - m.type); + str += m.to_string_long_padded(); } return str; @@ -51,13 +43,13 @@ static string format_mode(const Videomode& m, unsigned idx) static string format_mode_short(const Videomode& m) { - string h = sformat("%u/%u/%u/%u", m.hdisplay, m.hfp(), m.hsw(), m.hbp()); - string v = sformat("%u/%u/%u/%u", m.vdisplay, m.vfp(), m.vsw(), m.vbp()); + string h = fmt::format("{}/{}/{}/{}", m.hdisplay, m.hfp(), m.hsw(), m.hbp()); + string v = fmt::format("{}/{}/{}/{}", m.vdisplay, m.vfp(), m.vsw(), m.vbp()); - return sformat("%s %.3f %s %s %u (%.2f)", - m.name.c_str(), + return fmt::format("{} {:.3f} {} {} {} ({:.2f})", + m.name, m.clock / 1000.0, - h.c_str(), v.c_str(), + h, v, m.vrefresh, m.calculated_vrefresh()); } @@ -65,8 +57,8 @@ static string format_connector(Connector& c) { string str; - str = sformat("Connector %u (%u) %s", - c.idx(), c.id(), c.fullname().c_str()); + str = fmt::format("Connector {} ({}) {}", + c.idx(), c.id(), c.fullname()); switch (c.connector_status()) { case ConnectorStatus::Connected: @@ -85,15 +77,15 @@ static string format_connector(Connector& c) static string format_encoder(Encoder& e) { - return sformat("Encoder %u (%u) %s", - e.idx(), e.id(), e.get_encoder_type().c_str()); + return fmt::format("Encoder {} ({}) {}", + e.idx(), e.id(), e.get_encoder_type()); } static string format_crtc(Crtc& c) { string str; - str = sformat("Crtc %u (%u)", c.idx(), c.id()); + str = fmt::format("Crtc {} ({})", c.idx(), c.id()); if (c.mode_valid()) str += " " + format_mode_short(c.mode()); @@ -105,17 +97,17 @@ static string format_plane(Plane& p) { string str; - str = sformat("Plane %u (%u)", p.idx(), p.id()); + str = fmt::format("Plane {} ({})", p.idx(), p.id()); if (p.fb_id()) - str += sformat(" fb-id: %u", p.fb_id()); + str += fmt::format(" fb-id: {}", p.fb_id()); string crtcs = join<Crtc*>(p.get_possible_crtcs(), " ", [](Crtc* crtc) { return to_string(crtc->idx()); }); - str += sformat(" (crtcs: %s)", crtcs.c_str()); + str += fmt::format(" (crtcs: {})", crtcs); if (p.card().has_atomic()) { - str += sformat(" %u,%u %ux%u -> %u,%u %ux%u", + str += fmt::format(" {},{} {}x{} -> {},{} {}x{}", (uint32_t)p.get_prop_value("SRC_X") >> 16, (uint32_t)p.get_prop_value("SRC_Y") >> 16, (uint32_t)p.get_prop_value("SRC_W") >> 16, @@ -128,20 +120,20 @@ static string format_plane(Plane& p) string fmts = join<PixelFormat>(p.get_formats(), " ", [](PixelFormat fmt) { return PixelFormatToFourCC(fmt); }); - str += sformat(" (%s)", fmts.c_str()); + str += fmt::format(" ({})", fmts); return str; } static string format_fb(Framebuffer& fb) { - return sformat("FB %u %ux%u", + return fmt::format("FB {} {}x{}", fb.id(), fb.width(), fb.height()); } static string format_property(const Property* prop, uint64_t val) { - string ret = sformat("%s (%u) = ", prop->name().c_str(), prop->id()); + string ret = fmt::format("{} ({}) = ", prop->name(), prop->id()); switch (prop->type()) { case PropertyType::Bitmask: @@ -151,10 +143,11 @@ static string format_property(const Property* prop, uint64_t val) for (auto kvp : prop->get_enums()) { if (val & (1 << kvp.first)) v.push_back(kvp.second); - vall.push_back(sformat("%s=0x%x", kvp.second.c_str(), 1 << kvp.first)); + vall.push_back(fmt::format("{}={:#x}", kvp.second, 1 << kvp.first)); } - ret += sformat("0x%" PRIx64 " (%s) [%s]", val, join(v, "|").c_str(), join(vall, "|").c_str()); + // XXX + ret += fmt::format("{:#x} ({}) [{}]", val, join(v, "|"), join(vall, "|")); break; } @@ -167,9 +160,9 @@ static string format_property(const Property* prop, uint64_t val) Blob blob(prop->card(), blob_id); auto data = blob.data(); - ret += sformat("blob-id %u len %zu", blob_id, data.size()); + ret += fmt::format("blob-id {} len {}", blob_id, data.size()); } else { - ret += sformat("blob-id %u", blob_id); + ret += fmt::format("blob-id {}", blob_id); } break; @@ -183,17 +176,17 @@ static string format_property(const Property* prop, uint64_t val) for (auto kvp : prop->get_enums()) { if (val == kvp.first) cur = kvp.second; - vall.push_back(sformat("%s=%" PRIu64, kvp.second.c_str(), kvp.first)); + vall.push_back(fmt::format("{}={}", kvp.second, kvp.first)); } - ret += sformat("%" PRIu64 " (%s) [%s]", val, cur.c_str(), join(vall, "|").c_str()); + ret += fmt::format("{} ({}) [{}]", val, cur, join(vall, "|")); break; } case PropertyType::Object: { - ret += sformat("object id %u", (uint32_t)val); + ret += fmt::format("object id {}", val); break; } @@ -201,7 +194,7 @@ static string format_property(const Property* prop, uint64_t val) { auto values = prop->get_values(); - ret += sformat("%" PRIu64 " [%" PRIu64 " - %" PRIu64 "]", + ret += fmt::format("{} [{} - {}]", val, values[0], values[1]); break; @@ -211,7 +204,7 @@ static string format_property(const Property* prop, uint64_t val) { auto values = prop->get_values(); - ret += sformat("%" PRIi64 " [%" PRIi64 " - %" PRIi64 "]", + ret += fmt::format("{} [{} - {}]", (int64_t)val, (int64_t)values[0], (int64_t)values[1]); break; @@ -317,14 +310,16 @@ static const map<TreeGlyph, string> glyphs_ascii = { }; -const char* get_glyph(TreeGlyph glyph) +const string& get_glyph(TreeGlyph glyph) { + static const string s_empty = " "; + if (s_glyph_mode == TreeGlyphMode::None) - return " "; + return s_empty; const map<TreeGlyph, string>& glyphs = s_glyph_mode == TreeGlyphMode::UTF8 ? glyphs_utf8 : glyphs_ascii; - return glyphs.at(glyph).c_str(); + return glyphs.at(glyph); } static void print_entry(const Entry& e, const string& prefix, bool is_child, bool is_last) @@ -337,7 +332,7 @@ static void print_entry(const Entry& e, const string& prefix, bool is_child, boo prefix2 = prefix + (is_last ? get_glyph(TreeGlyph::Space) : get_glyph(TreeGlyph::Vertical)); } - printf("%s%s\n", prefix1.c_str(), e.title.c_str()); + fmt::print("{}{}\n", prefix1, e.title); bool has_children = e.children.size() > 0; @@ -345,7 +340,7 @@ static void print_entry(const Entry& e, const string& prefix, bool is_child, boo for (const string& str : e.lines) { string p = data_prefix + get_glyph(TreeGlyph::Space); - printf("%s%s\n", p.c_str(), str.c_str()); + fmt::print("{}{}\n", p, str); } for (const Entry& child : e.children) { @@ -399,16 +394,16 @@ static void print_as_list(Card& card) } for (DrmPropObject* ob: obs) { - printf("%s\n", format_ob(ob).c_str()); + fmt::print("{}\n", format_ob(ob)); if (s_opts.print_props) { for (string str : format_props(ob)) - printf(" %s\n", str.c_str()); + fmt::print(" {}\n", str); } } for (Framebuffer* fb: fbs) { - printf("%s\n", format_ob(fb).c_str()); + fmt::print("{}\n", format_ob(fb)); } } @@ -473,11 +468,11 @@ static void print_modes(Card& card) if (!conn->connected()) continue; - printf("%s\n", format_ob(conn).c_str()); + fmt::print("{}\n", format_ob(conn)); auto modes = conn->get_modes(); for (unsigned i = 0; i < modes.size(); ++i) - printf("%s\n", format_mode(modes[i], i).c_str()); + fmt::print("{}\n", format_mode(modes[i], i)); } } diff --git a/utils/kmstest.cpp b/utils/kmstest.cpp index 8144117..938268d 100644 --- a/utils/kmstest.cpp +++ b/utils/kmstest.cpp @@ -9,6 +9,8 @@ #include <sys/select.h> +#include <fmt/format.h> + #include <kms++/kms++.h> #include <kms++/modedb.h> #include <kms++/mode_cvt.h> @@ -74,7 +76,7 @@ static void print_regex_match(smatch sm) { for (unsigned i = 0; i < sm.size(); ++i) { string str = sm[i].str(); - printf("%u: %s\n", i, str.c_str()); + fmt::print("{}: {}\n", i, str); } } @@ -691,69 +693,40 @@ static vector<OutputInfo> setups_to_outputs(Card& card, ResourceManager& resman, return outputs; } -static char sync_to_char(SyncPolarity pol) -{ - switch (pol) { - case SyncPolarity::Positive: - return '+'; - case SyncPolarity::Negative: - return '-'; - default: - return '?'; - } -} - -static std::string videomode_to_string(const Videomode& m) -{ - string h = sformat("%u/%u/%u/%u/%c", m.hdisplay, m.hfp(), m.hsw(), m.hbp(), sync_to_char(m.hsync())); - string v = sformat("%u/%u/%u/%u/%c", m.vdisplay, m.vfp(), m.vsw(), m.vbp(), sync_to_char(m.vsync())); - - return sformat("%s %.3f %s %s %u (%.2f) %#x %#x", - m.name.c_str(), - m.clock / 1000.0, - h.c_str(), v.c_str(), - m.vrefresh, m.calculated_vrefresh(), - m.flags, - m.type); -} - static void print_outputs(const vector<OutputInfo>& outputs) { for (unsigned i = 0; i < outputs.size(); ++i) { const OutputInfo& o = outputs[i]; - printf("Connector %u/@%u: %s", o.connector->idx(), o.connector->id(), - o.connector->fullname().c_str()); + fmt::print("Connector {}/@{}: {}", o.connector->idx(), o.connector->id(), + o.connector->fullname()); for (const PropInfo &prop: o.conn_props) - printf(" %s=%" PRIu64, prop.prop->name().c_str(), - prop.val); + fmt::print(" {}={}", prop.prop->name(), prop.val); - printf("\n Crtc %u/@%u", o.crtc->idx(), o.crtc->id()); + fmt::print("\n Crtc {}/@{}", o.crtc->idx(), o.crtc->id()); for (const PropInfo &prop: o.crtc_props) - printf(" %s=%" PRIu64, prop.prop->name().c_str(), - prop.val); + fmt::print(" {}={}", prop.prop->name(), prop.val); - printf(": %s\n", videomode_to_string(o.mode).c_str()); + fmt::print(": {}\n", o.mode.to_string_long()); if (!o.legacy_fbs.empty()) { auto fb = o.legacy_fbs[0]; - printf(" Fb %u %ux%u-%s\n", fb->id(), fb->width(), fb->height(), PixelFormatToFourCC(fb->format()).c_str()); + fmt::print(" Fb {} {}x{}-{}\n", fb->id(), fb->width(), fb->height(), PixelFormatToFourCC(fb->format())); } for (unsigned j = 0; j < o.planes.size(); ++j) { const PlaneInfo& p = o.planes[j]; auto fb = p.fbs[0]; - printf(" Plane %u/@%u: %u,%u-%ux%u", p.plane->idx(), p.plane->id(), - p.x, p.y, p.w, p.h); + fmt::print(" Plane {}/@{}: {},{}-{}x{}", p.plane->idx(), p.plane->id(), + p.x, p.y, p.w, p.h); for (const PropInfo &prop: p.props) - printf(" %s=%" PRIu64, prop.prop->name().c_str(), - prop.val); - printf("\n"); + fmt::print(" {}={}", prop.prop->name(), prop.val); + fmt::print("\n"); - printf(" Fb %u %ux%u-%s\n", fb->id(), fb->width(), fb->height(), - PixelFormatToFourCC(fb->format()).c_str()); + fmt::print(" Fb {} {}x{}-{}\n", fb->id(), fb->width(), fb->height(), + PixelFormatToFourCC(fb->format())); } } } @@ -799,8 +772,8 @@ static void set_crtcs_n_planes_legacy(Card& card, const vector<OutputInfo>& outp auto fb = o.legacy_fbs[0]; r = crtc->set_mode(conn, *fb, o.mode); if (r) - printf("crtc->set_mode() failed for crtc %u: %s\n", - crtc->id(), strerror(-r)); + fmt::print(stderr, "crtc->set_mode() failed for crtc {}: {}\n", + crtc->id(), strerror(-r)); } for (const PlaneInfo& p : o.planes) { @@ -814,8 +787,8 @@ static void set_crtcs_n_planes_legacy(Card& card, const vector<OutputInfo>& outp p.x, p.y, p.w, p.h, 0, 0, fb->width(), fb->height()); if (r) - printf("crtc->set_plane() failed for plane %u: %s\n", - p.plane->id(), strerror(-r)); + fmt::print(stderr, "crtc->set_plane() failed for plane {}: {}\n", + p.plane->id(), strerror(-r)); } } } @@ -957,10 +930,10 @@ private: if (m_frame_num % 100 == 0) { std::chrono::duration<float> fsec = now - m_prev_print; - printf("Connector %s: fps %f, slowest %.2f ms\n", - m_name.c_str(), - 100.0 / fsec.count(), - m_slowest_frame.count() * 1000); + fmt::print("Connector {}: fps {:.2f}, slowest {:.2f} ms\n", + m_name.c_str(), + 100.0 / fsec.count(), + m_slowest_frame.count() * 1000); m_prev_print = now; m_slowest_frame = std::chrono::duration<float>::min(); } @@ -1096,10 +1069,10 @@ static void main_flip(Card& card, const vector<OutputInfo>& outputs) r = select(fd + 1, &fds, NULL, NULL, NULL); if (r < 0) { - fprintf(stderr, "select() failed with %d: %m\n", errno); + fmt::print(stderr, "select() failed with {}: {}\n", errno, strerror(errno)); break; } else if (FD_ISSET(0, &fds)) { - fprintf(stderr, "Exit due to user-input\n"); + fmt::print(stderr, "Exit due to user-input\n"); break; } else if (FD_ISSET(fd, &fds)) { card.call_page_flip_handlers(); @@ -1130,7 +1103,7 @@ int main(int argc, char **argv) set_crtcs_n_planes(card, outputs); - printf("press enter to exit\n"); + fmt::print("press enter to exit\n"); if (s_flip_mode) main_flip(card, outputs); diff --git a/utils/wbcap.cpp b/utils/wbcap.cpp index 5a94a70..886fe36 100644 --- a/utils/wbcap.cpp +++ b/utils/wbcap.cpp @@ -342,9 +342,9 @@ int main(int argc, char** argv) if (src_mode.interlace()) dst_height /= 2; - printf("src %s, crtc %s\n", src_conn->fullname().c_str(), src_mode.to_string().c_str()); + printf("src %s, crtc %s\n", src_conn->fullname().c_str(), src_mode.to_string_short().c_str()); - printf("dst %s, crtc %s\n", dst_conn->fullname().c_str(), dst_mode.to_string().c_str()); + printf("dst %s, crtc %s\n", dst_conn->fullname().c_str(), dst_mode.to_string_short().c_str()); printf("src_fb %ux%u, dst_fb %ux%u\n", src_width, src_height, dst_width, dst_height); diff --git a/utils/wbm2m.cpp b/utils/wbm2m.cpp index b69bb28..71a26a5 100644 --- a/utils/wbm2m.cpp +++ b/utils/wbm2m.cpp @@ -6,6 +6,7 @@ #include <fstream> #include <map> #include <system_error> +#include <fmt/format.h> #include <kms++/kms++.h> #include <kms++util/kms++util.h> @@ -101,8 +102,13 @@ int main(int argc, char** argv) exit(-1); } - const string filename = sformat("wb-out-%ux%u_%4.4s.raw", dst_width, dst_height, - PixelFormatToFourCC(dst_fmt).c_str()); + printf("%ux%u-%s -> %ux%u-%s\n", src_width, src_height, PixelFormatToFourCC(src_fmt).c_str(), + dst_width, dst_height, PixelFormatToFourCC(dst_fmt).c_str()); + + const string filename = fmt::format("wb-out-{}x{}-{}.raw", dst_width, dst_height, + PixelFormatToFourCC(dst_fmt)); + + printf("writing to %s\n", filename.c_str()); VideoDevice vid("/dev/video10"); |