aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2020-04-01 14:42:37 -0700
committerHaibo Huang <hhb@google.com>2020-04-03 22:38:58 +0000
commit57240f80a21f4f7d9c6ceedf61549e0adf2c95b2 (patch)
treed2106d3321762d3b10ad49d3b4e93d1bbec254a0
parent6f7131a65dbe7d76eecc21643b51b50bae352c6a (diff)
parentcff8b2fd797537e36d5e16c1ac8e3303321e50b2 (diff)
downloadlibkmsxx-57240f80a21f4f7d9c6ceedf61549e0adf2c95b2.tar.gz
Upgrade libkmsxx to cff8b2fd797537e36d5e16c1ac8e3303321e50b2
Exempt-From-Owner-Approval: upgrade Change-Id: I6c7aae30d8ba09e05d47b03b55c58ac782097742
-rw-r--r--.gitmodules3
-rw-r--r--.travis.yml60
-rw-r--r--Android.bp25
-rw-r--r--CMakeLists.txt12
-rw-r--r--METADATA8
-rw-r--r--README.md15
m---------ext/fmt0
-rw-r--r--kms++/CMakeLists.txt12
-rw-r--r--kms++/inc/kms++/blob.h2
-rw-r--r--kms++/inc/kms++/card.h32
-rw-r--r--kms++/inc/kms++/connector.h4
-rw-r--r--kms++/inc/kms++/crtc.h4
-rw-r--r--kms++/inc/kms++/decls.h1
-rw-r--r--kms++/inc/kms++/dmabufframebuffer.h52
-rw-r--r--kms++/inc/kms++/drmpropobject.h2
-rw-r--r--kms++/inc/kms++/dumbframebuffer.h27
-rw-r--r--kms++/inc/kms++/encoder.h2
-rw-r--r--kms++/inc/kms++/extframebuffer.h29
-rw-r--r--kms++/inc/kms++/framebuffer.h16
-rw-r--r--kms++/inc/kms++/kms++.h1
-rw-r--r--kms++/inc/kms++/pixelformats.h8
-rw-r--r--kms++/inc/kms++/plane.h2
-rw-r--r--kms++/inc/kms++/property.h2
-rw-r--r--kms++/inc/kms++/videomode.h4
-rw-r--r--kms++/kms++.pc.in10
-rw-r--r--kms++/src/card.cpp18
-rw-r--r--kms++/src/connector.cpp2
-rw-r--r--kms++/src/crtc.cpp2
-rw-r--r--kms++/src/dmabufframebuffer.cpp145
-rw-r--r--kms++/src/drmobject.cpp2
-rw-r--r--kms++/src/drmpropobject.cpp2
-rw-r--r--kms++/src/dumbframebuffer.cpp36
-rw-r--r--kms++/src/encoder.cpp2
-rw-r--r--kms++/src/extframebuffer.cpp83
-rw-r--r--kms++/src/plane.cpp2
-rw-r--r--kms++/src/videomode.cpp56
-rw-r--r--kms++util/CMakeLists.txt10
-rw-r--r--kms++util/inc/kms++util/strhelpers.h3
-rw-r--r--kms++util/kms++util.pc.in11
-rw-r--r--kms++util/src/cpuframebuffer.cpp2
-rw-r--r--kms++util/src/strhelpers.cpp14
-rw-r--r--kms++util/src/videodevice.cpp28
-rw-r--r--py/pykms/pykmsbase.cpp19
-rwxr-xr-xpy/tests/alpha-test.py48
-rwxr-xr-xpy/tests/ctm_test.py59
-rwxr-xr-xpy/tests/global_alpha_test.py25
-rwxr-xr-xpy/tests/hpd.py10
-rwxr-xr-xpy/tests/kmsmodeview.py7
-rwxr-xr-xpy/tests/test.py2
-rwxr-xr-xpy/tests/testmodes.py47
-rw-r--r--utils/kmscapture.cpp8
-rw-r--r--utils/kmsprint.cpp93
-rw-r--r--utils/kmstest.cpp81
-rw-r--r--utils/wbcap.cpp4
-rw-r--r--utils/wbm2m.cpp10
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:
diff --git a/Android.bp b/Android.bp
index e62650e..100ff92 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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()
diff --git a/METADATA b/METADATA
index e098fe8..d219292 100644
--- a/METADATA
+++ b/METADATA
@@ -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
}
}
diff --git a/README.md b/README.md
index feb43d7..4e402f8 100644
--- a/README.md
+++ b/README.md
@@ -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");